     1                                  
     2                                  %if 0
     3                                  
     4                                  lDOS iniload packed payload
     5                                   by E. C. Masloch, 2018-2020
     6                                  
     7                                  Usage of the works is permitted provided that this
     8                                  instrument is retained with the works, so that any entity
     9                                  that uses the works is notified of this instrument.
    10                                  
    11                                  DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                                  
    13                                  
    14                                  Includes one of several depackers, some of which are under
    15                                  separate usage conditions. Refer to the individual depacker
    16                                  source files for the applicable usage conditions.
    17                                  
    18                                  %endif
    19                                  
    20                                  %include "lmacros3.mac"
     1                              <1> [list -]
    14                              <2> [list -]
    14                              <1> [list -]
    21                                  
    22                                  	struc LOADSTACKVARS, -10h
    23 FFFFFFF0 ????????                lsvFirstCluster:	resd 1
    24 FFFFFFF4 ????????                lsvFATSector:		resd 1
    25 FFFFFFF8 ????                    lsvFATSeg:		resw 1
    26 FFFFFFFA ????                    lsvLoadSeg:		resw 1
    27 FFFFFFFC ????????                lsvDataStart:		resd 1
    28                                  	endstruc
    29                                  
    30                                  	struc LOADDATA, LOADSTACKVARS - 10h
    31 FFFFFFE0 ????                    ldMemoryTop:	resw 1
    32 FFFFFFE2 ????                    ldLoadTop:	resw 1
    33 FFFFFFE4 ????                    ldSectorSeg:	resw 1
    34 FFFFFFE6 ??                      ldFATType:	resb 1
    35 FFFFFFE7 ??                      ldHasLBA:	resb 1
    36 FFFFFFE8 ????                    ldClusterSize:	resw 1
    37 FFFFFFEA ????                    ldParaPerSector:resw 1
    38 FFFFFFEC ????                    ldLoadingSeg:	resw 1
    39 FFFFFFEE ????                    ldLoadUntilSeg:	resw 1
    40                                  	endstruc
    41                                  
    42                                  
    43                                  %ifndef _MAP
    44                                  %elifempty _MAP
    45                                  %else	; defined non-empty, str or non-str
    46                                  	[map all _MAP]
    47                                  %endif
    48                                  
    49                                  	defaulting
    50                                  
    51                                  	numdef DEBUG0		; use errordata to generate an error code
    52                                  	numdef DEBUG1		; dump_stack_frame after an error occurred
    53                                  	numdef DEBUG2		; dump_stack_frame before blz_depack_safe call
    54                                  	numdef DEBUG3		; dump_stack_frame at start of blz_depack_safe
    55                                  
    56                                  	numdef OPTIMISE_INPUT_SMALL,	0
    57                                  	numdef OPTIMISE_OUYPUT_SMALL,	0
    58                                  	numdef ALLOW_OVERLAPPING,	1	; allow overlapping src and dst
    59                                  	numdef TEST_PROGRAM,		0
    60                                  	numdef TEST_PROGRAM_DECOMPRESSED_SIZE,		0,0
    61                                  %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE
    62                                   %error Test program has to learn of decompressed size.
    63                                  %endif
    64                                  	numdef TEST_PROGRESS,	0
    65                                  
    66                                  	numdef INCLUDE_UNCOMPRESSED
    67                                  	numdef INCLUDE_UNCOMPRESSED_IN_IMAGE, 1
    68                                  	numdef WRITE_WRONG_FILE
    69                                  	numdef RELOAD_XMS, 0
    70                                  	numdef RELOAD_FILE, 0
    71                                  
    72                                  	numdef EXEC_OFFSET,	0
    73                                  	numdef EXEC_SEGMENT,	0
    74                                  	numdef IMAGE_EXE,	0
    75                                  %if ! _IMAGE_EXE && _TEST_PROGRAM
    76                                   %error Test program can only be used as EXE.
    77                                  %endif
    78                                  	numdef IMAGE_EXE_CS,	-16	; relative-segment for CS
    79                                  	numdef IMAGE_EXE_IP,	256 +64	; value for IP
    80                                  		; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0.
    81                                  	numdef IMAGE_EXE_SS,	-16	; relative-segment for SS
    82                                  	numdef IMAGE_EXE_SP,	0FFFEh	; value for SP (0 underflows)
    83                                  	numdef IMAGE_EXE_AUTO_STACK,	0, 2048	; use stack behind image
    84                                  		; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of
    85                                  		;  the same name. This one is only used as a flag; if non-zero,
    86                                  		;  keep the stack given to us by iniload; if zero, set up the
    87                                  		;  stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP.
    88                                  	numdef IMAGE_EXE_GET_COM_STACK, 0
    89                                  					; set up stack for flat .COM style entry
    90                                  	numdef DEVICE,			0
    91                                  	gendef DEVICE_NAME,		""
    92                                  	numdef DEVICE_ATTRIBUTE,	8000h
    93                                  	numdef DEVICE_ZERO_ENTRYPOINT,	0
    94                                  	numdef BOOTLDR,		1	; support boot loaded entrypoint
    95                                  
    96                                  	numdef BRIEFLZ,		0
    97                                  	numdef LZ4,		0
    98                                  	numdef SNAPPY,		0
    99                                  	numdef EXODECR,		0
   100                                  	numdef X,		0
   101                                  	numdef HEATSHRINK,	0
   102                                  	numdef LZD,		0
   103                                  	numdef LZO,		0
   104                                  	numdef LZSA2,		0
   105                                  	numdef APL,		0
   106                                  	numdef BZP,		0
   107                                  	numdef ZEROCOMP,	0
   108                                  	numdef MVCOMP,		0
   109                                  	numdef LZEXEDAT,	0
   110                                  %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK 	+ !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP 	+ !!_MVCOMP + !!_LZEXEDAT) != 1
   113                                   %fatal Exactly one compression method must be selected.
   114                                  %endif
   115                                  %assign ADDITIONAL_MEMORY 0
   116                                  %if _BRIEFLZ
   117                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BLZ"
   118                                  %elif _LZ4
   119                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ4"
   120                                  %elif _SNAPPY
   121                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SZ"
   122                                  %elif _EXODECR
   123                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.EXO"
   124                                  %elif _X
   125                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.X"
   126                                  %elif _HEATSHRINK
   127                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.HS"
   128                                  %elif _LZD
   129                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ"
   130                                  %elif _LZO
   131                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZO"
   132                                  %elif _LZSA2
   133                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SA2"
   134                                  %elif _APL
   135                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.APL"
   136                                  %elif _BZP
   137                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BZP"
   138                                  %elif _ZEROCOMP
   139                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.ZER"
   140                                  %elif _MVCOMP
   141                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.MV"
   142                                  %elif _LZEXEDAT
   143                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZE"
   144                                  %endif
   145                                  	numdef PAYLOAD_KERNEL_MAX_PARAS,	0, 0
   146                                  %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE)
   147                                   %error Kernel mode max paras requires building dual-mode or triple-mode executable
   148                                  %endif
   149                                  	numdef COUNTER,		0, 32
   150                                  %if (_COUNTER - 1) & _COUNTER
   151                                   %error COUNTER must be a power of two
   152                                  %endif
   153                                  	numdef PROGRESS,	0, 1
   154                                  	numdef PROGRESSAMOUNT,	0, 0
   155                                  	numdef PROGRESSMULTI,	1
   156                                  	numdef PROGRESSVAR,	1
   157                                  	numdef PROGRESSVARNAME, ""
   158                                  	numdef PROGRESSDEFAULT,	0
   159                                  	numdef PROGRESSDEFAULTAPP,	_PROGRESSDEFAULT
   160                                  	numdef PROGRESSDEFAULTDEVICE,	_PROGRESSDEFAULT
   161                                  	numdef PROGRESSDEFAULTBOOT,1
   162                                  	numdef PASSLCFG, 0
   163                                  	numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG
   164                                  
   165                                  
   166                                  %define MODULE inicomp
   167                                  	strdef INILOAD_CFG, ""
   168                                  %ifnidn _INILOAD_CFG, ""
   169                                   %include _INILOAD_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> strdef INILOAD_SIGNATURE, "eb"
     3                              <1> %assign _DEVICE 1
     4                              <1> %assign _DEVICE_ZERO_ENTRYPOINT 1
     5                              <1> %assign _DEVICE_ATTRIBUTE 8800h
     6                              <1> %define _DEVICE_NAME "LDEBUG$$"
     7                              <1> %define _PROGRESSVARNAME "LDEBUGPROGRESS"
     8                              <1> %assign _LOADERSUPPORT 1
   170                                  %endif
   171                                  	strdef LCFG_CFG, ""
   172                                  
   173                                  %if _DEVICE
   174                                   %ifidn _DEVICE_NAME, ""
   175                                    %error Device name must be set
   176                                   %endif
   177                                  %endif
   178                                  
   179                                  	struc XMSM
   180 00000000 ????????                .size_:		resd 1
   181 00000004 ????                    .srchdl:	resw 1
   182 00000006 ????????                .srcadr:	resd 1
   183 0000000A ????                    .dsthdl:	resw 1
   184 0000000C ????????                .dstadr:	resd 1
   185                                  	endstruc
   186                                  
   187                                  
   188                                  	cpu 8086
   189                                  	addsection INIT0, start=0 vstart=0
   190                                  init0_start:
   191                                  %if _DEVICE
   192                                  		; The device header is of a fixed format.
   193                                  		;  For our purposes, the 4-byte code for
   194                                  		;  each the strategy entry and the
   195                                  		;  interrupt entry is part of this format.
   196                                  		; (DOS may read the attributes or entrypoint
   197                                  		;  offsets before calling either, so in the inicomp
   198                                  		;  stage we need to recreate in the entrypoints part
   199                                  		;  exactly what the application has here.)
   200                                  		; _PASSLCFG: The lCFG block is passed in the dword
   201                                  		;  behind the interrupt entry.
   202                                  device_header:
   203                                  .next:
   204                                   %if _DEVICE_ZERO_ENTRYPOINT
   205 00000000 EB3E                    	fill 2, -1, jmp strict short j_zero_entrypoint
   206 00000002 FFFF                    	dw -1
   207                                   %else
   208                                  	dd -1				; link to next device
   209                                   %endif
   210                                  .attributes:
   211 00000004 0088                    	dw _DEVICE_ATTRIBUTE		; attributes
   212                                  .strategy:
   213 00000006 [1200]                  	dw .strategy_entry		; -> strategy entry
   214                                  .interrupt:
   215 00000008 [1600]                  	dw .interrupt_entry		; -> interrupt entry
   216                                  .name:
   217 0000000A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME	; character device name,
   218                                  					;  or block device number of units
   219                                  					;  + optional name
   220                                  .strategy_entry:
   221 00000012 EB7C90<rep 2h>          	fill 4, 90h, jmp device_entrypoint
   222                                  .interrupt_entry:
   223 00000016 CB90<rep 3h>            	fill 4, 90h, retf
   224                                  .pass_lcfg:
   225                                  %endif
   226                                  
   227                                  
   228                                  %if _IMAGE_EXE || _DEVICE
   229 0000001A 90                      	nop
   230 0000001B 90<rep 5h>              	align 32, nop
   231                                  init0_kernel_entry:
   232                                  		; cs:ip = load seg : 32 here
   233                                  %if ($ - $$) != 32
   234                                   %error Wrong kernel mode entrypoint
   235                                  %endif
   236                                  %if _TEST_PROGRAM
   237                                  @@:
   238                                  	int3
   239                                  	sti
   240                                  	hlt
   241                                  	jmp @B
   242                                  %endif
   243                                  %if _BOOTLDR
   244                                  %if ! _IMAGE_EXE
   245                                  j_zero_entrypoint:
   246                                  %endif
   247 00000020 31DB                    	xor bx, bx		; 0 = kernel mode
   248 00000022 50                      	push ax
   249 00000023 8CC8                    	mov ax, cs
   250 00000025 83C01F                  	add ax, (init0_end - init0_start) >> 4
   251 00000028 8B56E2                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   252 0000002B BE6000                  	mov si, 60h		; => destination
   253 0000002E EB20                    	jmp init0_common
   254                                  %endif
   255                                  
   256                                   %if _IMAGE_EXE
   257 00000030 90<rep 10h>             	align 64, nop
   258                                  j_zero_entrypoint:
   259                                  init0_exe_entry:
   260                                  		; NOTE:	This part is called with ip = 256 + 64, cs = PSP.
   261                                  %if ($ - $$) != 64
   262                                   %error Wrong EXE mode entrypoint
   263                                  %endif
   264                                  %if _IMAGE_EXE_GET_COM_STACK
   265                                  	mov bx, ds		; => PSP
   266                                  	dec bx			; => MCB
   267                                  	mov ds, bx
   268                                  	add bx, word [3]	; add size of memory block
   269                                  	sub bx, -1 + paras(512)	; add one, then subtract enough paragraphs
   270                                  	cli
   271                                  	mov ss, bx
   272                                  	mov sp, 512		; -> new stack
   273                                  	sti
   274                                  %endif
   275 00000040 BB0100                  	mov bx, 1		; EXE mode
   276 00000043 50                      	push ax
   277                                    %if _TEST_PROGRAM
   278                                  %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE
   279                                  	push ds
   280                                  	mov ax, word [2Ch]	; => environment
   281                                  	test ax, ax
   282                                  	jnz @F
   283                                  .errorfile:
   284                                  	jmp init0_error_file
   285                                  @@:
   286                                  	mov ds, ax
   287                                  	mov cx, 8000h
   288                                  	xor si, si		; -> environment
   289                                  @@:
   290                                  	lodsb
   291                                  	test al, al
   292                                  	loopnz @B		; si -> past one NUL
   293                                  	jcxz .errorfile
   294                                  	cmp byte [si], 0	; -> another NUL ?
   295                                  	loopne @B		; no, skip next variable -->
   296                                  	jcxz .errorfile
   297                                  	inc si			; skip double NUL
   298                                  	lodsw			; load amount strings after environment
   299                                  	cmp ax, 1		; 1 ?
   300                                  	jne .errorfile		; no -->
   301                                  	mov dx, si		; ds:dx -> executable pathname
   302                                  	mov ax, 3D00h + 0_010_0_000b	; deny write, read only
   303                                  	int 21h			; open
   304                                  	jc .errorfile
   305                                  	pop ds			; restore => PSP
   306                                  	push ax			; push into ?handle
   307                                  %endif
   308                                  
   309                                  	mov si, 81h
   310                                  	xor dx, dx
   311                                  	xor ax, ax
   312                                  cmdline:
   313                                  .:
   314                                  	lodsb
   315                                  	cmp al, 9
   316                                  	je .
   317                                  	cmp al, 32
   318                                  	je .
   319                                  	cmp al, 13
   320                                  	je .end
   321                                  	cmp al, '0'
   322                                  	jb .notdigit
   323                                  	cmp al, '9'
   324                                  	ja .notdigit
   325                                  .digit:
   326                                  	sub al, '0'
   327                                  	mov cx, dx		; times 1
   328                                  	add dx, dx
   329                                  	jc .invalid
   330                                  	add dx, dx		; times 4
   331                                  	jc .invalid
   332                                  	add dx, cx		; times 5
   333                                  	jc .invalid
   334                                  	add dx, dx		; times 10
   335                                  	jc .invalid
   336                                  	add dx, ax		; add in low digit
   337                                  	jc .invalid
   338                                  	jmp .
   339                                  
   340                                  .notdigit:
   341                                  	cmp al, 'A'
   342                                  	je .a
   343                                  	cmp al, 'a'
   344                                  	je .a
   345                                  	cmp al, 'B'
   346                                  	je .b
   347                                  	cmp al, 'b'
   348                                  	je .b
   349                                  	cmp al, 'C'
   350                                  	je .c
   351                                  	cmp al, 'c'
   352                                  	je .c
   353                                  .invalid:
   354                                  	mov dx, -1		; invalid
   355                                  	jmp .end
   356                                  
   357                                  .a:
   358                                  	and bh, ~ 80h		; A mode. determine min alloc size
   359                                  	jmp .
   360                                  
   361                                  .b:
   362                                  	or bh, 80h		; B mode. repeat depack, counter in command line
   363                                  	jmp .
   364                                  
   365                                  .c:
   366                                  	or bh, 40h		; C mode. how often would the counter be called
   367                                  	jmp .
   368                                  
   369                                  .end:
   370                                  				; bx for ?whichtest
   371                                  	push dx			; for ?repetitions
   372                                    %endif
   373 00000044 8CD2                    	mov dx, ss		; => after end of available space
   374 00000046 8CC8                    	mov ax, cs
   375 00000048 83C02F                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   376 0000004B 8CCE                    	mov si, cs
   377 0000004D 83C610                  	add si, 256 >> 4	; => destination
   378                                   %endif
   379                                  
   380                                  init0_common:
   381                                  		; REM:	This part must be position-independent, as it is
   382                                  		;	 called either with ip = init0_common (kernel mode
   383                                  		;	 or device mode)
   384                                  		;	 or ip = init0_common + 256 (application mode).
   385                                  		; INP:	si => depack destination
   386                                  		;	ax => source of payload + INIT1
   387                                  		;	dx => behind available memory
   388                                  		; OUT:	cs:ip -> init1_start:
   389                                  		;	ax => INIT1
   390                                  		;	dx => payload source
   391                                  		;	si => depack destination
   392                                  		;	bx = mode
   393 00000050 FC                      	cld
   394                                  %if _TEST_PROGRAM
   395                                   %ifn _RELOAD_XMS || _RELOAD_FILE
   396                                  	sub dx, ( (payload_end - payload) ) >> 4
   397                                  	jc .error
   398                                   %endif
   399                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   405                                  	sub dx, cx
   406                                  	jc .error
   407                                  	cmp dx, ax
   408                                  	jb .error
   409                                  %else
   410 00000051 B99A18                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   415                                  				; cx = amount paragraphs in INIT0B + payload + INIT1
   416 00000054 29CA                    	sub dx, cx		; => destination for INIT0B + payload + INIT1
   417                                  				;  (highest possible spot in available memory)
   418                                  %endif
   419 00000056 56                      	push si			; preserve destination
   420 00000057 E80701                  	call init0_movp		; move up payload + INIT1
   421 0000005A 5E                      	pop si
   422                                  %else
   423                                  	cld
   424                                  	mov ax, cs
   425                                  	add ax, (init0_end - init0_start) >> 4
   426                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   431                                  	mov dx, word [ bp + ldLoadTop ]
   432                                  	sub dx, cx
   433                                  	call init0_movp
   434                                  %endif
   435                                  
   436                                  %if _LCFG && ! _TEST_PROGRAM
   437 0000005B 0E                      	push cs
   438 0000005C E80000                  	call @F			; position-independent far pointer
   439                                  @@:
   440 0000005F 58                      	pop ax
   441 00000060 83C011                  	add ax, lcfg - @B	; -> lCFG block
   442 00000063 50                      	push ax
   443                                  %endif
   444                                  
   445 00000064 89D0                    	mov ax, dx		; => INIT0B
   446                                  				;  (same as => payload if INIT0B is empty)
   447                                  %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM
   448 00000066 83C211                  	add dx, ( 		+ (init0b_end - init0b_start) 		) >> 4		; => payload
   451                                  %else
   452                                   %if _TEST_PROGRAM
   453                                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4		; => INIT2
   458                                   %else
   459                                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   463                                   %endif
   464                                  %endif
   465 00000069 31C9                    	xor cx, cx
   466 0000006B 50                      	push ax
   467 0000006C 51                      	push cx
   468 0000006D CB                      	retf			; jump to relocated
   469                                  				;  INIT0B:init0b_start
   470                                  				;  or INIT1:init1_start
   471                                  				;  or INIT2:init2_start
   472                                  
   473                                  
   474                                  %if _TEST_PROGRAM
   475                                  .error:
   476                                  	mov di, bx		; whichtest
   477                                  
   478                                  	push cs
   479                                  	pop ds
   480                                  	mov dx, init0_msg.error_stderr + 256
   481                                  	mov cx, init0_msg.error_stderr.length
   482                                  	mov bx, 2
   483                                  	mov ah, 40h
   484                                  	int 21h
   485                                  
   486                                  	test di, 4000h		; whichtest
   487                                  	jz @F
   488                                  	mov dx, init0_msg.error_c_stdout + 256
   489                                  	mov cx, init0_msg.error_c_stdout.length
   490                                  	jmp @FF
   491                                  @@:
   492                                  	test di, di		; whichtest
   493                                  	js @FF
   494                                  	mov dx, init0_msg.error_stdout + 256
   495                                  	mov cx, init0_msg.error_stdout.length
   496                                  @@:
   497                                  	mov bx, 1
   498                                  	mov ah, 40h
   499                                  	int 21h
   500                                  @@:
   501                                  	mov ax, 4CFFh
   502                                  	int 21h
   503                                  
   504                                  %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE
   505                                  init0_error_file:
   506                                  	mov dx, init0_msg.error_stderr_file + 256
   507                                  	mov cx, init0_msg.error_stderr_file.length
   508                                  	push cs
   509                                  	pop ds
   510                                  	mov bx, 2
   511                                  	mov ah, 40h
   512                                  	int 21h
   513                                  
   514                                  	mov dx, init0_msg.error_stdout + 256
   515                                  	mov cx, init0_msg.error_stdout.length
   516                                  	mov bx, 1
   517                                  	mov ah, 40h
   518                                  	int 21h
   519                                  	mov ax, 4CFFh
   520                                  	int 21h
   521                                  %endif
   522                                  
   523                                  %endif
   524                                  
   525                                  
   526                                  %if _LCFG
   527                                  	%imacro lcfgoption 3+.nolist
   528                                  	_fill %1, 0, lcfg
   529                                  %%start:
   530                                  	%2
   531                                  	%3
   532                                  %%end:
   533                                  %assign %%index %%start - lcfg
   534                                  %rep %%end - %%start
   535                                  %assign LCFGINUSE LCFGINUSE | (1 << %%index)
   536                                   %assign %%index %%index + 1
   537                                  %endrep
   538                                  	%endmacro
   539                                  %assign LCFGINUSE 0
   540                                  
   541 0000006E 90<rep 2h>              	align 16
   542                                  lcfg:
   543 00000070 EB1E                    .:		jmp strict short .end
   544 00000072 6C434647                lcfgoption 2,,	db "lCFG"
   545 00000076 3030                    lcfgoption 6,,	db "00"
   546 00000078 FCFF070000000000        lcfgoption 8,,	dq .inuse
   547                                   %if _PROGRESS && _PROGRESSMULTI
   548                                    %if _IMAGE_EXE
   549 00000080 00                      lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP
   550                                    %endif
   551                                    %if _DEVICE
   552 00000081 00                      lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE
   553                                    %endif
   554                                    %if _BOOTLDR
   555 00000082 01                      lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT
   556                                    %endif
   557                                   %endif
   558                                  
   559                                  %ifnidn _LCFG_CFG, ""
   560                                   %include _LCFG_CFG
   561                                  %endif
   562                                  
   563 00000083 00<rep Dh>              lcfgoption 32,,
   564                                  .end:
   565                                  .size: equ .end - .
   566                                  .inuse equ LCFGINUSE
   567                                  %endif
   568                                  
   569                                  
   570                                  %if _DEVICE
   571                                  device_entrypoint:
   572                                  %if _TEST_PROGRAM
   573                                  @@:
   574                                  	int3
   575                                  	sti
   576                                  	hlt
   577                                  	jmp @B
   578                                  %endif
   579 00000090 26807F0200              	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   580 00000095 7407                    	je @F
   581                                  
   582 00000097 26C747030381            	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   583 0000009D CB                      	retf
   584                                  
   585                                  @@:
   586 0000009E 2E830E[0000]FF          	or word [cs:device_header.next], -1
   587 000000A4 0E                      	push cs
   588 000000A5 2EFF36[0600]            	push word [cs:device_header.strategy]
   589                                  					; -> far return to payload's strategy
   590 000000AA 55                      	push bp
   591 000000AB 1E                      	push ds
   592 000000AC 56                      	push si
   593 000000AD 57                      	push di
   594 000000AE 52                      	push dx
   595 000000AF 51                      	push cx
   596 000000B0 50                      	push ax
   597 000000B1 53                      	push bx
   598 000000B2 06                      	push es
   599                                  
   600 000000B3 268B570E                	mov dx, word [es:bx + 14]
   601 000000B7 B104                    	mov cl, 4
   602 000000B9 D3EA                    	shr dx, cl		; = how many full paragraphs (rounded down)
   603 000000BB 26035710                	add dx, word [es:bx + 14 + 2]
   604                                  				; ax => behind end
   605                                  
   606 000000BF 8CCF                    	mov di, cs
   607                                  image_size: equ  ( 		+ (init0_end - init0_start) 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   613 000000C1 81C7B918                	add di, image_size >> 4		; di => end of image
   614                                  
   615 000000C5 39FA                    	cmp dx, di			; enough memory to hold all of us ?
   616 000000C7 720E                    	jb @F				; no -->
   617                                  				; yes
   618                                  .have_some_memory:
   619                                  				; dx => after end of memory
   620 000000C9 BB0200                  	mov bx, 2		; device mode
   621 000000CC 50                      	push ax
   622 000000CD 8CC8                    	mov ax, cs
   623 000000CF 83C01F                  	add ax, (init0_end - init0_start) >> 4
   624 000000D2 8CCE                    	mov si, cs		; => destination
   625 000000D4 E979FF                  	jmp init0_common
   626                                  
   627                                  
   628                                  @@:
   629 000000D7 0E                      	push cs
   630 000000D8 1F                      	pop ds
   631 000000D9 BA[1801]                	mov dx, .msg_no_memory
   632 000000DC B409                    	mov ah, 09h
   633 000000DE CD21                    	int 21h
   634                                  
   635 000000E0 B80030                  	mov ax, 3000h
   636 000000E3 CD21                    	int 21h
   637 000000E5 3C05                    	cmp al, 5
   638 000000E7 7307                    	jae @F
   639 000000E9 BA[3701]                	mov dx, .msg_dos_below_5
   640 000000EC B409                    	mov ah, 09h
   641 000000EE CD21                    	int 21h
   642                                  @@:
   643                                  
   644 000000F0 BA[5E01]                	mov dx, .msg_linebreak
   645 000000F3 B409                    	mov ah, 09h
   646 000000F5 CD21                    	int 21h
   647                                  
   648                                  		; tear down the stack frame and modify the request header
   649 000000F7 07                      	pop es
   650 000000F8 5B                      	pop bx
   651 000000F9 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   652 000000FF 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   653 00000104 268C4F10                	mov word [es:bx + 14 + 2], cs
   654 00000108 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   655 0000010D 58                      	pop ax
   656 0000010E 59                      	pop cx
   657 0000010F 5A                      	pop dx
   658 00000110 5F                      	pop di
   659 00000111 5E                      	pop si
   660 00000112 1F                      	pop ds
   661 00000113 5D                      	pop bp
   662 00000114 83C404                  	add sp, 4		; discard far return to payload's strategy
   663 00000117 CB                      	retf			; return to DOS
   664                                  
   665                                  
   666 00000118 4C6F6164206572726F-     .msg_no_memory:		ascic "Load error: Not enough memory."
   666 00000121 723A204E6F7420656E-
   666 0000012A 6F756768206D656D6F-
   666 00000133 72792E24           
   667 00000137 204E6F74653A20444F-     .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   667 00000140 53206D757374206265-
   667 00000149 206174206C65617374-
   667 00000152 2076657273696F6E20-
   667 0000015B 352E24             
   668 0000015E 0D0A24                  .msg_linebreak:		ascic 13,10
   669                                  %endif
   670                                  
   671                                  
   672                                  		; Move paragraphs
   673                                  		;
   674                                  		; INP:	ax => source
   675                                  		;	dx => destination
   676                                  		;	cx = number of paragraphs
   677                                  		; CHG:	cx, ds, si, es, di
   678                                  		; OUT:	ax and dx unchanged
   679                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   680                                  		;	Do not provide a wrapped/HMA source or destination!
   681                                  init0_movp:
   682 00000161 39D0                    	cmp ax, dx		; source above destination ?
   683 00000163 770A                    	ja .up			; yes, move up (forwards) -->
   684 00000165 747B                    	je .return		; same, no need to move -->
   685 00000167 50                      	push ax
   686 00000168 01C8                    	add ax, cx		; (expected not to carry)
   687 0000016A 39D0                    	cmp ax, dx		; end of source is above destination ?
   688 0000016C 58                      	pop ax
   689 0000016D 7730                    	ja .down		; yes, move from top down -->
   690                                  	; Here, the end of source is below-or-equal the destination,
   691                                  	;  so they do not overlap. In this case we prefer moving up.
   692                                  
   693                                  .up:
   694 0000016F 50                      	push ax
   695 00000170 52                      	push dx
   696                                  .uploop:
   697 00000171 8ED8                    	mov ds, ax
   698 00000173 8EC2                    	mov es, dx
   699 00000175 31FF                    	xor di, di
   700 00000177 31F6                    	xor si, si		; -> start of segment
   701 00000179 81E90010                	sub cx, 1000h		; 64 KiB left ?
   702 0000017D 7610                    	jbe .uplast		; no -->
   703 0000017F 51                      	push cx
   704 00000180 B90080                  	mov cx, 10000h /2
   705 00000183 F3A5                    	rep movsw		; move 64 KiB
   706 00000185 59                      	pop cx
   707 00000186 050010                  	add ax, 1000h
   708 00000189 81C20010                	add dx, 1000h		; -> next segment
   709 0000018D EBE2                    	jmp short .uploop	; proceed for more -->
   710                                  .uplast:
   711 0000018F 81C10010                	add cx, 1000h		; restore counter
   712 00000193 D1E1                    	shl cx, 1
   713 00000195 D1E1                    	shl cx, 1
   714 00000197 D1E1                    	shl cx, 1		; *8, paragraphs to words
   715 00000199 F3A5                    	rep movsw		; move last part
   716 0000019B 5A                      	pop dx
   717 0000019C 58                      	pop ax
   718 0000019D EB43                    	jmp short .return
   719                                  
   720                                  .down:
   721 0000019F FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   722                                  .dnloop:
   723 000001A0 81E90010                	sub cx, 1000h		; 64 KiB left ?
   724 000001A4 761A                    	jbe .dnlast		; no -->
   725 000001A6 50                      	push ax
   726 000001A7 52                      	push dx
   727 000001A8 01C8                    	add ax, cx
   728 000001AA 01CA                    	add dx, cx
   729 000001AC 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   730 000001AE 8EC2                    	mov es, dx
   731 000001B0 5A                      	pop dx
   732 000001B1 58                      	pop ax
   733 000001B2 BFFEFF                  	mov di, -2
   734 000001B5 89FE                    	mov si, di		; moved from last word down
   735 000001B7 51                      	push cx
   736 000001B8 B90080                  	mov cx, 10000h /2
   737 000001BB F3A5                    	rep movsw		; move 64 KiB
   738 000001BD 59                      	pop cx
   739 000001BE EBE0                    	jmp short .dnloop	; proceed for more -->
   740                                  .dnlast:
   741 000001C0 81C10010                	add cx, 1000h		; restore counter
   742 000001C4 D1E1                    	shl cx, 1
   743 000001C6 D1E1                    	shl cx, 1
   744 000001C8 D1E1                    	shl cx, 1		; *8, paragraphs to words
   745 000001CA 89CF                    	mov di, cx
   746 000001CC 4F                      	dec di
   747 000001CD D1E7                    	shl di, 1		; words to offset, -> last word
   748 000001CF 89FE                    	mov si, di
   749 000001D1 8ED8                    	mov ds, ax
   750 000001D3 8EC2                    	mov es, dx		; first segment correct
   751                                  
   752                                  
   753                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   754                                  %if 0
   755                                  
   756                                  Jack R. Ellis pointed out this erratum:
   757                                  
   758                                  Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
   759                                  
   760                                  109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
   761                                  
   762                                  Description
   763                                  
   764                                  In certain situations a REP MOVS instruction may lead to
   765                                  incorrect results. An incorrect address size, data size
   766                                  or source operand segment may be used or a succeeding
   767                                  instruction may be skipped. This may occur under the
   768                                  following conditions:
   769                                  
   770                                  * EFLAGS.DF=1 (the string is being moved in the reverse direction).
   771                                  
   772                                  * The number of items being moved (RCX) is between 1 and 20.
   773                                  
   774                                  * The REP MOVS instruction is preceded by some microcoded instruction
   775                                    that has not completely retired by the time the REP MOVS begins
   776                                    execution. The set of such instructions includes BOUND, CLI, LDS,
   777                                    LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
   778                                  
   779                                  Potential Effect on System
   780                                  
   781                                  Incorrect results may be produced or the system may hang.
   782                                  
   783                                  Suggested Workaround
   784                                  
   785                                  Contact your AMD representative for information on a BIOS update.
   786                                  
   787                                  %endif
   788                                  
   789                                  %if _AMD_ERRATUM_109_WORKAROUND
   790 000001D5 E308                    	jcxz @FF
   791 000001D7 83F914                  	cmp cx, 20
   792 000001DA 7703                    	ja @FF
   793                                  @@:
   794 000001DC A5                      	movsw
   795 000001DD E2FD                    	loop @B
   796                                  @@:
   797                                  %endif
   798 000001DF F3A5                    	rep movsw		; move first part
   799 000001E1 FC                      	cld
   800                                  .return:
   801 000001E2 C3                      	retn
   802                                  
   803                                  
   804                                  	addsection INIT0B, align=16 vstart=0 follows=INIT0
   805                                  		; INP:	ax:cx = cs:ip = cs:0
   806                                  		;	ax => INIT0B
   807                                  		;	dx => payload source
   808                                  		;	ss:sp -> (dword pointer to lCFG block)
   809                                  		;	if app/device mode supported:
   810                                  		;	 si => depack destination
   811                                  		;	 bx = mode
   812                                  init0b_start:
   813                                  %if _LCFG || _PROGRESS
   814                                  
   815 00000000 054018                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   819                                  
   820                                  %if _LCFG && _PASSLCFG
   821                                   %if (_IMAGE_EXE || _DEVICE)
   822                                  	mov cx, si		; preserve si
   823                                   %endif
   824                                  	pop si
   825                                  	pop ds			; -> lCFG block
   826                                  	mov es, ax
   827                                  	mov di, transfer_lcfg_block
   828                                  				; -> destination
   829                                   %if (_IMAGE_EXE || _DEVICE)
   830                                  	push cx
   831                                   %endif
   832                                  	push di
   833                                  	mov cx, words(lcfg.size)
   834                                  	rep movsw		; cx = 0
   835                                  	pop di			; es:di -> relocated lCFG block, same difference
   836                                   %if (_IMAGE_EXE || _DEVICE)
   837                                  	pop si			; preserve si
   838                                   %endif
   839                                  %elif _LCFG
   840 00000003 5F                      	pop di
   841 00000004 07                      	pop es			; es:di -> (original) lCFG block
   842                                  %endif
   843                                  
   844 00000005 50                      	push ax
   845 00000006 51                      	push cx			; -> far return address to init1_start
   846                                  
   847                                  %if _PROGRESS && _PROGRESSMULTI
   848                                   %if (_IMAGE_EXE || _DEVICE)
   849 00000007 56                      	push si
   850 00000008 53                      	push bx
   851                                   %endif
   852                                   %if _BOOTLDR
   853                                    %if _LCFG
   854 00000009 31C0                    	xor ax, ax
   855 0000000B 268A4512                	mov al, byte [es:di + lcfg.progress_boot - lcfg]
   856 0000000F 97                      	xchg di, ax		; di = boot default progress
   857                                  				; es:ax -> lCFG block
   858                                    %else			; _LCFG
   859                                  	mov di, _PROGRESSDEFAULTBOOT
   860                                    %endif		; _LCFG
   861                                   %endif			; _BOOTLDR
   862                                   %if (_IMAGE_EXE || _DEVICE)
   863                                    %if _BOOTLDR
   864 00000010 85DB                    	test bx, bx
   865 00000012 7503E9AC00              	jz .default
   866                                    %endif		; _BOOTLDR
   867                                    %if _LCFG
   868 00000017 06                      	push es
   869                                     %if _BOOTLDR
   870 00000018 50                      	push ax			; -> lCFG block
   871                                     %else		; _BOOTLDR
   872                                  	push di
   873                                     %endif		; _BOOTLDR
   874                                    %endif		; _LCFG
   875                                    %if _PROGRESSVAR
   876 00000019 B451                    	mov ah, 51h
   877 0000001B CD21                    	int 21h
   878                                  @@:
   879 0000001D 8EDB                    	mov ds, bx
   880 0000001F A12C00                  	mov ax, word [2Ch]
   881 00000022 85C0                    	test ax, ax
   882 00000024 7510                    	jnz .gotenv
   883 00000026 A11600                  	mov ax, word [16h]
   884 00000029 40                      	inc ax
   885 0000002A 7469                    	jz .default_nonboot
   886 0000002C 48                      	dec ax
   887 0000002D 7466                    	jz .default_nonboot
   888 0000002F 39C3                    	cmp bx, ax
   889 00000031 7462                    	je .default_nonboot
   890 00000033 93                      	xchg bx, ax
   891 00000034 EBE7                    	jmp @B
   892                                  
   893                                  .gotenv:
   894 00000036 0E                      	push cs
   895 00000037 1F                      	pop ds				; => cs
   896 00000038 8EC0                    	mov es, ax			; => environment
   897                                   %ifnidni _PROGRESSVARNAME, ""
   898 0000003A BB[F000]                	mov bx, progressvarname1
   899 0000003D E80C00                  	call .findenv
   900 00000040 732E                    	jnc .foundenv			; match -->
   901 00000042 BB[0001]                	mov bx, progressvarname2
   902                                   %endif
   903 00000045 E80400                  	call .findenv
   904 00000048 7326                    	jnc .foundenv			; match -->
   905 0000004A EB49                    	jmp .default_nonboot
   906                                  
   907                                  .findenv:
   908 0000004C 31FF                    	xor di, di
   909                                  @@:
   910                                   %ifnidni _PROGRESSVARNAME, ""
   911 0000004E 89DE                    	mov si, bx			; -> variable name
   912                                   %else
   913                                  	mov si, progressvarname2	; -> variable name
   914                                   %endif
   915 00000050 31C0                    	xor ax, ax
   916 00000052 AC                      	lodsb				; get length
   917 00000053 91                      	xchg cx, ax			; cx = length
   918 00000054 57                      	push di
   919 00000055 F3A6                    	repe cmpsb			; match ?
   920 00000057 7415                    	je .findret_pop			; (NC) yes -->
   921 00000059 5F                      	pop di
   922 0000005A B90080                  	mov cx, 8000h			; maximum env size
   923 0000005D 29F9                    	sub cx, di			; any left ?
   924 0000005F 760B                    	jbe .findret_CY			; no -->
   925 00000061 B000                    	mov al, 0
   926 00000063 F2AE                    	repne scasb			; find next NUL
   927 00000065 7505                    	jne .findret_CY
   928 00000067 263805                  	cmp byte [es:di], al		; double NUL ?
   929 0000006A 75E2                    	jne @B				; no, loop -->
   930                                  .findret_CY:
   931 0000006C F9                      	stc				; not found
   932 0000006D C3                      	retn
   933                                  
   934                                  .findret_pop:
   935 0000006E 59                      	pop cx
   936 0000006F C3                      	retn
   937                                  
   938                                  .foundenv:
   939                                  %if _LCFG
   940 00000070 5E                      	pop si
   941 00000071 5E                      	pop si				; discard far pointer to lCFG
   942                                  %endif
   943 00000072 89FE                    	mov si, di			; es:si -> var content
   944 00000074 31FF                    	xor di, di			; = 0
   945 00000076 31C0                    	xor ax, ax			; ah = 0
   946                                  @@:
   947 00000078 26AC                    	es lodsb			; next candidate digit
   948 0000007A 2C30                    	sub al, '0'			; digit ?
   949 0000007C 7212                    	jb @F				; no -->
   950 0000007E 3C09                    	cmp al, 9
   951 00000080 770E                    	ja @F				; no -->
   952 00000082 01FF                    	add di, di			; times 2
   953 00000084 89FB                    	mov bx, di
   954 00000086 01FF                    	add di, di			; times 4
   955 00000088 01FF                    	add di, di			; times 8
   956 0000008A 01DF                    	add di, bx			; times 8 + times 2 = times 10
   957 0000008C 01C7                    	add di, ax			; add in next digit
   958 0000008E EBE8                    	jmp @B				; and loop
   959                                  
   960                                  @@:
   961 00000090 83E71F                  	and di, 31			; mask to low 5 bits
   962 00000093 EB10                    	jmp @F
   963                                    %endif	; _PROGRESSVAR
   964                                  
   965                                  .default_nonboot:
   966                                  %if _LCFG
   967 00000095 5F                      	pop di
   968 00000096 07                      	pop es			; -> lCFG block
   969 00000097 5B                      	pop bx			; = 1 if app, = 2 if device
   970 00000098 53                      	push bx
   971 00000099 268B4510                	mov ax, word [es:di + lcfg.progress_app - lcfg]
   972                                   %if _DEVICE
   973                                    %if lcfg.progress_app + 1 != lcfg.progress_dev
   974                                     %error Unexpected layout
   975                                    %endif
   976                                  				; al = app, ah = device
   977 0000009D 4B                      	dec bx
   978 0000009E 7402                    	jz .default_app
   979 000000A0 86C4                    	xchg al, ah		; al = device
   980                                  .default_app:
   981                                   %endif			; _DEVICE
   982 000000A2 B400                    	mov ah, 0		; ax = default
   983 000000A4 97                      	xchg di, ax		; di = default
   984                                  %else			; _LCFG
   985                                  	mov di, _PROGRESSDEFAULT
   986                                  %endif			; _LCFG
   987                                  @@:
   988 000000A5 F7C71000                	test di, 16
   989 000000A9 7405                    	jz @F
   990 000000AB 83E7EF                  	and di, ~16
   991 000000AE EB13                    	jmp .outputdevice	; if 16 set skip device check
   992                                  @@:
   993 000000B0 52                      	push dx
   994 000000B1 B80044                  	mov ax, 4400h		; IOCTL get device information
   995 000000B4 BB0100                  	mov bx, 1		; StdOut
   996 000000B7 B283                    	mov dl, 83h		; default if 21.4400 fails
   997 000000B9 CD21                    	int 21h
   998 000000BB F6C280                  	test dl, 80h
   999 000000BE 5A                      	pop dx
  1000 000000BF 7502                    	jnz .outputdevice
  1001 000000C1 31FF                    	xor di, di		; stdout is a file: force no progress marker
  1002                                  .outputdevice:
  1003                                   %endif			; (_IMAGE_EXE || _DEVICE)
  1004                                  
  1005                                  .default:
  1006                                   %if (_IMAGE_EXE || _DEVICE)
  1007 000000C3 5B                      	pop bx
  1008 000000C4 5E                      	pop si
  1009                                   %endif
  1010 000000C5 83FF05                  	cmp di, step_progress_table.amount
  1011                                  					; valid ?
  1012 000000C8 7202                    	jb @F				; yes -->
  1013 000000CA 31FF                    	xor di, di			; disable
  1014                                  @@:
  1015 000000CC D1E7                    	shl di, 1			; = word index
  1016 000000CE 59                      	pop cx				; = 0
  1017 000000CF 1F                      	pop ds				; ds => INIT1
  1018                                  
  1019 000000D0 2E8B85[E600]            	mov ax, word [cs:step_progress_table + di]
  1020                                  					; ax = rel16 for step progress handler
  1021 000000D5 1E                      	push ds
  1022 000000D6 51                      	push cx				; -> init1_start
  1023 000000D7 A3[BA00]                	mov word [step_progress.handler], ax
  1024                                  					; patch it
  1025                                  
  1026 000000DA 83FF04                  	cmp di, 2 * 2			; none or dots ?
  1027 000000DD 7305                    	jae @F				; no, skip -->
  1028 000000DF C606[0600]A9            	mov byte [..@empty_step_progress], __TEST_IMM16
  1029                                  					; for none and dots do not call here
  1030                                  @@:
  1031                                  %endif			;  _PROGRESS && _PROGRESSMULTI
  1032 000000E4 CB                      	retf
  1033                                  %endif
  1034                                  
  1035                                  %if _PROGRESS && _PROGRESSMULTI
  1036 000000E5 00                      		align 2, db 0
  1037                                  step_progress_table:
  1038                                  .:
  1039 000000E6 1600                    		dw step_progress.0_step - step_progress.base
  1040 000000E8 3B00                    		dw step_progress.1_step - step_progress.base
  1041 000000EA 0000                    		dw step_progress.2_step - step_progress.base
  1042 000000EC 4100                    		dw step_progress.3_step - step_progress.base
  1043 000000EE 8600                    		dw step_progress.4_step - step_progress.base
  1044                                  .amount equ ($ - .) / 2
  1045                                  
  1046                                   %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE)
  1047                                    %ifnidni _PROGRESSVARNAME, ""
  1048 000000F0 0F4C44454255475052-     progressvarname1:	counted _PROGRESSVARNAME, '='
  1048 000000F9 4F47524553533D     
  1049                                    %endif
  1050 00000100 0D4C444F5350524F47-     progressvarname2:	counted "LDOSPROGRESS="
  1050 00000109 524553533D         
  1051                                   %endif
  1052                                  %endif
  1053                                  
  1054 0000010E 90<rep 2h>              	align 16
  1055                                  init0b_end:
  1056                                  
  1057                                  
  1058                                  	addsection PAYLOAD, align=16 follows=INIT0B
  1059                                  payload:
  1060 00000000 <bin 182EFh>            	incbin _PAYLOAD_FILE
  1061                                  .end:
  1062 000182EF 26                      	align 16, db 38
  1063                                  payload_end:
  1064                                  
  1065                                  %if _OPTIMISE_INPUT_SMALL
  1066                                   %ifn (payload_end - payload) <= 65_520
  1067                                    %error Input declared small is not small
  1068                                   %endif
  1069                                  %else
  1070                                   %if (payload_end - payload) <= 65_520
  1071                                    %warning Input could be declared small
  1072                                   %endif
  1073                                  %endif
  1074                                  
  1075                                  
  1076                                  	addsection INIT1, align=16 follows=PAYLOAD vstart=0
  1077                                  init1_start:
  1078                                  		; INP:	ax = cs = INIT1
  1079                                  		;	dx = cs - (payload_end - payload) >> 4 => source data
  1080                                  		;	if kernel mode:
  1081                                  		;	 ss:bp -> LOADDATA and LOADSTACKVARS
  1082                                  		;	 ss:sp -> valid stack above [bp + ldLoadTop]
  1083                                  		;	 60h => destination
  1084                                  		;	any mode:
  1085                                  		;	 ss:sp -> word value for ax
  1086                                  		;	 bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode
  1087                                  		;	 si => destination (60h for kernel mode,
  1088                                  		;		after PSP for EXE mode,
  1089                                  		;		at device header for device mode)
  1090                                  		;		(not set if only kernel mode supported)
  1091                                  		;	 if EXE mode:
  1092                                  		;	  ss:sp -> valid stack above INIT1
  1093                                  		;	  bp = unset
  1094                                  		;	 if device mode:
  1095                                  		;	  ss:sp -> device entrypoint stack
  1096                                  		;	  holds: es, bx, ax, cx, dx, di, si, ds, bp,
  1097                                  		;		  far address of payload strategy entrypoint,
  1098                                  		;		  far return address to DOS
  1099                                  		;	  bp = unset
  1100                                  		; STT:	UP
  1101                                  		; CHG:	ax, bx, cx, dx, es, ds, si, di
  1102                                  %if _IMAGE_EXE || _DEVICE
  1103                                  	lframe
  1104 00000000 5589E5                  	lenter
  1105                                  	lvar word,	exemode		; must be bp - 2!
  1106 00000003 53                      	 push bx
  1107                                   %if ?exemode != -2
  1108                                    %error exemode variable must be directly below bp
  1109                                   %endif
  1110 00000004 56                      	push si
  1111                                   %if _PROGRESS
  1112 00000005 F8                      	clc			; NC
  1113                                   %endif
  1114                                  %else
  1115                                  	xor bx, bx		; always tell them it is kernel mode (NC)
  1116                                  %endif
  1117                                  
  1118                                  %if _PROGRESS
  1119                                  	; clc
  1120                                  ..@empty_step_progress:		; SMC, byte patched to __TEST_IMM16 if none or dots
  1121                                   %if _TEST_PROGRAM
  1122                                  	times 3 nop
  1123                                   %else
  1124 00000006 E89F00                  	call step_progress.CF	; display empty / 0.0%
  1125                                   %endif
  1126                                  @@:
  1127                                  %endif
  1128                                  
  1129                                  %if _IMAGE_EXE || _DEVICE
  1130 00000009 8EC6                    	mov es, si		; es => destination
  1131                                  %else
  1132                                  	mov ax, 60h
  1133                                  	mov es, ax		; es => destination
  1134                                  %endif
  1135 0000000B 31FF                    	xor di, di		; -> destination
  1136                                  
  1137 0000000D 8EDA                    	mov ds, dx
  1138 0000000F 31F6                    	xor si, si		; -> source
  1139                                  
  1140 00000011 B9EF82                  	mov cx, (payload.end - payload) & 0FFFFh
  1141                                  %if (payload.end - payload) >> 16
  1142 00000014 BA0100                  	mov dx, (payload.end - payload) >> 16	; = length of source
  1143                                  %else
  1144                                  	xor dx, dx
  1145                                  %endif
  1146                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  1147                                  	mov ax, _PAYLOAD_KERNEL_MAX_PARAS
  1148                                  	test bx, bx
  1149                                  	jz @F
  1150                                  %endif
  1151 00000017 B8FFFF                  	mov ax, -1
  1152                                  @@:
  1153                                  
  1154                                  		; INP:	ds:si -> source
  1155                                  		;	dx:cx = length of source
  1156                                  		;	es:di -> destination (below source)
  1157                                  		;	bx = EXE mode flag
  1158                                  		;	 (1 if EXE mode, 0 if kernel mode)
  1159                                  		;	 (always 0 if this is a build without EXE mode)
  1160                                  		;	if _PAYLOAD_KERNEL_MAX_PARAS:
  1161                                  		;	 ax = maximum amount in paragraphs of destination needed
  1162                                  		;	 (-1 if full source should be decompressed)
  1163                                  		;	else:
  1164                                  		;	 ax = -1
  1165                                  		; Note:	The destination reaches up to below the source.
  1166 0000001A E85602                  	call depack
  1167                                  %ifn _TEST_PROGRAM
  1168 0000001D 7234                    	jc strict short error	; -2 (replaced by retf \ nop)
  1169                                  %endif
  1170                                  %if _IMAGE_EXE || _DEVICE
  1171 0000001F 5E                      	pop si			; si
  1172                                   %if _TEST_PROGRAM
  1173                                  	pop ax			; (discard ?exemode, leave bx as returned)
  1174                                   %else
  1175 00000020 5B                      	pop bx			; ?exemode
  1176                                   %endif
  1177 00000021 5D                      	pop bp			; bp
  1178 00000022 58                      	pop ax			; ax
  1179                                  	lleave ctx
  1180                                  %endif
  1181                                  %if _TEST_PROGRAM
  1182                                  	retf			; +1 (replace jc error)
  1183                                  	nop			; +1
  1184                                  %endif
  1185                                  
  1186                                  %if _DEVICE
  1187 00000023 F6C302                  	test bl, 2
  1188 00000026 7411                    	jz .jmp_exe_or_kernel_mode
  1189                                  
  1190                                  .jmp_device_mode:
  1191 00000028 8EDE                    	mov ds, si
  1192 0000002A 830E[0000]FF            	or word [device_header.next], -1
  1193                                  %if _LCFG && _PASSLCFG
  1194                                  	mov word [device_header.pass_lcfg], transfer_lcfg_block
  1195                                  	mov word [device_header.pass_lcfg + 2], cs
  1196                                  %endif
  1197 0000002F 07                      	pop es
  1198 00000030 5B                      	pop bx
  1199 00000031 58                      	pop ax
  1200 00000032 59                      	pop cx
  1201 00000033 5A                      	pop dx
  1202 00000034 5F                      	pop di
  1203 00000035 5E                      	pop si
  1204 00000036 1F                      	pop ds
  1205 00000037 5D                      	pop bp
  1206 00000038 CB                      	retf			; transfer to payload strategy entrypoint
  1207                                  				; still on stack: far return address to DOS
  1208                                  
  1209                                  .jmp_exe_or_kernel_mode:
  1210                                  %endif
  1211                                  
  1212                                  %if _IMAGE_EXE
  1213 00000039 F6C301                  	test bl, 1
  1214 0000003C 7410                    	jz .jmp_kernel_mode
  1215                                  
  1216                                  .jmp_exe_mode:
  1217                                  %if ! _IMAGE_EXE_AUTO_STACK
  1218                                  	mov cx, cs
  1219                                  	lea dx, [si + _IMAGE_EXE_SS]
  1220                                  	push dx			; stack = relocated ss value
  1221                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
  1222                                  	cmp cx, dx		; INIT1 code is above intended stack ?
  1223                                  	jae @F			; yes -->
  1224                                  
  1225                                  	lframe
  1226                                  	lenter
  1227                                  	lvar	word, exemode
  1228                                  	 push bx
  1229                                   %if ?exemode != -2
  1230                                    %error exemode variable must be directly below bp
  1231                                   %endif
  1232                                  	mov bx, -1		; unimplemented, return error
  1233                                  	jmp error
  1234                                  	lleave ctx
  1235                                  @@:
  1236                                  	cli
  1237                                  	pop ss			; = relocated ss value
  1238                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
  1239                                  	sti
  1240                                  %endif
  1241                                  
  1242 0000003E 31C9                    	xor cx, cx
  1243 00000040 51                      	push cx			; put zero on top of stack
  1244                                  
  1245                                  %if _IMAGE_EXE_IP < 256
  1246                                  	mov cl, _IMAGE_EXE_IP
  1247                                  %elif (_IMAGE_EXE_IP & 255) == 0
  1248                                  	mov ch, _IMAGE_EXE_IP >> 8
  1249                                  %else
  1250 00000041 B94001                  	mov cx, _IMAGE_EXE_IP
  1251                                  %endif
  1252                                  
  1253                                  %if _IMAGE_EXE_CS == -16
  1254 00000044 83C6F0                  	add si, -16
  1255 00000047 8EDE                    	mov ds, si
  1256 00000049 8EC6                    	mov es, si
  1257                                  %else
  1258                                  	lea dx, [si - 10h]	; => PSP
  1259                                  	mov ds, dx
  1260                                  	mov es, dx		; ds = es => PSP
  1261                                   %if _IMAGE_EXE_CS
  1262                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
  1263                                   %endif
  1264                                  %endif
  1265 0000004B 56                      	push si
  1266 0000004C 51                      	push cx
  1267                                  %if _LCFG && _PASSLCFG
  1268                                  	mov di, transfer_lcfg_block
  1269                                  	mov cx, cs
  1270                                  %endif
  1271 0000004D CB                      	retf			; jump to EXE mode of image
  1272                                  
  1273                                  %endif
  1274                                  .jmp_kernel_mode:
  1275                                  %if _LCFG && _PASSLCFG
  1276                                  	mov di, transfer_lcfg_block
  1277                                  	mov cx, cs
  1278                                  %endif
  1279 0000004E EA20006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
  1280                                  
  1281                                  
  1282                                  %if _TEST_PROGRAM
  1283                                  disp_al_counter:
  1284                                  	inc word [cs:init1_c_mode_counter]	; 5 bytes
  1285                                  	retn					; 1 byte
  1286                                  
  1287                                  init1_c_mode_counter:		dw 0		; 2 bytes, total 8
  1288                                  %else
  1289                                   %if _PROGRESS
  1290                                  disp_al_counter equ step_progress
  1291                                   %else
  1292                                  disp_al_counter equ disp_al
  1293                                   %endif
  1294                                  %endif
  1295                                  
  1296                                  
  1297                                  error:
  1298                                   %ifn _TEST_PROGRAM		; 2 bytes
  1299 00000053 0E                      	push cs
  1300 00000054 1F                      	pop ds
  1301                                   %endif
  1302                                  %if _DEBUG0
  1303                                  	mov si, msg.error_begin
  1304                                  	call disp_error
  1305                                  	xchg ax, bx			; ax = error code
  1306                                  	call disp_ax_hex
  1307                                   %ifn _TEST_PROGRAM		; 3 bytes
  1308                                  	mov si, msg.error_end
  1309                                   %endif
  1310                                  %else
  1311                                   %ifn _TEST_PROGRAM		; 3 bytes
  1312 00000055 BE[4E02]                	mov si, msg.error
  1313                                   %endif
  1314                                  %endif
  1315                                   %ifn _TEST_PROGRAM		; 3 bytes, total 2 + 3 + 3 = 8
  1316 00000058 E8C901                  	call disp_error
  1317                                   %endif
  1318                                  %if _DEVICE
  1319 0000005B F646FE02                	test byte [bp - 2], 2
  1320 0000005F 7435                    	jz .exit_app_or_kernel
  1321                                  
  1322 00000061 5E                      	pop si				; => device segment
  1323 00000062 5B                      	pop bx				; mode word
  1324 00000063 5D                      	pop bp
  1325 00000064 58                      	pop ax
  1326 00000065 8EC6                    	mov es, si
  1327 00000067 31FF                    	xor di, di			; -> device header
  1328 00000069 0E                      	 push cs
  1329 0000006A 1F                      	 pop ds
  1330 0000006B BE[0002]                	mov si, device_header_copy	; -> to reset header
  1331 0000006E B91100                  	mov cx, words(device_header_copy.length)
  1332 00000071 F3A5                    	rep movsw		; overwrite device header with default
  1333                                  				;  (reset to a valid state after unsuccessful
  1334                                  				;  decompression, which may have partially
  1335                                  				;  written the header already)
  1336 00000073 06                      	 push es
  1337 00000074 1F                      	 pop ds				; -> device segment
  1338 00000075 07                      	pop es
  1339 00000076 5B                      	pop bx
  1340 00000077 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1341 0000007D 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
  1342 00000082 268C5F10                	mov word [es:bx + 14 + 2], ds
  1343 00000086 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
  1344 0000008B 58                      	pop ax
  1345 0000008C 59                      	pop cx
  1346 0000008D 5A                      	pop dx
  1347 0000008E 5F                      	pop di
  1348 0000008F 5E                      	pop si
  1349 00000090 1F                      	pop ds
  1350 00000091 5D                      	pop bp
  1351 00000092 83C404                  	add sp, 4		; discard far return to payload's strategy
  1352 00000095 CB                      	retf			; return to DOS
  1353                                  
  1354                                  
  1355                                  .exit_app_or_kernel:
  1356                                  %endif
  1357                                  
  1358                                  %if _IMAGE_EXE
  1359                                  %if _BOOTLDR
  1360 00000096 F646FE01                	test byte [bp - 2], 1
  1361 0000009A 7405                    	jz .exit_kernel_mode
  1362                                  %endif
  1363                                  
  1364 0000009C B87F4C                  	mov ax, 4C7Fh
  1365 0000009F CD21                    	int 21h
  1366                                  
  1367                                  .exit_kernel_mode:
  1368                                  %endif
  1369                                  %if _BOOTLDR
  1370 000000A1 31C0                    	xor ax, ax
  1371 000000A3 CD16                    	int 16h
  1372 000000A5 CD19                    	int 19h
  1373                                  %endif
  1374                                  
  1375                                  
  1376                                  %if _PROGRESS
  1377                                  step_progress:
  1378 000000A7 F9                      	stc
  1379                                  .CF:
  1380 000000A8 53                      	push bx
  1381 000000A9 51                      	push cx
  1382 000000AA 52                      	push dx
  1383 000000AB 1E                      	push ds
  1384 000000AC 56                      	push si
  1385 000000AD 57                      	push di
  1386 000000AE 50                      	push ax
  1387                                  
  1388 000000AF 0E                      	push cs
  1389 000000B0 1F                      	pop ds
  1390                                  
  1391 000000B1 8316[E201]00            	adc word [.counter], 0
  1392 000000B6 A1[E201]                	mov ax, word [.counter]
  1393                                  
  1394                                   %if _PROGRESSMULTI
  1395                                    %if _IMAGE_EXE || _DEVICE
  1396                                     %assign defaultprogresshandler _PROGRESSDEFAULT
  1397                                    %else
  1398                                     %assign defaultprogresshandler _PROGRESSDEFAULTBOOT
  1399                                    %endif
  1400 000000B9 E91600                  	jmp strict near . %+ defaultprogresshandler %+ _step
  1401                                  .handler: equ $ - 2		; SMC, patched to dispatch to handler
  1402                                  .base:
  1403                                   %endif
  1404                                  
  1405                                  .2_step:
  1406 000000BC BAE803                  	mov dx, 1000
  1407 000000BF F7E2                    	mul dx			; dx:ax = counter times 1000
  1408                                  %if _PROGRESSAMOUNT
  1409 000000C1 B9D000                  	mov cx, _PROGRESSAMOUNT
  1410 000000C4 F7F1                    	div cx			; ax = 0..1000
  1411                                  %else
  1412                                   %warning Progress amount is zero
  1413                                  	mov ax, 1
  1414                                  %endif
  1415                                  
  1416                                  %if 0
  1417                                  	cmp word [.display], ax
  1418                                  	je .ret
  1419                                  	mov word [.display], ax
  1420                                  %endif
  1421 000000C6 BE[EB01]                	mov si, .message_number_end - 1
  1422 000000C9 E80E00                  	call .format_percentage
  1423                                  
  1424 000000CC BE[E401]                	mov si, .message
  1425 000000CF E85201                  	call disp_error
  1426                                  
  1427                                  .ret:
  1428 000000D2 58                      	pop ax
  1429                                  .ret_ax:
  1430 000000D3 5F                      	pop di
  1431 000000D4 5E                      	pop si
  1432 000000D5 1F                      	pop ds
  1433 000000D6 5A                      	pop dx
  1434 000000D7 59                      	pop cx
  1435 000000D8 5B                      	pop bx
  1436                                  .retn:
  1437 000000D9 C3                      	retn
  1438                                  
  1439                                  
  1440                                  .format_percentage:
  1441 000000DA BB0200                  	mov bx, 2		; skip dot
  1442                                  
  1443 000000DD B90A00                  	mov cx, 10		; base
  1444                                  @@:
  1445 000000E0 31D2                    	xor dx, dx		; dx:ax = current number
  1446 000000E2 F7F1                    	div cx			; dl = remainder, ax = next number
  1447 000000E4 80C230                  	add dl, '0'		; make decit
  1448 000000E7 8814                    	mov byte [si], dl	; store
  1449 000000E9 29DE                    	sub si, bx		; -> next digit slot
  1450 000000EB 80FB02                  	cmp bl, 2		; did we just store fractional ?
  1451 000000EE B301                    	mov bl, 1		; ! next iteration do not skip dot
  1452 000000F0 74EE                    	je @B			; yes, loop always -->
  1453 000000F2 85C0                    	test ax, ax		; nonzero left ?
  1454 000000F4 75EA                    	jnz @B			; yes, loop if so -->
  1455 000000F6 C3                      	retn
  1456                                  
  1457                                  
  1458                                   %if _PROGRESSMULTI
  1459                                  .0_step: equ .ret
  1460                                  
  1461                                  .1_step:
  1462 000000F7 58                      	pop ax
  1463 000000F8 E83701                  	call disp_al
  1464 000000FB EBD6                    	jmp .ret_ax
  1465                                  
  1466                                  .3_step:
  1467 000000FD BB4B00                  	mov bx, 80 - 1 - 4
  1468 00000100 F7E3                    	mul bx			; dx:ax = counter times 75
  1469                                  %if _PROGRESSAMOUNT
  1470 00000102 B9D000                  	mov cx, _PROGRESSAMOUNT
  1471 00000105 F7F1                    	div cx			; ax = 0..75
  1472                                  %else
  1473                                   %warning Progress amount is zero
  1474                                  	mov ax, 1
  1475                                  %endif
  1476                                  
  1477 00000107 3906[E001]              	cmp word [.display], ax
  1478 0000010B 74C5                    	je .ret
  1479 0000010D A3[E001]                	mov word [.display], ax
  1480                                  
  1481 00000110 50                      	push ax
  1482 00000111 91                      	xchg cx, ax
  1483 00000112 B00D                    	mov al, 13
  1484 00000114 E81B01                  	call disp_al
  1485 00000117 B05B                    	mov al, '['
  1486 00000119 E81601                  	call disp_al
  1487 0000011C B020                    	mov al, 32
  1488 0000011E E81101                  	call disp_al
  1489                                  
  1490 00000121 B023                    	mov al, '#'
  1491 00000123 E305                    	jcxz @FF
  1492                                  @@:
  1493 00000125 E80A01                  	call disp_al
  1494 00000128 E2FB                    	loop @B
  1495                                  @@:
  1496                                  
  1497 0000012A B020                    	mov al, 32
  1498 0000012C 59                      	pop cx
  1499 0000012D 29CB                    	sub bx, cx
  1500 0000012F 7607                    	jbe @FF
  1501 00000131 89D9                    	mov cx, bx
  1502                                  @@:
  1503 00000133 E8FC00                  	call disp_al
  1504 00000136 E2FB                    	loop @B
  1505                                  @@:
  1506                                  
  1507                                  .m4done:
  1508 00000138 E8F700                  	call disp_al
  1509 0000013B B05D                    	mov al, ']'
  1510 0000013D E8F200                  	call disp_al
  1511 00000140 EB90                    	jmp .ret
  1512                                  
  1513                                  
  1514                                  .4_step:
  1515 00000142 50                      	push ax
  1516                                  
  1517 00000143 BAE803                  	mov dx, 1000
  1518 00000146 F7E2                    	mul dx			; dx:ax = counter times 1000
  1519                                  %if _PROGRESSAMOUNT
  1520 00000148 B9D000                  	mov cx, _PROGRESSAMOUNT
  1521 0000014B F7F1                    	div cx			; ax = 0..1000
  1522                                  %else
  1523                                   %warning Progress amount is zero
  1524                                  	mov ax, 1
  1525                                  %endif
  1526                                  
  1527 0000014D BE[F501]                	mov si, .message_4_number_end - 1
  1528 00000150 E887FF                  	call .format_percentage
  1529                                  
  1530 00000153 58                      	pop ax
  1531 00000154 BB4B00                  	mov bx, 80 - 1 - 4
  1532 00000157 F7E3                    	mul bx			; dx:ax = counter times 75
  1533                                  %if _PROGRESSAMOUNT
  1534 00000159 B9D000                  	mov cx, _PROGRESSAMOUNT
  1535 0000015C F7F1                    	div cx			; ax = 0..75
  1536                                  %else
  1537                                   %warning Progress amount is zero
  1538                                  	mov ax, 1
  1539                                  %endif
  1540                                  
  1541 0000015E 50                      	push ax
  1542 0000015F 91                      	xchg cx, ax
  1543 00000160 B00D                    	mov al, 13
  1544 00000162 E8CD00                  	call disp_al
  1545 00000165 B05B                    	mov al, '['
  1546 00000167 E8C800                  	call disp_al
  1547 0000016A B020                    	mov al, 32
  1548 0000016C E8C300                  	call disp_al
  1549                                  
  1550 0000016F 31FF                    	xor di, di
  1551 00000171 BA2200                  	mov dx, (80 - 1 - 4 - .message_4_length) / 2
  1552 00000174 803E[F101]20            	cmp byte [.message_4_number], 32
  1553 00000179 7401                    	je @F
  1554 0000017B 47                      	inc di
  1555                                  @@:
  1556 0000017C 29FA                    	sub dx, di
  1557                                  
  1558 0000017E B023                    	mov al, '#'
  1559 00000180 E306                    	jcxz @FF
  1560                                  @@:
  1561 00000182 E8AD00                  	call disp_al
  1562 00000185 4A                      	dec dx
  1563 00000186 E0FA                    	loopnz @B
  1564                                  @@:
  1565                                  
  1566 00000188 85D2                    	test dx, dx
  1567 0000018A 752E                    	jnz .notyetm4
  1568                                  
  1569 0000018C BE[F101]                	mov si, .message_4
  1570 0000018F 29FE                    	sub si, di
  1571 00000191 E89000                  	call disp_error
  1572                                  
  1573 00000194 29F9                    	sub cx, di
  1574 00000196 760E                    	jbe @FF
  1575 00000198 83E907                  	sub cx, .message_4_length
  1576 0000019B 7609                    	jbe @FF
  1577 0000019D 89CA                    	mov dx, cx
  1578 0000019F B023                    	mov al, '#'
  1579                                  @@:
  1580 000001A1 E88E00                  	call disp_al
  1581 000001A4 E2FB                    	loop @B
  1582                                  @@:
  1583 000001A6 59                      	pop cx
  1584 000001A7 B020                    	mov al, 32
  1585 000001A9 83EB29                  	sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length
  1586 000001AC 29D3                    	sub bx, dx
  1587 000001AE 7607                    	jbe @FF
  1588 000001B0 89D9                    	mov cx, bx
  1589                                  @@:
  1590 000001B2 E87D00                  	call disp_al
  1591 000001B5 E2FB                    	loop @B
  1592                                  @@:
  1593 000001B7 E97EFF                  	jmp .m4done
  1594                                  
  1595                                  .notyetm4:
  1596 000001BA B020                    	mov al, 32
  1597 000001BC 59                      	pop cx
  1598 000001BD 29CB                    	sub bx, cx
  1599 000001BF 7608                    	jbe @FF
  1600 000001C1 89D9                    	mov cx, bx
  1601                                  @@:
  1602 000001C3 E86C00                  	call disp_al
  1603 000001C6 4A                      	dec dx
  1604 000001C7 E0FA                    	loopnz @B
  1605                                  @@:
  1606                                  
  1607 000001C9 BE[F101]                	mov si, .message_4
  1608 000001CC 29FE                    	sub si, di
  1609 000001CE E85300                  	call disp_error
  1610                                  
  1611 000001D1 B020                    	mov al, 32
  1612 000001D3 29F9                    	sub cx, di
  1613 000001D5 83E907                  	sub cx, .message_4_length
  1614                                  	; jbe @FF
  1615                                  @@:
  1616 000001D8 E85700                  	call disp_al
  1617 000001DB E2FB                    	loop @B
  1618                                  @@:
  1619 000001DD E958FF                  	jmp .m4done
  1620                                  %endif
  1621                                  
  1622                                  	align 2, db 0
  1623                                   %if _PROGRESSMULTI
  1624 000001E0 FFFF                    .display:	dw -1
  1625                                   %endif
  1626 000001E2 0000                    .counter:	dw 0
  1627 000001E4 0D5B20                  .message:	db 13,"[ "
  1628 000001E7 2020312E30              .message_number:db "  1.0"	; enough digit slots for 100.0%,
  1629                                  				;  blanks are pre-init until written
  1630                                  .message_number_end:
  1631 000001EC 25205D00                		db "% ]",0
  1632                                   %if _PROGRESSMULTI
  1633 000001F0 20                      		db " "
  1634                                  .message_4:
  1635 000001F1 2020312E30              .message_4_number:db "  1.0"	; enough digit slots for 100.0%,
  1636                                  				;  blanks are pre-init until written
  1637                                  .message_4_number_end:
  1638 000001F6 252000                  		db "% ",0
  1639                                  .message_4_length: equ $ - 1 - .message_4
  1640                                   %endif
  1641                                  %endif
  1642                                  
  1643                                  
  1644                                  %if _DEVICE
  1645 000001F9 90<rep 7h>              	align 16
  1646                                  device_header_copy:
  1647                                  .:
  1648                                  .next:
  1649 00000200 FFFFFFFF                	dd -1				; already initialised
  1650                                  .attributes:
  1651 00000204 0088                    	dw _DEVICE_ATTRIBUTE
  1652                                  .strategy:
  1653 00000206 1200                    	dw .strategy_entry - .		; -> strategy entry
  1654                                  .interrupt:
  1655 00000208 1600                    	dw .interrupt_entry - .		; -> interrupt entry
  1656                                  .name:
  1657 0000020A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME
  1658                                  
  1659                                  .strategy_entry:
  1660 00000212 EB0690<rep 2h>          	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
  1661                                  .interrupt_entry:
  1662 00000216 CB90<rep 3h>            	fill 4, 90h, retf
  1663                                  
  1664                                  .set_error:
  1665 0000021A 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1666 00000220 CB                      	retf
  1667                                  .length: equ $ - .
  1668                                  %endif
  1669                                  
  1670                                  
  1671                                  disp_error.loop:
  1672 00000221 E80E00                  	call disp_al
  1673                                  disp_error:
  1674 00000224 AC                      	lodsb
  1675 00000225 84C0                    	test al, al
  1676 00000227 75F8                    	jnz .loop
  1677 00000229 C3                      	retn
  1678                                  
  1679                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
  1680                                  disp_ax_hex:			; ax
  1681                                  		xchg al,ah
  1682                                  		call disp_al_hex		; display former ah
  1683                                  		xchg al,ah			;  and fall trough for al
  1684                                  disp_al_hex:			; al
  1685                                  		push cx
  1686                                  		mov cl,4
  1687                                  		ror al,cl
  1688                                  		call disp_al_lownibble_hex	; display former high-nibble
  1689                                  		rol al,cl
  1690                                  		pop cx
  1691                                  						;  and fall trough for low-nibble
  1692                                  disp_al_lownibble_hex:
  1693                                  		push ax			 ; save ax for call return
  1694                                  		and al,00001111b		; high nibble must be zero
  1695                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1696                                  		cmp al,'9'
  1697                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1698                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1699                                   .decimalnum:
  1700                                  		call disp_al
  1701                                  		pop ax
  1702                                  		retn
  1703                                  %endif
  1704                                  
  1705                                  
  1706                                  disp_al_for_progress:
  1707                                  %if _PROGRESS && _PROGRESSMULTI
  1708 0000022A 2E833E[BA00]16          	cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base
  1709 00000230 741B                    	je disp_al.retn
  1710                                  %endif
  1711                                  disp_al:
  1712                                  %if _TEST_PROGRAM
  1713                                  	retn
  1714                                  %else
  1715 00000232 50                      	push ax
  1716                                  %endif
  1717                                  %if _BOOTLDR
  1718 00000233 53                      	push bx
  1719 00000234 55                      	push bp
  1720 00000235 B40E                    	mov ah, 0Eh
  1721 00000237 BB0700                  	mov bx, 7
  1722                                  %endif
  1723                                  %if _IMAGE_EXE || _DEVICE
  1724 0000023A 52                      	push dx
  1725                                  
  1726                                  %if _BOOTLDR
  1727 0000023B F646FE03                	test byte [bp - 2], 1 | 2
  1728 0000023F 7406                    	jz .display_kernel_mode
  1729                                  %endif
  1730                                  
  1731 00000241 92                      	xchg dx, ax				; dl = input al
  1732 00000242 B402                    	mov ah, 02h
  1733 00000244 CD21                    	int 21h
  1734                                  %if _BOOTLDR
  1735 00000246 A9                      	db __TEST_IMM16				; (skip int)
  1736                                  %endif
  1737                                  
  1738                                  .display_kernel_mode:
  1739                                  %endif
  1740                                  %if _BOOTLDR
  1741 00000247 CD10                    	int 10h
  1742                                  %endif
  1743                                  %if _IMAGE_EXE
  1744 00000249 5A                      	pop dx
  1745                                  %endif
  1746                                  %if _BOOTLDR
  1747 0000024A 5D                      	pop bp
  1748 0000024B 5B                      	pop bx
  1749                                  %endif
  1750 0000024C 58                      	pop ax
  1751                                  .retn:
  1752                                  disp_error.ret:
  1753 0000024D C3                      	retn
  1754                                  
  1755                                  
  1756                                  msg:
  1757                                  %if _DEBUG0
  1758                                  .error_begin:	db "Load error: Decompression failure, code ",0
  1759                                  .error_end:	db "h.",13,10,0
  1760                                  %else
  1761 0000024E 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
  1761 00000257 723A204465636F6D70-
  1761 00000260 72657373696F6E2066-
  1761 00000269 61696C7572652E0D0A-
  1761 00000272 00                 
  1762                                  %endif
  1763                                  
  1764                                  
  1765                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
  1766                                  %assign NEED_NORMALISE_BOTH_POINTERS 1
  1767                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
  1768                                  %assign CHECK_POINTERS_VARIABLE_DST 1
  1769                                  
  1770                                  		; Specific depacker's file is included within label msg.
  1771                                  		; In the file, lframe is used and lleave ctx is not used.
  1772                                  
  1773                                  %if _BRIEFLZ
  1774                                  	%include "brieflz.asm"
  1775                                  %endif
  1776                                  
  1777                                  
  1778                                  %if _LZ4
  1779                                  	%include "lz4.asm"
     1                              <1> 
     2                              <1> %if 0
     3                              <1> 
     4                              <1> 8086 Assembly lDOS iniload payload LZ4 depacker
     5                              <1>  by E. C. Masloch, 2018
     6                              <1> 
     7                              <1> Usage of the works is permitted provided that this
     8                              <1> instrument is retained with the works, so that any entity
     9                              <1> that uses the works is notified of this instrument.
    10                              <1> 
    11                              <1> DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                              <1> 
    13                              <1> %endif
    14                              <1> 
    15                              <1> 
    16                              <1> lz4_flg_version_mask:	equ 1100_0000b
    17                              <1> lz4_flg_version:	equ 0100_0000b
    18                              <1> lz4_flg_b_indep:	equ 0010_0000b
    19                              <1> lz4_flg_b_checksum:	equ 0001_0000b
    20                              <1> lz4_flg_c_size:		equ 0000_1000b
    21                              <1> lz4_flg_c_checksum:	equ 0000_0100b
    22                              <1> lz4_flg_reserved:	equ 0000_0010b
    23                              <1> lz4_flg_dict_id:	equ 0000_0001b
    24                              <1> 
    25                              <1> lz4_bd_reserved_mask:	equ 1000_1111b
    26                              <1> 		; BD block max size is not used by us
    27                              <1> 
    28                              <1> 
    29                              <1> 		; INP:	ds:si -> source
    30                              <1> 		;	dx:cx = length of source
    31                              <1> 		;	es:di -> destination (below source)
    32                              <1> 		;	if _IMAGE_EXE:
    33                              <1> 		;	 bx = EXE mode flag (bit 0)
    34                              <1> 		;	else:
    35                              <1> 		;	 bx = 0
    36                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
    37                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
    38                              <1> 		;	 (-1 if full source should be decompressed)
    39                              <1> 		;	else:
    40                              <1> 		;	 ax = -1
    41                              <1> 		; OUT:	NC if success
    42                              <1> 		;	CY if error,
    43                              <1> 		;	 bx = ?errordata (if _DEBUG0)
    44                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
    45                              <1> 		; STT:	UP
    46                              <1> 		;
    47                              <1> 		; Note:	The destination reaches up to below the source.
    48                              <1> 		; Note:	The input pointers need not be normalised yet.
    49                              <1> 		;	 Normalised means that the offset part is below 16.
    50                              <1> depack:
    51                              <1> 	lframe near
    52                              <1> %if _IMAGE_EXE || _DEBUG0 || _COUNTER
    53 00000273 5589E5              <1> 	lenter early
    54                              <1>  %if _IMAGE_EXE
    55                              <1> 	lvar word,	exemode	; must be bp - 2!
    56 00000276 53                  <1> 	 push bx
    57                              <1>   %if ?exemode != -2
    58                              <1>    %error exemode variable must be directly below bp
    59                              <1>   %endif
    60                              <1>  %endif
    61                              <1>  %if _DEBUG0 || _COUNTER
    62 00000277 31DB                <1> 	xor bx, bx
    63                              <1>  %endif
    64                              <1>  %if _DEBUG0
    65                              <1> 	lvar word,	errordata
    66                              <1> 	 push bx
    67                              <1>  %endif
    68                              <1> %endif
    69                              <1> 	lvar word,	token_and_counter
    70                              <1> 	lequ ?token_and_counter, token
    71                              <1> 	lequ ?token_and_counter + 1, counter
    72                              <1> %if _COUNTER
    73 00000279 53                  <1> 	 push bx		; initialise counter (high byte) to zero
    74                              <1> %endif
    75                              <1> 	lvar dword,	src_behind_block
    76                              <1> 	lvar word,	frame_descriptor_flg_and_bd
    77 0000027A 8D66F6              <1> 	lenter
    78                              <1> 
    79 0000027D E8A302              <1> 	call normalise_both_pointers
    80                              <1> 
    81                              <1> 	lvar dword,	src
    82 00000280 1E                  <1> 	 push ds
    83 00000281 56                  <1> 	 push si
    84                              <1> 	lvar dword,	original_dst
    85 00000282 06                  <1> 	 push es
    86 00000283 57                  <1> 	 push di
    87                              <1> 	lvar dword,	dst
    88 00000284 06                  <1> 	 push es
    89 00000285 57                  <1> 	 push di
    90                              <1> 	lvar dword,	length_of_source
    91 00000286 52                  <1> 	 push dx
    92 00000287 51                  <1> 	 push cx
    93                              <1> 
    94                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
    95                              <1> 	cmp ax, -1		; no maximum specified ?
    96                              <1> 	je @FF			; retain -1 in ax -->
    97                              <1> 	test di, di		; do we need an additional paragraph ?
    98                              <1> 	jz @F			; no -->
    99                              <1> 	inc ax			; es + ax => paragraph after necessary part
   100                              <1> @@:
   101                              <1> 	mov dx, es
   102                              <1> 	add ax, dx		; => paragraph after necessary part
   103                              <1> 		; If the normalised destination pointer's segment grows
   104                              <1> 		;  to this segment then enough has been decompressed.
   105                              <1> d0	mov byte [bp + ?errordata], 40h
   106                              <1> 	jc .error		; should not carry
   107                              <1> @@:
   108                              <1> 	lvar word,	dst_max_segment
   109                              <1> 	 push ax
   110                              <1> %endif
   111                              <1> 
   112 00000288 1E                  <1> 	 push ds
   113 00000289 56                  <1> 	 push si
   114 0000028A E8F602              <1> 	call pointer_to_linear
   115                              <1> 
   116 0000028D 89D3                <1> 	mov bx, dx
   117 0000028F 91                  <1> 	xchg cx, ax		; bx:cx = source linear
   118                              <1> 
   119 00000290 06                  <1> 	 push es
   120 00000291 57                  <1> 	 push di
   121 00000292 E8EE02              <1> 	call pointer_to_linear
   122                              <1> 
   123                              <1> %if _ALLOW_OVERLAPPING
   124 00000295 034EE6              <1> 	add cx, word [bp + ?length_of_source]
   125 00000298 135EE8              <1> 	adc bx, word [bp + ?length_of_source + 2]
   126                              <1> 		; In case of allowing overlapping source and destination,
   127                              <1> 		;  the ?length_of_destination variable is set to
   128                              <1> 		;  ?src + ?length_of_source - ?dst, allowing to write to
   129                              <1> 		;  all of the source buffer (with the checks already in place
   130                              <1> 		;  from the default handling). Additional checks are done by
   131                              <1> 		;  calling check_pointers_not_overlapping. This is done after
   132                              <1> 		;  every change of ?dst to verify that the write pointer stays
   133                              <1> 		;  below-or-equal the read pointer.
   134                              <1> 		; This means the remaining source data may be corrupted by a
   135                              <1> 		;  write, but nothing after the source data is written to,
   136                              <1> 		;  so the error handling (in INIT1 after the data) still works.
   137                              <1> %endif
   138                              <1> 
   139 0000029B 29C1                <1> 	sub cx, ax
   140 0000029D 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   141                              <1> 
   142                              <1> 	lvar dword,	length_of_destination
   143 0000029F 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   144 000002A0 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   145                              <1> 
   146                              <1> %if _ALLOW_OVERLAPPING
   147 000002A1 E86302              <1> 	call check_pointers_not_overlapping
   148                              <1> 		; Note:	We initially check here that the write pointer is
   149                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   150                              <1> 		;	 Doing this check here (as well as after any
   151                              <1> 		;	 copied match) allows us to drop the check done
   152                              <1> 		;	 after moving literal bytes.
   153                              <1> d0	mov byte [bp + ?errordata], 1Bh
   154 000002A4 720D                <1> 	jc .error
   155                              <1> %endif
   156                              <1> 
   157                              <1> .loop_frame:
   158 000002A6 31C9                <1> 	xor cx, cx
   159 000002A8 394EE8              <1> 	cmp word [bp + ?length_of_source + 2], cx
   160 000002AB 7517                <1> 	jne @F
   161 000002AD 394EE6              <1> 	cmp word [bp + ?length_of_source], cx
   162 000002B0 7512                <1> 	jne @F
   163                              <1> 
   164                              <1> .end:
   165 000002B2 A8                  <1> 	db __TEST_IMM8			; (NC)
   166                              <1> .error:
   167 000002B3 F9                  <1> 	stc
   168                              <1> 
   169                              <1> %if _COUNTER
   170 000002B4 9F                  <1> 	lahf
   171 000002B5 B00D                <1> 	mov al, 13
   172 000002B7 E870FF              <1> 	call disp_al_for_progress
   173 000002BA B00A                <1> 	mov al, 10
   174 000002BC E86BFF              <1> 	call disp_al_for_progress
   175 000002BF 9E                  <1> 	sahf
   176                              <1> %endif
   177                              <1> d0	mov bx, word [bp + ?errordata]
   178 000002C0 89EC5D              <1> 	lleave code
   179 000002C3 C3                  <1> 	lret
   180                              <1> 
   181                              <1> 
   182                              <1> @@:
   183 000002C4 B104                <1> 	mov cl, 4
   184 000002C6 E81B02              <1> 	call read_le_data_src
   185                              <1> d0	mov byte [bp + ?errordata], 1
   186 000002C9 72E8                <1> 	jc .error
   187                              <1> 
   188 000002CB 81FA4D18            <1> 	cmp dx, 184Dh			; signature match ?
   189                              <1> d0	mov byte [bp + ?errordata], 2
   190 000002CF 75E2                <1> 	jne .error			; no -->
   191 000002D1 3D0422              <1> 	cmp ax, 2204h			; usual frame ?
   192 000002D4 7427                <1> 	je @F				; yes -->
   193                              <1> 
   194 000002D6 24F0                <1> 	and al,  ~0Fh
   195 000002D8 3D502A              <1> 	cmp ax, 2A50h			; skippable frame ?
   196                              <1> d0	mov byte [bp + ?errordata], 3
   197 000002DB 75D6                <1> 	jne .error			; no -->
   198                              <1> 
   199                              <1> 		; cx = 4 still here
   200 000002DD E80402              <1> 	call read_le_data_src		; read length of skippable frame
   201                              <1> d0	mov byte [bp + ?errordata], 4
   202 000002E0 72D1                <1> 	jc .error
   203                              <1> 
   204 000002E2 1E                  <1> 	 push ds
   205 000002E3 56                  <1> 	 push si
   206 000002E4 89C1                <1> 	mov cx, ax
   207 000002E6 89D3                <1> 	mov bx, dx			; displacement = skippable frame length
   208 000002E8 E86902              <1> 	call normalise_pointer_with_displacement_bxcx
   209 000002EB 8F46F2              <1> 	 pop word [bp + ?src]
   210 000002EE 8F46F4              <1> 	 pop word [bp + ?src + 2]	; ?src += length
   211                              <1> d0	mov byte [bp + ?errordata], 1Dh
   212 000002F1 72C0                <1> 	jc .error
   213                              <1> 
   214 000002F3 2946E6              <1> 	sub word [bp + ?length_of_source], ax
   215 000002F6 1956E8              <1> 	sbb word [bp + ?length_of_source + 2], dx
   216                              <1> 					; ?length_of_source -= length
   217                              <1> d0	mov byte [bp + ?errordata], 5
   218 000002F9 72B8                <1> 	jc .error
   219 000002FB EBA9                <1> 	jmp .loop_frame
   220                              <1> 
   221                              <1> 
   222                              <1> @@:
   223 000002FD B102                <1> 	mov cl, 2
   224 000002FF E8E201              <1> 	call read_le_data_src		; read FLG (low byte), BD (high byte)
   225                              <1> d0	mov byte [bp + ?errordata], 6
   226                              <1> .error_CY_1:
   227 00000302 72AF                <1> 	jc .error
   228                              <1> 
   229 00000304 8946F6              <1> 	mov word [bp + ?frame_descriptor_flg_and_bd], ax
   230 00000307 89C3                <1> 	mov bx, ax
   231 00000309 80E3C0              <1> 	and bl, lz4_flg_version_mask
   232 0000030C 80FB40              <1> 	cmp bl, lz4_flg_version		; version correct ?
   233                              <1> d0	mov byte [bp + ?errordata], 7
   234                              <1> .error_NZ_1:
   235 0000030F 75A2                <1> 	jne .error			; no -->
   236                              <1> 
   237 00000311 A9038F              <1> 	test ax, (lz4_bd_reserved_mask << 8) 		 | lz4_flg_reserved | lz4_flg_dict_id	; unsupported bits set?
   239                              <1> d0	mov byte [bp + ?errordata], 8
   240 00000314 75F9                <1> 	jnz .error_NZ_1			; yes -->
   241                              <1> 
   242                              <1> 		; not checked: lz4_flg_b_indep (linked is always supported),
   243                              <1> 		;  lz4_flg_b_checksum, lz4_flg_c_checksum (both checked later)
   244                              <1> 
   245 00000316 A808                <1> 	test al, lz4_flg_c_size		; content size field present ?
   246 00000318 7407                <1> 	jz @F				; no -->
   247 0000031A B108                <1> 	mov cl, 8
   248 0000031C E8C501              <1> 	call read_le_data_src		; (skip content size field)
   249                              <1> d0	mov byte [bp + ?errordata], 9
   250 0000031F 72E1                <1> 	jc .error_CY_1
   251                              <1> @@:
   252 00000321 B101                <1> 	mov cl, 1
   253 00000323 E8BE01              <1> 	call read_le_data_src		; (skip header checksum field)
   254                              <1> d0	mov byte [bp + ?errordata], 0Ah
   255 00000326 72DA                <1> 	jc .error_CY_1
   256                              <1> 
   257                              <1> .loop_block:
   258                              <1> %if _COUNTER && !_PROGRESS
   259                              <1> 	mov al, '#'
   260                              <1> 	call disp_al
   261                              <1> %endif
   262 00000328 B90400              <1> 	mov cx, 4
   263 0000032B E8B601              <1> 	call read_le_data_src		; read block size field
   264                              <1> 					; leaves ds:si -> source
   265                              <1> d0	mov byte [bp + ?errordata], 0Bh
   266 0000032E 72D2                <1> 	jc .error_CY_1
   267                              <1> 
   268 00000330 85D2                <1> 	test dx, dx			; nonzero ?
   269 00000332 7512                <1> 	jnz @FF
   270 00000334 85C0                <1> 	test ax, ax
   271 00000336 750E                <1> 	jnz @FF				; yes -->
   272                              <1> 
   273 00000338 F646F604            <1> 	test byte [bp + ?frame_descriptor_flg_and_bd], lz4_flg_c_checksum
   274 0000033C 7405                <1> 	jz @F
   275                              <1> 		; cx = 4 already
   276 0000033E E8A301              <1> 	call read_le_data_src		; (skip c checksum field)
   277                              <1> d0	mov byte [bp + ?errordata], 0Ch
   278                              <1> .error_CY_2:
   279 00000341 72BF                <1> 	jc .error_CY_1
   280                              <1> @@:
   281 00000343 E960FF              <1> 	jmp .loop_frame			; next frame, if any -->
   282                              <1> 
   283                              <1> 
   284                              <1> @@:
   285 00000346 1E                  <1> 	 push ds
   286 00000347 56                  <1> 	 push si			; -> source
   287 00000348 89D3                <1> 	mov bx, dx
   288 0000034A 80E77F              <1> 	and bh, ~80h			; clear "uncompressed" flag
   289 0000034D 89C1                <1> 	mov cx, ax			; bx:cx = block size
   290 0000034F E80202              <1> 	call normalise_pointer_with_displacement_bxcx
   291                              <1> 					; -> source after block
   292 00000352 8F46F8              <1> 	 pop word [bp + ?src_behind_block]
   293 00000355 8F46FA              <1> 	 pop word [bp + ?src_behind_block + 2]
   294                              <1> d0	mov byte [bp + ?errordata], 1Eh
   295 00000358 7303E956FF          <1> 	jc .error
   296 0000035D F6C680              <1> 	test dh, 80h			; is it uncompressed ?
   297 00000360 7448                <1> 	jz .compressed			; no -->
   298                              <1> 
   299                              <1> .uncompressed:
   300 00000362 87DA                <1> 	xchg bx, dx			; get size without "uncompressed" flag
   301 00000364 E8FC00              <1> 	call lz4_copy_literal_or_uncompressed
   302                              <1> d0	mov byte [bp + ?errordata], 0Dh
   303 00000367 72D8                <1> 	jc .error_CY_2
   304                              <1> 
   305                              <1> .end_block:
   306 00000369 FF76FA              <1> 	 push word [bp + ?src_behind_block + 2]
   307 0000036C FF76F8              <1> 	 push word [bp + ?src_behind_block]
   308 0000036F E81102              <1> 	call pointer_to_linear
   309 00000372 89C1                <1> 	mov cx, ax
   310 00000374 89D3                <1> 	mov bx, dx			; bx:cx = linear ?src_behind_block
   311                              <1> 
   312 00000376 FF76F4              <1> 	 push word [bp + ?src + 2]
   313 00000379 FF76F2              <1> 	 push word [bp + ?src]
   314 0000037C E80402              <1> 	call pointer_to_linear		; dx:ax = linear ?src
   315                              <1> 
   316 0000037F 29C1                <1> 	sub cx, ax
   317 00000381 19D3                <1> 	sbb bx, dx			; ?src_behind_block - ?src
   318                              <1> 					;  = amount to skip
   319                              <1> d0	mov byte [bp + ?errordata], 0Fh
   320 00000383 72BC                <1> 	jc .error_CY_2
   321                              <1> 
   322 00000385 294EE6              <1> 	sub word [bp + ?length_of_source], cx
   323 00000388 195EE8              <1> 	sbb word [bp + ?length_of_source + 2], bx
   324                              <1> d0	mov byte [bp + ?errordata], 10h
   325                              <1> .error_CY_3:
   326 0000038B 72B4                <1> 	jc .error_CY_2			; not enough data to skip -->
   327                              <1> 
   328 0000038D FF76FA              <1> 	push word [bp + ?src_behind_block + 2]
   329 00000390 FF76F8              <1> 	push word [bp + ?src_behind_block]
   330 00000393 8F46F2              <1> 	pop word [bp + ?src]
   331 00000396 8F46F4              <1> 	pop word [bp + ?src + 2]	; set ?src -> behind block
   332                              <1> 
   333 00000399 F646F610            <1> 	test byte [bp + ?frame_descriptor_flg_and_bd], lz4_flg_b_checksum
   334 0000039D 7408                <1> 	jz @F				; no block checksum -->
   335 0000039F B90400              <1> 	mov cx, 4
   336 000003A2 E83F01              <1> 	call read_le_data_src		; (skip block checksum field)
   337                              <1> d0	mov byte [bp + ?errordata], 0Eh
   338 000003A5 72E4                <1> 	jc .error_CY_3
   339                              <1> @@:
   340                              <1> 
   341 000003A7 E97EFF              <1> 	jmp .loop_block
   342                              <1> 
   343                              <1> 
   344                              <1> .compressed:
   345                              <1> .loop_sequence:
   346                              <1> 
   347                              <1> %if _COUNTER
   348 000003AA FE46FD              <1> 	inc byte [bp + ?counter]
   349 000003AD F646FD1F            <1> 	test byte [bp + ?counter], _COUNTER - 1
   350 000003B1 7505                <1> 	jnz @F
   351 000003B3 B02E                <1> 	mov al, '.'
   352 000003B5 E8EFFC              <1> 	call disp_al_counter
   353                              <1> @@:
   354                              <1> %endif
   355                              <1> 
   356 000003B8 BB[3604]            <1> 	mov bx, .lodsb
   357 000003BB E8EE00              <1> 	call lz4_func_bx_with_src	; load token
   358                              <1> d0	mov byte [bp + ?errordata], 11h
   359 000003BE 72CB                <1> 	jc .error_CY_3
   360 000003C0 8846FC              <1> 	mov byte [bp + ?token], al
   361                              <1> 
   362 000003C3 B104                <1> 	mov cl, 4
   363 000003C5 D2E8                <1> 	shr al, cl
   364 000003C7 E8F300              <1> 	call lz4_get_length		; dx:cx = length of literals
   365                              <1> d0	mov byte [bp + ?errordata], 12h
   366 000003CA 72BF                <1> 	jc .error_CY_3
   367                              <1> 
   368 000003CC 89C8                <1> 	mov ax, cx			; dx:ax = length of literals (may be 0)
   369 000003CE E89200              <1> 	call lz4_copy_literal_or_uncompressed
   370                              <1> 					; copy over the literals
   371                              <1> d0	mov byte [bp + ?errordata], 13h
   372 000003D1 72B8                <1> 	jc .error_CY_3
   373                              <1> 
   374 000003D3 E87800              <1> 	call lz4_check_behind_block_higher_than_src
   375                              <1> 					; do we have more data in this block ?
   376 000003D6 725B                <1> 	jc .end_sequence		; no -->
   377                              <1> 
   378 000003D8 BB[4204]            <1> 	mov bx, .lodsw
   379 000003DB E8CE00              <1> 	call lz4_func_bx_with_src	; load match offset
   380                              <1> d0	mov byte [bp + ?errordata], 14h
   381                              <1> .error_CY_4:
   382 000003DE 72AB                <1> 	jc .error_CY_3
   383                              <1> 
   384 000003E0 85C0                <1> 	test ax, ax			; offset is 0 ?
   385                              <1> d0	mov byte [bp + ?errordata], 15h
   386 000003E2 F9                  <1> 	stc
   387 000003E3 74F9                <1> 	jz .error_CY_4			; yes, error -->
   388                              <1> 
   389 000003E5 89C1                <1> 	mov cx, ax
   390 000003E7 F7D9                <1> 	neg cx				; -1 .. -65535
   391 000003E9 BBFFFF              <1> 	mov bx, -1			; sign-extend (always negative sense)
   392                              <1> 
   393 000003EC FF76EC              <1> 	 push word [bp + ?dst + 2]
   394 000003EF FF76EA              <1> 	 push word [bp + ?dst]
   395 000003F2 E85F01              <1> 	call normalise_pointer_with_displacement_bxcx
   396 000003F5 5E                  <1> 	 pop si
   397 000003F6 1F                  <1> 	 pop ds				; ds:si -> source of matching
   398                              <1> d0	mov byte [bp + ?errordata], 1Fh
   399 000003F7 7203E9B7FE          <1> 	jnc .error
   400                              <1> 
   401 000003FC 8CD8                <1> 	mov ax, ds			; is source of matching within ?dst ?
   402 000003FE 3946F0              <1> 	cmp word [bp + ?original_dst + 2], ax
   403                              <1> d0	mov byte [bp + ?errordata], 16h
   404                              <1> .error_A_1:
   405 00000401 7603E9ADFE          <1> 	ja .error
   406 00000406 7205                <1> 	jb @F
   407 00000408 3976EE              <1> 	cmp word [bp + ?original_dst], si
   408                              <1> d0	mov byte [bp + ?errordata], 17h
   409 0000040B 77F4                <1> 	ja .error_A_1			; no, ?original_dst is above it -->
   410                              <1> @@:
   411                              <1> 
   412 0000040D 8A46FC              <1> 	mov al, byte [bp + ?token]
   413 00000410 240F                <1> 	and al, 0Fh			; get match length from token
   414 00000412 E8A800              <1> 	call lz4_get_length		; dx:cx = length of match - 4
   415                              <1> d0	mov byte [bp + ?errordata], 18h
   416 00000415 72C7                <1> 	jc .error_CY_4
   417 00000417 89C8                <1> 	mov ax, cx			; dx:ax = length of match - 4
   418 00000419 83C004              <1> 	add ax, 4
   419 0000041C 83D200              <1> 	adc dx, 0			; dx:ax = length of match
   420                              <1> d0	mov byte [bp + ?errordata], 19h
   421 0000041F 72BD                <1> 	jc .error_CY_4
   422 00000421 E85400              <1> 	call lz4_copy_data		; give ?dst -> dest, ds:si -> source
   423                              <1> 		; returns: ?dst incremented, ds:si -> after match source
   424                              <1> d0	mov byte [bp + ?errordata], 1Ah
   425 00000424 72B8                <1> 	jc .error_CY_4
   426                              <1> 
   427                              <1> %if _ALLOW_OVERLAPPING
   428 00000426 E8DE00              <1> 	call check_pointers_not_overlapping
   429                              <1> d0	mov byte [bp + ?errordata], 1Ch
   430 00000429 72B3                <1> 	jc .error_CY_4
   431                              <1> %endif
   432                              <1> 
   433                              <1> .next_sequence:
   434 0000042B E82000              <1> 	call lz4_check_behind_block_higher_than_src
   435 0000042E 7203E977FF          <1> 	jnc .loop_sequence		; process next sequence -->
   436                              <1> 
   437                              <1> .end_sequence:
   438 00000433 E933FF              <1> 	jmp .end_block
   439                              <1> 
   440                              <1> 
   441                              <1> 		; INP:	ds:si -> source data
   442                              <1> 		;	?length_of_source
   443                              <1> 		; OUT:	CY if error (source buffer too small)
   444                              <1> 		;	NC if success,
   445                              <1> 		;	 al = value read
   446                              <1> 		;	 ds:si incremented (NOT normalised)
   447                              <1> 		;	 ?length_of_source decremented
   448                              <1> .lodsb:
   449 00000436 836EE601            <1> 	sub word [bp + ?length_of_source], 1
   450 0000043A 835EE800            <1> 	sbb word [bp + ?length_of_source + 2], 0
   451 0000043E 7201                <1> 	jb .retn
   452 00000440 AC                  <1> 	lodsb
   453                              <1> .retn:
   454 00000441 C3                  <1> 	retn
   455                              <1> 
   456                              <1> 
   457                              <1> 		; INP:	ds:si -> source data
   458                              <1> 		;	?length_of_source
   459                              <1> 		; OUT:	CY if error (source buffer too small)
   460                              <1> 		;	NC if success,
   461                              <1> 		;	 ax = value read
   462                              <1> 		;	 ds:si incremented (NOT normalised)
   463                              <1> 		;	 ?length_of_source decremented
   464                              <1> .lodsw:
   465 00000442 836EE602            <1> 	sub word [bp + ?length_of_source], 2
   466 00000446 835EE800            <1> 	sbb word [bp + ?length_of_source + 2], 0
   467 0000044A 72F5                <1> 	jb .retn
   468 0000044C AD                  <1> 	lodsw
   469 0000044D C3                  <1> 	retn
   470                              <1> 
   471                              <1> 
   472                              <1> 		; INP:	?src_behind_block -> block end (normalised)
   473                              <1> 		;	?src -> current address in source buffer
   474                              <1> 		; OUT:	CY if ?src is >= (above-or-equal) ?src_behind_block
   475                              <1> 		;	NC else (?src is below ?src_behind_block, more data)
   476                              <1> 		; CHG:	ax, dx
   477                              <1> 		;
   478                              <1> 		; Note:	Although ?src should always equal ?src_behind_block
   479                              <1> 		;	 if CY here, we actually check for above-or-equal.
   480                              <1> lz4_check_behind_block_higher_than_src:
   481 0000044E 8B56FA              <1> 	mov dx, word [bp + ?src_behind_block + 2]
   482 00000451 8B46F8              <1> 	mov ax, word [bp + ?src_behind_block]
   483                              <1> 					; dx:ax -> behind block
   484                              <1> 
   485 00000454 3956F4              <1> 	cmp word [bp + ?src + 2], dx	; compare segment
   486 00000457 7708                <1> 	ja .error			; ?src > dx:ax -->
   487 00000459 7205                <1> 	jb .success			; ?src < dx:ax -->
   488 0000045B 3946F2              <1> 	cmp word [bp + ?src], ax	; segment is same, compare offset
   489 0000045E 7301                <1> 	jae .error			; ?src >= dx:ax -->
   490                              <1> 
   491                              <1> .success:
   492 00000460 A8                  <1> 	db __TEST_IMM8			; (NC)
   493                              <1> .error:
   494 00000461 F9                  <1> 	stc
   495 00000462 C3                  <1> 	retn
   496                              <1> 
   497                              <1> 
   498                              <1> 		; INP:	?dst -> destination (normalised)
   499                              <1> 		;	?src -> source (normalised)
   500                              <1> 		;	dx:ax = how long the literal data is (0 is valid)
   501                              <1> 		; OUT:	?dst incremented (normalised)
   502                              <1> 		;	?src incremented (normalised)
   503                              <1> 		;	?length_of_destination shortened
   504                              <1> 		;	?length_of_source shortened
   505                              <1> 		;	CY if error (either buffer too small)
   506                              <1> 		;	NC if success
   507                              <1> 		; CHG:	cx, dx, ax, es, di, ds, si
   508                              <1> lz4_copy_literal_or_uncompressed:
   509 00000463 C576F2              <1> 	lds si, [bp + ?src]
   510                              <1> 
   511 00000466 2946E6              <1> 	sub word [bp + ?length_of_source], ax
   512 00000469 1956E8              <1> 	sbb word [bp + ?length_of_source + 2], dx
   513                              <1> 					; enough data exists ?
   514 0000046C 7209                <1> 	jb .return			; no --> (CY)
   515                              <1> 
   516 0000046E E80700              <1> 	call lz4_copy_data		; CY/NC depending on status
   517                              <1> 
   518 00000471 8976F2              <1> 	mov word [bp + ?src], si
   519 00000474 8C5EF4              <1> 	mov word [bp + ?src + 2], ds
   520                              <1> 					; (CF preserved)
   521                              <1> .return:
   522 00000477 C3                  <1> 	retn
   523                              <1> 
   524                              <1> 
   525                              <1> 		; INP:	?dst -> destination (normalised)
   526                              <1> 		;	ds:si -> source (normalised)
   527                              <1> 		;	dx:ax = how long the data is (0 is valid)
   528                              <1> 		; OUT:	?dst incremented (normalised)
   529                              <1> 		;	ds:si incremented (normalised)
   530                              <1> 		;	?length_of_destination shortened
   531                              <1> 		;	CY if error (buffer too small)
   532                              <1> 		;	NC if success
   533                              <1> 		;	Instead of returning, this may jump to depack.end
   534                              <1> 		;	 if the destination segment grows up to the value
   535                              <1> 		;	 stored in the ?dst_max_segment variable. It is
   536                              <1> 		;	 assumed that this will use the stack frame to leave
   537                              <1> 		;	 the function, therefore discarding any of the stack
   538                              <1> 		;	 contents between the frame and the stack top.
   539                              <1> 		; CHG:	cx, dx, ax, es, di, ds, si
   540                              <1> lz4_copy_data:
   541                              <1> d0	inc byte [bp + ?errordata + 1]
   542 00000478 2946E2              <1> 	sub word [bp + ?length_of_destination], ax
   543 0000047B 1956E4              <1> 	sbb word [bp + ?length_of_destination + 2], dx
   544                              <1> 					; enough space left ?
   545 0000047E 722A                <1> 	jb .error			; no -->
   546                              <1> 
   547 00000480 C47EEA              <1> 	les di, [bp + ?dst]
   548                              <1> .loop:
   549 00000483 B9F0FF              <1> 	mov cx, 64 * 1024 - 16		; block size
   550                              <1> 		; If both pointers are normalised, moving 0FFF0h bytes is
   551                              <1> 		;  valid and results in a maximum offset of 0FFFFh in either.
   552                              <1> 
   553 00000486 85D2                <1> 	test dx, dx			; >= 1_0000h ?
   554 00000488 7508                <1> 	jnz @F				; yes, full block -->
   555 0000048A 85C0                <1> 	test ax, ax			; == 0 ?
   556 0000048C 7415                <1> 	jz .end				; yes, done -->
   557 0000048E 39C8                <1> 	cmp ax, cx			; can move in one (last) block ?
   558 00000490 7607                <1> 	jbe .last			; yes -->
   559                              <1> @@:
   560                              <1> 					; no, move one block and continue
   561 00000492 29C8                <1> 	sub ax, cx
   562 00000494 83DA00              <1> 	sbb dx, 0			; left over remaining
   563 00000497 EB03                <1> 	jmp .copy
   564                              <1> 
   565                              <1> .last:
   566 00000499 91                  <1> 	xchg cx, ax			; cx = remaining length
   567 0000049A 31C0                <1> 	xor ax, ax			; no more remaining
   568                              <1> 
   569                              <1> .copy:
   570 0000049C F3A4                <1> 	rep movsb			; move one block (full or partial)
   571                              <1> 
   572 0000049E E88200              <1> 	call normalise_both_pointers
   573 000004A1 EBE0                <1> 	jmp .loop
   574                              <1> 
   575                              <1> .end:
   576 000004A3 897EEA              <1> 	mov word [bp + ?dst], di
   577 000004A6 8C46EC              <1> 	mov word [bp + ?dst + 2], es
   578                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
   579                              <1> 	mov ax, es
   580                              <1> 	cmp ax, word [bp + ?dst_max_segment]
   581                              <1> 	jae depack.end
   582                              <1> %endif
   583                              <1> 
   584 000004A9 A8                  <1> 	db __TEST_IMM8			; (NC)
   585                              <1> .error:
   586 000004AA F9                  <1> 	stc
   587 000004AB C3                  <1> 	retn
   588                              <1> 
   589                              <1> 
   590                              <1> 		; INP:	?src -> source data
   591                              <1> 		;	bx = function to call
   592                              <1> 		; OUT:	ds:si = ?src -> behind data (normalised)
   593                              <1> 		;	CY if error (buffer too small)
   594                              <1> 		;	NC if success
   595                              <1> 		;	(CF is passed from what the function at bx returns)
   596                              <1> 		;
   597                              <1> 		; Protocol of function in bx called by this:
   598                              <1> 		; INP:	ds:si -> source data
   599                              <1> 		;	?length_of_source
   600                              <1> 		;	(may take more inputs depending on function)
   601                              <1> 		; OUT:	ds:si incremented (NOT normalised)
   602                              <1> 		;	?length_of_source decremented
   603                              <1> 		;	CY if error (buffer too small or other error)
   604                              <1> 		;	NC if success
   605                              <1> 		;	(may give more outputs depending on function)
   606                              <1> lz4_func_bx_with_src:
   607 000004AC C576F2              <1> 	lds si, [bp + ?src]
   608 000004AF FFD3                <1> 	call bx
   609 000004B1 9C                  <1> 	pushf
   610 000004B2 E87500              <1> 	call normalise_dssi_pointer
   611 000004B5 8976F2              <1> 	mov word [bp + ?src], si
   612 000004B8 8C5EF4              <1> 	mov word [bp + ?src + 2], ds
   613 000004BB 9D                  <1> 	popf
   614 000004BC C3                  <1> 	retn
   615                              <1> 
   616                              <1> 
   617                              <1> 		; INP:	?src -> source data
   618                              <1> 		;	?length_of_source
   619                              <1> 		;	al = first field data (0 to 15)
   620                              <1> 		; OUT:	dx:cx = length value
   621                              <1> 		;	?src incremented
   622                              <1> 		;	?length_of_source decremented
   623                              <1> 		;	CY if error (too high or out of source data)
   624                              <1> 		;	NC if success
   625                              <1> 		; CHG:	ax, bx
   626                              <1> lz4_get_length:
   627 000004BD 1E                  <1> 	push ds
   628 000004BE 56                  <1> 	push si
   629                              <1> 
   630 000004BF 31C9                <1> 	xor cx, cx
   631 000004C1 31D2                <1> 	xor dx, dx			; dx:cx = length field
   632 000004C3 B40F                <1> 	mov ah, 15			; first byte maximum value
   633                              <1> .loop:
   634 000004C5 00C1                <1> 	add cl, al
   635 000004C7 80D500              <1> 	adc ch, 0
   636 000004CA 83D200              <1> 	adc dx, 0			; add in this byte
   637 000004CD 7211                <1> 	jc .error			; if too high -->
   638 000004CF 38E0                <1> 	cmp al, ah			; is this the maximum value ?
   639 000004D1 750C                <1> 	jne .end			; no -->
   640 000004D3 BB[3604]            <1> 	mov bx, depack.lodsb
   641 000004D6 E8D3FF              <1> 	call lz4_func_bx_with_src	; load next byte
   642 000004D9 7205                <1> 	jc .error
   643 000004DB B4FF                <1> 	mov ah, 255			; next maximum value is 255
   644 000004DD EBE6                <1> 	jmp .loop			; -->
   645                              <1> 
   646                              <1> .end:
   647 000004DF A8                  <1> 	db __TEST_IMM8			; (NC)
   648                              <1> .error:
   649 000004E0 F9                  <1> 	stc
   650                              <1> 
   651 000004E1 5E                  <1> 	pop si
   652 000004E2 1F                  <1> 	pop ds
   653 000004E3 C3                  <1> 	retn
   654                              <1> 
   655                              <1> 
   656                              <1> 		; INP:	?src -> source data (normalised)
   657                              <1> 		;	cx = size to read, 1 to 4 or higher (at most 0FFF0h)
   658                              <1> 		;	?length_of_source
   659                              <1> 		; OUT:	If cx >= 4,
   660                              <1> 		;	 dx:ax = value read as little-endian
   661                              <1> 		;	If cx == 3,
   662                              <1> 		;	 dl:ax = value read
   663                              <1> 		;	If cx == 2,
   664                              <1> 		;	 ax = value read
   665                              <1> 		;	If cx == 1,
   666                              <1> 		;	 al = value read
   667                              <1> 		;	If cx == 0,
   668                              <1> 		;	 invalid, CY
   669                              <1> 		;	ds:si = ?src = incremented source (normalised)
   670                              <1> 		;	?length_of_source decremented
   671                              <1> 		;	CY if error (source buffer too small, or cx zero)
   672                              <1> 		;	NC if success
   673                              <1> 		; CHG:	ds, si, dx, ax
   674                              <1> 		;
   675                              <1> 		; Note:	Always reads four bytes at INP:ds:si -> data.
   676                              <1> read_le_data_src:
   677 000004E4 E31F                <1> 	jcxz .error
   678                              <1> 
   679 000004E6 294EE6              <1> 	sub word [bp + ?length_of_source], cx
   680 000004E9 835EE800            <1> 	sbb word [bp + ?length_of_source + 2], 0
   681 000004ED 7216                <1> 	jb .error
   682                              <1> 
   683 000004EF C576F2              <1> 	lds si, [bp + ?src]
   684                              <1> 
   685 000004F2 AD                  <1> 	lodsw
   686 000004F3 92                  <1> 	xchg ax, dx		; dx = low word (first)
   687 000004F4 AD                  <1> 	lodsw			; ax = high word (second)
   688 000004F5 92                  <1> 	xchg ax, dx		; fix order, dx:ax = dword
   689                              <1> 
   690 000004F6 83EE04              <1> 	sub si, 4
   691 000004F9 01CE                <1> 	add si, cx
   692                              <1> 
   693 000004FB E82C00              <1> 	call normalise_dssi_pointer
   694 000004FE 8976F2              <1> 	mov word [bp + ?src], si
   695 00000501 8C5EF4              <1> 	mov word [bp + ?src + 2], ds
   696                              <1> 
   697 00000504 A8                  <1> 	db __TEST_IMM8		; (NC)
   698                              <1> .error:
   699 00000505 F9                  <1> 	stc
   700 00000506 C3                  <1> 	retn
   701                              <1> 
  1780                                  %endif
  1781                                  
  1782                                  
  1783                                  %if _SNAPPY
  1784                                  	%include "snappy.asm"
  1785                                  %endif
  1786                                  
  1787                                  
  1788                                  %if _EXODECR
  1789                                  	%include "exodecr.asm"
  1790                                  %endif
  1791                                  
  1792                                  
  1793                                  %if _X
  1794                                  	%include "x.asm"
  1795                                  %endif
  1796                                  
  1797                                  
  1798                                  %if _HEATSHRINK
  1799                                  	%include "heatshr.asm"
  1800                                  %endif
  1801                                  
  1802                                  
  1803                                  %if _LZD
  1804                                  	%include "lzd.asm"
  1805                                  %endif
  1806                                  
  1807                                  
  1808                                  %if _LZO
  1809                                  	%include "lzo.asm"
  1810                                  %endif
  1811                                  
  1812                                  
  1813                                  %if _LZSA2
  1814                                  	%include "lzsa2.asm"
  1815                                  %endif
  1816                                  
  1817                                  
  1818                                  %if _APL
  1819                                  	%include "apl.asm"
  1820                                  %endif
  1821                                  
  1822                                  
  1823                                  %if _BZP
  1824                                  	%include "bzp.asm"
  1825                                  %endif
  1826                                  
  1827                                  
  1828                                  %if _ZEROCOMP
  1829                                  	%include "zerocomp.asm"
  1830                                  %endif
  1831                                  
  1832                                  
  1833                                  %if _MVCOMP
  1834                                  	%include "mvcomp.asm"
  1835                                  %endif
  1836                                  
  1837                                  
  1838                                  %if _LZEXEDAT
  1839                                  	%include "lzexedat.asm"
  1840                                  %endif
  1841                                  
  1842                                  
  1843                                  %if _ALLOW_OVERLAPPING
  1844                                  		; INP:	?src, ?dst
  1845                                  		; OUT:	CY if error (?src < ?dst)
  1846                                  		;	NC if success
  1847                                  		; CHG:	ax, bx, cx, dx
  1848                                  check_pointers_not_overlapping:
  1849                                  %if CHECK_POINTERS_VARIABLE_DST
  1850 00000507 FF76EC                  	 push word [bp + ?dst + 2]
  1851 0000050A FF76EA                  	 push word [bp + ?dst]
  1852                                  %else
  1853                                  	 push es
  1854                                  	 push di
  1855                                  %endif
  1856 0000050D E87300                  	call pointer_to_linear
  1857                                  
  1858 00000510 91                      	xchg cx, ax
  1859 00000511 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1860                                  
  1861                                  %if CHECK_POINTERS_VARIABLE_SRC
  1862 00000513 FF76F4                  	 push word [bp + ?src + 2]
  1863 00000516 FF76F2                  	 push word [bp + ?src]
  1864                                  %else
  1865                                  	 push ds
  1866                                  	 push si
  1867                                  %endif
  1868 00000519 E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1869                                  
  1870 0000051C 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1871 0000051E 7502                    	jne @F
  1872 00000520 39C8                    	cmp ax, cx
  1873                                  @@:
  1874                                  					; (CY) if error (src < dst)
  1875                                  					; (NC) if no error
  1876 00000522 C3                      	retn
  1877                                  %endif
  1878                                  
  1879                                  	; This leaves the lframe context created within the
  1880                                  	;  specific depacker's file. The above function
  1881                                  	;  check_pointers_not_overlapping uses the frame.
  1882                                  	lleave ctx
  1883                                  
  1884                                  
  1885                                  		; INP:	ds:si = pointer
  1886                                  		;	es:di = pointer
  1887                                  		; OUT:	ds:si normalised
  1888                                  		;	es:di normalised
  1889                                  %if NEED_NORMALISE_BOTH_POINTERS
  1890                                  normalise_both_pointers:
  1891 00000523 06                      	 push es
  1892 00000524 57                      	 push di
  1893 00000525 E80A00                  	call normalise_pointer
  1894 00000528 5F                      	 pop di
  1895 00000529 07                      	 pop es
  1896                                  %endif
  1897                                  
  1898                                  normalise_dssi_pointer:
  1899 0000052A 1E                      	 push ds
  1900 0000052B 56                      	 push si
  1901 0000052C E80300                  	call normalise_pointer
  1902 0000052F 5E                      	 pop si
  1903 00000530 1F                      	 pop ds
  1904 00000531 C3                      	retn
  1905                                  
  1906                                  
  1907                                  		; INP:	word [ss:sp + 2] = segment
  1908                                  		;	word [ss:sp] = offset
  1909                                  		;
  1910                                  		; Note:	Does not work correctly with pointers that point to
  1911                                  		;	 a HMA location. Do not use then!
  1912                                  normalise_pointer:
  1913                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1914                                  	lframe near
  1915                                  	lpar word,	segment
  1916                                  	lpar word,	offset
  1917                                  	lpar_return
  1918 00000532 5589E5                  	lenter
  1919                                  
  1920 00000535 837E040F                	cmp word [bp + ?offset], 15
  1921 00000539 7617                    	jbe .ret
  1922                                  
  1923 0000053B 53                      	push bx
  1924 0000053C 51                      	push cx
  1925                                  
  1926 0000053D 31DB                    	xor bx, bx
  1927 0000053F 31C9                    	xor cx, cx
  1928 00000541 FF7606                  	 push word [bp + ?segment]
  1929 00000544 FF7604                  	 push word [bp + ?offset]
  1930 00000547 E80A00                  	call normalise_pointer_with_displacement_bxcx
  1931 0000054A 8F4604                  	 pop word [bp + ?offset]
  1932 0000054D 8F4606                  	 pop word [bp + ?segment]
  1933                                  
  1934 00000550 59                      	pop cx
  1935 00000551 5B                      	pop bx
  1936                                  .ret:
  1937 00000552 5D                      	lleave
  1938 00000553 C3                      	lret
  1939                                  
  1940                                  
  1941                                  		; INP:	word [ss:sp + 2] = segment
  1942                                  		;	word [ss:sp] = offset
  1943                                  		;	bx:cx = add/sub displacement
  1944                                  		; OUT:	CY if the displacement carries
  1945                                  		;	NC if not
  1946                                  normalise_pointer_with_displacement_bxcx:
  1947                                  %endif
  1948                                  	lframe near
  1949                                  	lpar word,	segment
  1950                                  	lpar word,	offset
  1951                                  	lpar_return
  1952 00000554 5589E5                  	lenter
  1953                                  
  1954                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1955                                  	cmp word [bp + ?offset], 15
  1956                                  	jbe .ret
  1957                                  %endif
  1958                                  
  1959 00000557 50                      	push ax
  1960 00000558 51                      	push cx
  1961 00000559 52                      	push dx
  1962                                  
  1963 0000055A FF7606                  	 push word [bp + ?segment]
  1964 0000055D FF7604                  	 push word [bp + ?offset]
  1965 00000560 E82000                  	call pointer_to_linear
  1966                                  
  1967                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1968                                  	; push bx
  1969                                  	; 				; sign-extend cx into bx:cx
  1970                                  	; cmp cx, 8000h			; CY if < 8000h (NC if negative)
  1971                                  	; cmc				; NC if positive
  1972                                  	; sbb bx, bx			; 0 if was NC, -1 if was CY
  1973                                  
  1974 00000563 01C1                    	add cx, ax
  1975 00000565 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1976                                  	; pop bx
  1977 00000567 9F                      	lahf				; ah = flags
  1978                                  %else
  1979                                  	xchg ax, cx
  1980                                  %endif
  1981                                  
  1982                                  %if 0
  1983                                  		; Adds in HMA support for this function. Not currently used.
  1984                                  	cmp dx, 10h			; dx:ax >= 10_0000h ?
  1985                                  	jb @F				; no, linear-to-pointer normally -->
  1986                                  	; ja .error
  1987                                  
  1988                                  	add cx, 10h
  1989                                  	; jc .error
  1990                                  	mov word [bp + ?offset], cx
  1991                                  	or word [bp + ?segment], -1
  1992                                  	jmp .return
  1993                                  @@:
  1994                                  %endif
  1995                                  
  1996 00000568 53                      	push bx
  1997 00000569 89CB                    	mov bx, cx
  1998 0000056B 83E10F                  	and cx, 15
  1999 0000056E 894E04                  	mov word [bp + ?offset], cx
  2000                                  
  2001 00000571 B104                    	mov cl, 4
  2002                                  @@:
  2003 00000573 D1EA                    	shr dx, 1
  2004 00000575 D1DB                    	rcr bx, 1
  2005 00000577 E2FA                    	loop @B
  2006                                  
  2007 00000579 895E06                  	mov word [bp + ?segment], bx
  2008 0000057C 5B                      	pop bx
  2009                                  
  2010                                  	; test dx, dx
  2011                                  	; jnz .error
  2012                                  
  2013                                  .return:
  2014                                  
  2015                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  2016 0000057D 9E                      	sahf				; restore flags from ah
  2017                                  %endif
  2018 0000057E 5A                      	pop dx
  2019 0000057F 59                      	pop cx
  2020 00000580 58                      	pop ax
  2021                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  2022                                  .ret:
  2023                                  %endif
  2024 00000581 5D                      	lleave
  2025 00000582 C3                      	lret
  2026                                  
  2027                                  
  2028                                  		; INP:	word [ss:sp + 2] = segment
  2029                                  		;	word [ss:sp] = offset
  2030                                  		; OUT:	dx:ax = linear address
  2031                                  pointer_to_linear:
  2032                                  	lframe near
  2033                                  	lpar word,	segment
  2034                                  	lpar word,	offset
  2035 00000583 5589E5                  	lenter
  2036                                  
  2037 00000586 8B4606                  	mov ax, word [bp + ?segment]
  2038 00000589 31D2                    	xor dx, dx
  2039 0000058B 51                      	push cx
  2040 0000058C B90400                  	mov cx, 4
  2041                                  @@:
  2042 0000058F D1E0                    	shl ax, 1
  2043 00000591 D1D2                    	rcl dx, 1
  2044 00000593 E2FA                    	loop @B
  2045                                  
  2046 00000595 034604                  	add ax, word [bp + ?offset]
  2047 00000598 11CA                    	adc dx, cx			; cx = 0 here
  2048 0000059A 59                      	pop cx
  2049                                  
  2050 0000059B 5D                      	lleave
  2051 0000059C C20400                  	lret
  2052                                  
  2053                                  
  2054                                  %if _PASSLCFG
  2055                                  	align 16
  2056                                  transfer_lcfg_block:
  2057                                  	times lcfg.size nop
  2058                                  %endif
  2059 0000059F 90                      	align 16
  2060                                  init1_end:
  2061                                  
  2062                                  
  2063                                  	usesection INIT0
  2064                                  %if _TEST_PROGRAM
  2065                                  init0_msg:
  2066                                  %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE
  2067                                  .error_stderr_file:	db "Error: Unable to open own executable file.",13,10
  2068                                  .error_stderr_file.length equ $ - .error_stderr_file
  2069                                  %endif
  2070                                  .error_stderr:	db "Error: Not enough memory allocated.",13,10
  2071                                  .error_stderr.length: equ $ - .error_stderr
  2072                                  .error_c_stdout:
  2073                                  .error_stdout:	db "0"
  2074                                  %if 0
  2075                                  		_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  2080                                  %endif
  2081                                  		db 13,10
  2082                                  .error_c_stdout.length: equ $ - .error_c_stdout
  2083                                  .error_stdout.length: equ $ - .error_stdout
  2084                                  
  2085                                  	align 1024
  2086                                  %if ($ - $$) != 1024
  2087                                   %error Wrong INIT0 size
  2088                                  %endif
  2089                                  %endif
  2090                                  
  2091 000001E3 90<rep Dh>              	align 16
  2092                                  init0_end:
  2093                                  
  2094                                  
  2095                                  %assign num (init1_end - init1_start) + (init0_end - init0_start)
  2096                                  %if _BRIEFLZ
  2097                                  %define which iniblz
  2098                                  %elif _LZ4
  2099                                  %define which inilz4
  2100                                  %elif _SNAPPY
  2101                                  %define which inisz
  2102                                  %elif _EXODECR
  2103                                  %define which iniexo
  2104                                  %elif _X
  2105                                  %define which inix
  2106                                  %elif _HEATSHRINK
  2107                                  %define which inihs
  2108                                  %elif _LZD
  2109                                  %define which inilz
  2110                                  %elif _LZO
  2111                                  %define which inilzo
  2112                                  %elif _LZSA2
  2113                                  %define which inilzsa2
  2114                                  %elif _APL
  2115                                  %define which iniapl
  2116                                  %elif _BZP
  2117                                  %define which inibzp
  2118                                  %elif _ZEROCOMP
  2119                                  %define which inizero
  2120                                  %elif _MVCOMP
  2121                                  %define which inimv
  2122                                  %elif _LZEXEDAT
  2123                                  %define which inilzexe
  2124                                  %endif
  2125                                  %warning which: num bytes used for depacker
  2125          ******************       warning: inilz4: 1936 bytes used for depacker [-w+user]
  2126                                  
  2127                                  
  2128                                  %if _TEST_PROGRAM
  2129                                  	addsection INIT2, align=16 follows=INIT1 vstart=0
  2130                                  init2_start:
  2131                                  		; si => after PSP
  2132                                  		; cs => INIT2
  2133                                  		; psp, free, payload, init1, init2, payload space, stack
  2134                                  		;
  2135                                  		; The correct allocation for the test program
  2136                                  		;  is image size (init0, payload, init1, init2)
  2137                                  		;  minus init0 plus compressed payload size
  2138                                  		;  plus decompressed size plus stack. For
  2139                                  		;  simplicity, init0 subtraction may be skipped.
  2140                                  
  2141                                  		; ss:sp -> word amount repetitions, word ax
  2142                                  		; bx = 1 if A mode test,
  2143                                  		;	8001h if B mode test,
  2144                                  		;	4001h if C mode test
  2145                                  	push bx			; push into ?whichtest
  2146                                  
  2147                                  	lframe 0
  2148                                  %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE
  2149                                  	lpar word,	handle
  2150                                  %endif
  2151                                  	lpar word,	repetitions
  2152                                  	lpar word,	whichtest
  2153                                  %if _RELOAD_XMS
  2154                                   	lvar dword, xmsentry
  2155                                   	lvar word, xmshandle
  2156                                  %endif
  2157                                  %if _INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2158                                  	lequ 128,	buffersize
  2159                                  	lvar ?buffersize,	buffer
  2160                                  %endif
  2161                                  	lenter
  2162                                  
  2163                                  %if _RELOAD_FILE && _RELOAD_XMS
  2164                                  	or word [bp + ?xmshandle], -1
  2165                                  %endif
  2166                                  
  2167                                  	mov dx, word [bp + ?repetitions]
  2168                                  	cmp dx, -1
  2169                                  	jne @F
  2170                                  
  2171                                  .cmdline_error:
  2172                                  %if _DEBUG0
  2173                                  	mov bx, -1
  2174                                  %endif
  2175                                  	mov dx, init2_msg.cmdline_error
  2176                                  	mov cx, init2_msg.cmdline_error.length
  2177                                  	jmp init2_error
  2178                                  
  2179                                  
  2180                                  @@:
  2181                                  	testopt [bp + ?whichtest], 4000h
  2182                                  	jnz .a_or_c
  2183                                  	testopt [bp + ?whichtest], 8000h
  2184                                  	jz .a_or_c
  2185                                  .b:
  2186                                  	test dx, dx
  2187                                  	jz .cmdline_error
  2188                                  	jmp @F
  2189                                  
  2190                                  .a_or_c:
  2191                                  	test dx, dx
  2192                                  	jnz .cmdline_error
  2193                                  @@:
  2194                                  
  2195                                  %if _RELOAD_XMS
  2196                                  	push si
  2197                                  	mov ax, 4300h
  2198                                  	int 2Fh
  2199                                  	cmp al, 80h
  2200                                  %if _RELOAD_FILE
  2201                                  	jne .noxms
  2202                                  %else
  2203                                  	jne init2_error_xms
  2204                                  %endif
  2205                                  	mov ax, 4310h
  2206                                  	int 2Fh
  2207                                  	mov word [bp + ?xmsentry], bx
  2208                                  	mov word [bp + ?xmsentry + 2], es
  2209                                  	mov ah, 09h
  2210                                  	mov dx, KiB(payload_end - payload)
  2211                                  	call far [bp + ?xmsentry]
  2212                                  	cmp ax, 1
  2213                                  %if _RELOAD_FILE
  2214                                  	jne .noxms
  2215                                  %else
  2216                                  	jne init2_error_xms
  2217                                  %endif
  2218                                  	mov word [bp + ?xmshandle], dx
  2219                                  	mov ax, cs
  2220                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2223                                  	 push cs
  2224                                  	 pop ds
  2225                                  	mov si, init2_xmsm_to_save
  2226                                  	mov word [si + XMSM.dsthdl], dx
  2227                                  	mov word [si + XMSM.srcadr + 2], ax
  2228                                  %ifn _RELOAD_FILE
  2229                                  	push ax
  2230                                  %endif
  2231                                  	mov ah, 0Bh
  2232                                  	call far [bp + ?xmsentry]
  2233                                  	cmp ax, 1
  2234                                  	jne init2_error_xms_free
  2235                                  %ifn _RELOAD_FILE
  2236                                  	pop ax			; => payload
  2237                                  %else
  2238                                  .noxms:
  2239                                  	mov ax, cs
  2240                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2243                                  @@:
  2244                                  %endif
  2245                                  	pop si
  2246                                  %elif _RELOAD_FILE
  2247                                  	mov ax, cs
  2248                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2251                                  %else
  2252                                  	mov dx, cs
  2253                                  	add dx, (init2_end - init2_start) >> 4
  2254                                  				; => payload saving area
  2255                                  	mov ax, cs
  2256                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2259                                  	mov cx, (payload_end - payload) >> 4
  2260                                  	call init2_movp		; copy payload to payload saving area
  2261                                  %endif
  2262                                  		; We save away the payload here because a failure
  2263                                  		;  to decompress generally overwrites part of that
  2264                                  		;  payload which was used as source.
  2265                                  
  2266                                  	mov dx, ax		; dx => payload source to use
  2267                                  	mov ax, cs
  2268                                  	sub ax, (init1_end - init1_start) >> 4
  2269                                  				; ax => INIT1
  2270                                  	mov bx, 1		; say we're in EXE mode
  2271                                  	push dx
  2272                                  	push ax
  2273                                  	push si			; si => target
  2274                                  	 push cs
  2275                                  	 call .transfer		; call decompression
  2276                                  	pop si
  2277                                  	pop ax
  2278                                  	pop dx
  2279                                  		; Returns here after decompression.
  2280                                  		; CY if error.
  2281                                  	jnc @F
  2282                                  
  2283                                  	mov dx, init2_msg.initial_error
  2284                                  	mov cx, init2_msg.initial_error.length
  2285                                  	jmp init2_error_free
  2286                                  
  2287                                  @@:
  2288                                  %if _INCLUDE_UNCOMPRESSED
  2289                                   %if _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2290                                  payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed
  2291                                   %else
  2292                                  payload_uncompressed_size equ _TEST_PROGRAM_DECOMPRESSED_SIZE
  2293                                   %endif
  2294                                  	call checkdecompressed
  2295                                  	je @F
  2296                                  
  2297                                  %if _WRITE_WRONG_FILE
  2298                                  	call writefiles
  2299                                  %endif
  2300                                  
  2301                                  %if _DEBUG0
  2302                                  	mov bx, -1
  2303                                  %endif
  2304                                  	mov dx, init2_msg.initial_error_2
  2305                                  	mov cx, init2_msg.initial_error_2.length
  2306                                  	jmp init2_error_free
  2307                                  
  2308                                  @@:
  2309                                  %endif
  2310                                  
  2311                                  	testopt [bp + ?whichtest], 4000h
  2312                                  	jz @F
  2313                                  	mov ax, cs
  2314                                  	sub ax, (init1_end - init1_start) >> 4
  2315                                  				; ax => INIT1
  2316                                  	mov es, ax
  2317                                  	mov ax, word [es:init1_c_mode_counter]
  2318                                  	call init2_disp_ax_dec
  2319                                  	mov al, 13
  2320                                  	call init2_disp_al
  2321                                  	mov al, 10
  2322                                  	call init2_disp_al
  2323                                  %if _RELOAD_XMS
  2324                                  	call freexms
  2325                                  %endif
  2326                                  	mov ax, 4C00h
  2327                                  	int 21h
  2328                                  
  2329                                  @@:
  2330                                  	lvar word,	upperbound
  2331                                  	 push dx
  2332                                  	lvar word,	lowerbound
  2333                                  	 push si
  2334                                  	lvar word,	current_init1
  2335                                  	 push ax
  2336                                  
  2337                                  %if _TEST_PROGRESS
  2338                                  	mov dx, init2_msg.progress.1
  2339                                  	mov cx, init2_msg.progress.1.length
  2340                                  .loop:
  2341                                  	push cs
  2342                                  	pop ds
  2343                                  	mov bx, 2
  2344                                  	mov ah, 40h
  2345                                  	int 21h
  2346                                  %else
  2347                                  .loop:
  2348                                  %endif
  2349                                  
  2350                                  	mov dx, [bp + ?upperbound]
  2351                                  
  2352                                  	testopt [bp + ?whichtest], 8000h
  2353                                  	jz @F
  2354                                  
  2355                                  	dec word [bp + ?repetitions]
  2356                                  	jnz .test_b_skip_bound
  2357                                  
  2358                                  %if _TEST_PROGRESS
  2359                                  	push cs
  2360                                  	pop ds
  2361                                  	mov dx, init2_msg.progress.linebreak
  2362                                  	mov cx, init2_msg.progress.linebreak.length
  2363                                  	mov bx, 2
  2364                                  	mov ah, 40h
  2365                                  	int 21h
  2366                                  %endif
  2367                                  %if _RELOAD_XMS
  2368                                  	call freexms
  2369                                  %endif
  2370                                  	mov ax, 4C00h
  2371                                  	int 21h
  2372                                  
  2373                                  
  2374                                  @@:
  2375                                  	sub dx, [bp + ?lowerbound]
  2376                                  	jz .found
  2377                                  	shr dx, 1
  2378                                  		; Rounding down, so that we never retry upper bound.
  2379                                  		;  The upper bound is known to be working.
  2380                                  	add dx, [bp + ?lowerbound]
  2381                                  
  2382                                  .test_b_skip_bound:
  2383                                  	push dx
  2384                                  	add dx, (payload_end - payload) >> 4
  2385                                  	mov ax, [bp + ?current_init1]
  2386                                  	mov cx, (init1_end - init1_start) >> 4
  2387                                  	call init2_movp
  2388                                  	mov [bp + ?current_init1], dx
  2389                                  	pop dx
  2390                                  
  2391                                  %if _RELOAD_XMS
  2392                                  	mov ax, [bp + ?xmshandle]
  2393                                   %if _RELOAD_FILE
  2394                                  	cmp ax, -1
  2395                                  	je .restore_no_xms
  2396                                   %endif
  2397                                  	push si
  2398                                  	 push cs
  2399                                  	 pop ds
  2400                                  	mov si, init2_xmsm_from_save
  2401                                  	mov word [si + XMSM.srchdl], ax
  2402                                  	mov word [si + XMSM.dstadr + 2], dx
  2403                                  	mov ah, 0Bh
  2404                                  	call far [bp + ?xmsentry]
  2405                                  	cmp ax, 1
  2406                                  	jne init2_error_xms_free
  2407                                  	pop si
  2408                                   %if _RELOAD_FILE
  2409                                  	jmp .restore_done
  2410                                   %endif
  2411                                  %endif
  2412                                  %if _RELOAD_FILE
  2413                                  .restore_no_xms:
  2414                                  size_compressed equ (payload.end - payload)
  2415                                  	push dx
  2416                                  	mov ds, dx
  2417                                  	mov cx, ((- size_compressed) >> 16) & 0FFFFh
  2418                                  	mov dx, (- size_compressed) & 0FFFFh
  2419                                  	mov ax, 4202h
  2420                                  	mov bx, [bp + ?handle]
  2421                                  	int 21h
  2422                                  	jc init2_error_file
  2423                                  	mov dx, size_compressed >> 16
  2424                                  	mov ax, size_compressed & 0FFFFh
  2425                                  @@:
  2426                                  	mov cx, 0FF00h
  2427                                  	test dx, dx
  2428                                  	jnz @F
  2429                                  	cmp ax, cx
  2430                                  	jae @F
  2431                                  	mov cx, ax
  2432                                  @@:
  2433                                  	sub ax, cx
  2434                                  	sbb dx, 0
  2435                                  	push dx
  2436                                  	push ax
  2437                                  	xor dx, dx
  2438                                  	mov ah, 3Fh
  2439                                  	int 21h
  2440                                  	jc init2_error_file
  2441                                  	cmp ax, cx
  2442                                  	jne init2_error_file
  2443                                  	mov dx, ds
  2444                                  	add dx, 0FF0h
  2445                                  	mov ds, dx
  2446                                  	pop ax
  2447                                  	pop dx
  2448                                  	mov cx, ax
  2449                                  	or cx, dx
  2450                                  	jnz @BB
  2451                                  	pop dx
  2452                                  .restore_done:
  2453                                  %endif
  2454                                  %ifn _RELOAD_XMS || _RELOAD_FILE
  2455                                  	mov ax, cs
  2456                                  	add ax, (init2_end - init2_start) >> 4
  2457                                  				; => payload in saving area
  2458                                  	mov cx, (payload_end - payload) >> 4
  2459                                  	call init2_movp		; copy payload from payload saving area
  2460                                  %endif
  2461                                  		; dx => source
  2462                                  	mov ax, [bp + ?current_init1]
  2463                                  	mov bx, 1
  2464                                  	push dx
  2465                                  	push si
  2466                                  	 push cs
  2467                                  	 call .transfer
  2468                                  	pop si
  2469                                  	pop dx
  2470                                  		; Returns here after decompression.
  2471                                  		; CY if error.
  2472                                  	jnc @F
  2473                                  
  2474                                  	testopt [bp + ?whichtest], 8000h
  2475                                  	jnz .test_b_fail
  2476                                  
  2477                                  		; error: this attempt is one below the new lower bound
  2478                                  	inc dx
  2479                                  	mov word [bp + ?lowerbound], dx
  2480                                  
  2481                                  %if _TEST_PROGRESS
  2482                                  	mov dx, init2_msg.progress.fail
  2483                                  	mov cx, init2_msg.progress.fail.length
  2484                                  %endif
  2485                                  	jmp .loop
  2486                                  
  2487                                  @@:
  2488                                  %if _INCLUDE_UNCOMPRESSED
  2489                                  	call checkdecompressed
  2490                                  	je @F
  2491                                  
  2492                                  %if _WRITE_WRONG_FILE
  2493                                  	call writefiles
  2494                                  %endif
  2495                                  
  2496                                  .test_b_fail:
  2497                                  %if _TEST_PROGRESS
  2498                                  	push cs
  2499                                  	pop ds
  2500                                  	mov dx, init2_msg.progress.linebreak
  2501                                  	mov cx, init2_msg.progress.linebreak.length
  2502                                  	mov bx, 2
  2503                                  	mov ah, 40h
  2504                                  	int 21h
  2505                                  %endif
  2506                                  %if _DEBUG0
  2507                                  	mov bx, -2
  2508                                  %endif
  2509                                  	mov dx, init2_msg.subsequent_error_2
  2510                                  	mov cx, init2_msg.subsequent_error_2.length
  2511                                  	jmp init2_error_free
  2512                                  
  2513                                  @@:
  2514                                  %endif
  2515                                  		; success: this attempt is the new upper bound
  2516                                  	mov word [bp + ?upperbound], dx
  2517                                  %if _TEST_PROGRESS
  2518                                  	mov dx, init2_msg.progress.success
  2519                                  	mov cx, init2_msg.progress.success.length
  2520                                  %endif
  2521                                  	jmp .loop
  2522                                  
  2523                                  .found:
  2524                                  %if _TEST_PROGRESS
  2525                                  	push cs
  2526                                  	pop ds
  2527                                  	mov dx, init2_msg.progress.linebreak
  2528                                  	mov cx, init2_msg.progress.linebreak.length
  2529                                  	mov bx, 2
  2530                                  	mov ah, 40h
  2531                                  	int 21h
  2532                                  %endif
  2533                                  	mov ax, word [bp + ?upperbound]
  2534                                  	sub ax, si		; = how many paragraphs in buffer before source
  2535                                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  2537                                  				; = how many paragraphs needed for process
  2538                                  	call init2_disp_ax_dec
  2539                                  	mov al, 13
  2540                                  	call init2_disp_al
  2541                                  	mov al, 10
  2542                                  	call init2_disp_al
  2543                                  %if _RELOAD_XMS
  2544                                  	call freexms
  2545                                  %endif
  2546                                  	mov ax, 4C00h
  2547                                  	int 21h
  2548                                  
  2549                                  
  2550                                  .transfer:
  2551                                  	xor di, di
  2552                                  	push di			; placeholder ax value on stack
  2553                                  	push ax			; INIT1 segment
  2554                                  	push di			; zero = init1_start
  2555                                  	retf			; transfer to INIT1:init1_start
  2556                                  
  2557                                  
  2558                                  
  2559                                  %if _INCLUDE_UNCOMPRESSED
  2560                                  
  2561                                  
  2562                                  %if _WRITE_WRONG_FILE
  2563                                  		; INP:	si => decompressed image
  2564                                  		;	payload_uncompressed_size = size
  2565                                  		;	! _INCLUDE_UNCOMPRESSED_IN_IMAGE:
  2566                                  		;	 word [bp + ?handle] = file handle
  2567                                  		;	 [bp + ?buffer] = ?buffersize buffer
  2568                                  		; OUT:	WRONG.BIN contains what we decompressed
  2569                                  		;	WRONG2.BIN contains expected payload
  2570                                  		; CHG:	ds, si, ax, bx, cx, dx
  2571                                  		; STT:	UP
  2572                                  writefiles:
  2573                                  	push cs
  2574                                  	pop ds
  2575                                  	mov dx, init2_msg.wrong_file_name
  2576                                  	xor cx, cx
  2577                                  	mov ah, 3Ch
  2578                                  	int 21h
  2579                                  	jc .notfile
  2580                                  
  2581                                  	mov bx, ax
  2582                                  	mov cx, payload_uncompressed_size >> 4
  2583                                  	xor dx, dx
  2584                                  .loopfile:
  2585                                  	mov ds, si
  2586                                  	mov ah, 40h
  2587                                  	push cx
  2588                                  	mov cx, 16
  2589                                  	int 21h
  2590                                  	pop cx
  2591                                  	inc si
  2592                                  	loop .loopfile
  2593                                  
  2594                                  	mov ds, si
  2595                                  	mov cx, payload_uncompressed_size & 15
  2596                                  	mov ah, 40h
  2597                                  	int 21h
  2598                                  
  2599                                  	mov ah, 3Eh
  2600                                  	int 21h
  2601                                  
  2602                                  .notfile:
  2603                                  
  2604                                  	push cs
  2605                                  	pop ds
  2606                                  	mov dx, init2_msg.wrong_file_name2
  2607                                  	xor cx, cx
  2608                                  	mov ah, 3Ch
  2609                                  	int 21h
  2610                                  	jc .notfile2
  2611                                  
  2612                                  %if _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2613                                  	mov bx, ax
  2614                                  	mov cx, payload_uncompressed_size >> 4
  2615                                  	mov si, cs
  2616                                  	add si, (payload_uncompressed - init2_start) >> 4
  2617                                  	xor dx, dx
  2618                                  .loopfile2:
  2619                                  	mov ds, si
  2620                                  	mov ah, 40h
  2621                                  	push cx
  2622                                  	mov cx, 16
  2623                                  	int 21h
  2624                                  	pop cx
  2625                                  	inc si
  2626                                  	loop .loopfile2
  2627                                  
  2628                                  	mov ds, si
  2629                                  	mov cx, payload_uncompressed_size & 15
  2630                                  	mov ah, 40h
  2631                                  	int 21h
  2632                                  
  2633                                  	mov ah, 3Eh
  2634                                  	int 21h
  2635                                  %else
  2636                                  	xchg si, ax
  2637                                  
  2638                                  %if _RELOAD_FILE
  2639                                  	mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh
  2640                                  	mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh
  2641                                  %else
  2642                                  	mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh
  2643                                  	mov dx, (- payload_uncompressed_size) & 0FFFFh
  2644                                  %endif
  2645                                  	mov ax, 4202h
  2646                                  	mov bx, [bp + ?handle]
  2647                                  	int 21h
  2648                                  	jc .closefile2
  2649                                  
  2650                                  	push ss
  2651                                  	pop ds
  2652                                  	lea dx, [bp + ?buffer]
  2653                                  
  2654                                  %if payload_uncompressed_size == 0
  2655                                   %error Empty payload not allowed
  2656                                  %endif
  2657                                  %if (payload_uncompressed_size / ?buffersize) != 0
  2658                                  	mov cx, payload_uncompressed_size / ?buffersize
  2659                                  %if ?buffersize == 0 || (?buffersize & 15) != 0
  2660                                   %error Unexpected layout
  2661                                  %endif
  2662                                  .loop:
  2663                                  	push cx
  2664                                  	mov cx, ?buffersize
  2665                                  	call transferchunk
  2666                                  	pop cx
  2667                                  	jc .closefile2
  2668                                  	loop .loop
  2669                                  %endif
  2670                                  %if (payload_uncompressed_size % ?buffersize) != 0
  2671                                  	mov cx, payload_uncompressed_size % ?buffersize
  2672                                  	call transferchunk
  2673                                  %endif
  2674                                  
  2675                                  .closefile2:
  2676                                  	mov bx, si
  2677                                  	mov ah, 3Eh
  2678                                  	int 21h
  2679                                  %endif
  2680                                  
  2681                                  .notfile2:
  2682                                  	retn
  2683                                  
  2684                                  %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2685                                  		; INP:	ds:dx -> buffer
  2686                                  		;	cx = size to transfer, must fit in buffer
  2687                                  		;	?handle = source file handle
  2688                                  		;	si = destination file handle
  2689                                  		; OUT:	NC if success
  2690                                  		;	CY if error
  2691                                  		; CHG:	ax, bx
  2692                                  		; STT:	UP
  2693                                  transferchunk:
  2694                                  	mov bx, word [bp + ?handle]
  2695                                  	mov ah, 3Fh
  2696                                  	int 21h
  2697                                  	jc .ret
  2698                                  	cmp ax, cx
  2699                                  	stc
  2700                                  	jne .ret		; if partial read --> (CY)
  2701                                  	mov bx, si
  2702                                  	mov ah, 40h
  2703                                  	int 21h
  2704                                  	jc .ret
  2705                                  	cmp ax, cx
  2706                                  	je .ret			; if not partial write --> (NC)
  2707                                  	stc
  2708                                  .ret:
  2709                                  	retn
  2710                                  %endif
  2711                                  
  2712                                  %endif
  2713                                  
  2714                                  
  2715                                  		; INP:	si => decompressed image
  2716                                  		;	payload_uncompressed_size = size
  2717                                  		;	! _INCLUDE_UNCOMPRESSED_IN_IMAGE:
  2718                                  		;	 word [bp + ?handle] = file handle
  2719                                  		;	 [bp + ?buffer] = ?buffersize buffer
  2720                                  		; OUT:	ZR if matching
  2721                                  		;	NZ if mismatching
  2722                                  		; CHG:	es, ds, di, bx, cx
  2723                                  		; STT:	UP
  2724                                  checkdecompressed:
  2725                                  	push ax
  2726                                  	push dx
  2727                                  	push si
  2728                                  %if _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2729                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  2730                                  	mov cx, _PAYLOAD_KERNEL_MAX_PARAS
  2731                                  	mov bx, 0
  2732                                  %else
  2733                                  	mov cx, payload_uncompressed_size >> 4
  2734                                  	mov bx, payload_uncompressed_size & 15
  2735                                  %endif
  2736                                  	mov di, cs
  2737                                  	add di, (payload_uncompressed - init2_start) >> 4
  2738                                  	jcxz .end
  2739                                  .loop:
  2740                                  	push cx
  2741                                  	mov cx, 8
  2742                                  	mov ds, si
  2743                                  	mov es, di
  2744                                  	inc si
  2745                                  	inc di
  2746                                  	push si
  2747                                  	push di
  2748                                  	xor si, si
  2749                                  	xor di, di
  2750                                  	repe cmpsw
  2751                                  	pop di
  2752                                  	pop si
  2753                                  	pop cx
  2754                                  	jne .ret
  2755                                  	loop .loop
  2756                                  .end:
  2757                                  	mov ds, si
  2758                                  	mov es, di
  2759                                  	xor si, si
  2760                                  	xor di, di		; (ZR)
  2761                                  	mov cx, bx
  2762                                  	repe cmpsb
  2763                                  %else
  2764                                  %if _RELOAD_FILE
  2765                                  size_compressed_plus_uncompressed equ  payload_uncompressed_size + (payload.end - payload)
  2767                                  	mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh
  2768                                  	mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh
  2769                                  %else
  2770                                  	mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh
  2771                                  	mov dx, (- payload_uncompressed_size) & 0FFFFh
  2772                                  %endif
  2773                                  	mov ax, 4202h
  2774                                  	mov bx, [bp + ?handle]
  2775                                  	int 21h
  2776                                  	jc .error
  2777                                  %if payload_uncompressed_size == 0
  2778                                   %error Empty payload not allowed
  2779                                  %endif
  2780                                  %if (payload_uncompressed_size / ?buffersize) != 0
  2781                                  	mov cx, payload_uncompressed_size / ?buffersize
  2782                                  %if ?buffersize == 0 || (?buffersize & 15) != 0
  2783                                   %error Unexpected layout
  2784                                  %endif
  2785                                  .loop:
  2786                                  	push cx
  2787                                  	mov cx, ?buffersize
  2788                                  	call comparechunk
  2789                                  	pop cx
  2790                                  	jne .ret
  2791                                  	loop .loop
  2792                                  %endif
  2793                                  %if (payload_uncompressed_size % ?buffersize) != 0
  2794                                  	mov cx, payload_uncompressed_size % ?buffersize
  2795                                  	call comparechunk
  2796                                  %endif
  2797                                  %endif
  2798                                  .ret:
  2799                                  	pop si
  2800                                  	pop dx
  2801                                  	pop ax
  2802                                  	retn
  2803                                  
  2804                                  %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2805                                  .error:
  2806                                  	or al, 1			; NZ
  2807                                  	jmp .ret
  2808                                  %endif
  2809                                  %endif
  2810                                  
  2811                                  
  2812                                  %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2813                                  		; INP:	?buffer -> ?buffersize buffer
  2814                                  		;	cx = amount of bytes, 0 < cx <= ?buffersize
  2815                                  		;	si => chunk
  2816                                  		;	?handle = handle
  2817                                  		;	seek -> chunk
  2818                                  		; OUT:	NZ if mismatch or error
  2819                                  		;	ZR else,
  2820                                  		;	 si => next chunk (assumes full chunk)
  2821                                  		; CHG:	ds, es, di, ax, bx, cx, dx
  2822                                  		; STT:	UP
  2823                                  comparechunk:
  2824                                  	push ss
  2825                                  	pop ds
  2826                                  	lea dx, [bp + ?buffer]
  2827                                  	mov bx, [bp + ?handle]
  2828                                  	mov ah, 3Fh
  2829                                  	int 21h
  2830                                  	jc .error
  2831                                  	cmp ax, cx
  2832                                  	jne .error
  2833                                  	mov es, si
  2834                                  	add si, ?buffersize / 16
  2835                                  	push si
  2836                                  	xor di, di
  2837                                  	mov si, dx
  2838                                  	repe cmpsb
  2839                                  	pop si
  2840                                  .ret:
  2841                                  	retn
  2842                                  
  2843                                  .error:
  2844                                  	or al, 1			; NZ
  2845                                  	retn
  2846                                  %endif
  2847                                  
  2848                                  %if _RELOAD_XMS
  2849                                  freexms:
  2850                                  	push ax
  2851                                  	push bx
  2852                                  	push dx
  2853                                  	mov dx, -1
  2854                                  	xchg dx, [bp + ?xmshandle]
  2855                                  %if _RELOAD_FILE
  2856                                  	cmp dx, -1
  2857                                  	je @F
  2858                                  %endif
  2859                                  	mov ah, 0Ah
  2860                                  	call far [bp + ?xmsentry]
  2861                                  @@:
  2862                                  	pop dx
  2863                                  	pop bx
  2864                                  	pop ax
  2865                                  	retn
  2866                                  
  2867                                  init2_error_xms_free:
  2868                                  	call freexms
  2869                                  init2_error_xms:
  2870                                  	mov dx, init2_msg.xms_error
  2871                                  	mov cx, init2_msg.xms_error.length
  2872                                  	jmp init2_error
  2873                                  %endif
  2874                                  
  2875                                  %if _RELOAD_FILE
  2876                                  init2_error_file:
  2877                                  	mov dx, init2_msg.file_error
  2878                                  	mov cx, init2_msg.file_error.length
  2879                                  %endif
  2880                                  
  2881                                  init2_error_free:
  2882                                  %if _RELOAD_XMS
  2883                                  	call freexms
  2884                                  %endif
  2885                                  init2_error:
  2886                                  %if _DEBUG0
  2887                                  	push bx
  2888                                  %endif
  2889                                  	push cs
  2890                                  	pop ds
  2891                                  	mov bx, 2
  2892                                  	mov ah, 40h
  2893                                  	int 21h
  2894                                  
  2895                                  %if _DEBUG0
  2896                                  	mov dx, init2_msg.rc
  2897                                  	mov cx, init2_msg.rc.length
  2898                                  	mov bx, 2
  2899                                  	mov ah, 40h
  2900                                  	int 21h
  2901                                  	pop ax
  2902                                  	call init2_error_disp_ax_hex
  2903                                  	mov dx, init2_msg.linebreak
  2904                                  	mov cx, init2_msg.linebreak.length
  2905                                  	mov bx, 2
  2906                                  	mov ah, 40h
  2907                                  	int 21h
  2908                                  %endif
  2909                                  
  2910                                  	testopt [bp + ?whichtest], 4000h
  2911                                  	jz @F
  2912                                  	mov dx, init2_msg.error_c_stdout
  2913                                  	mov cx, init2_msg.error_c_stdout.length
  2914                                  	jmp @FF
  2915                                  @@:
  2916                                  	testopt [bp + ?whichtest], 8000h
  2917                                  	jnz @FF
  2918                                  	mov dx, init2_msg.error_stdout
  2919                                  	mov cx, init2_msg.error_stdout.length
  2920                                  @@:
  2921                                  	mov bx, 1
  2922                                  	mov ah, 40h
  2923                                  	int 21h
  2924                                  @@:
  2925                                  	mov ax, 4CFFh
  2926                                  	int 21h
  2927                                  
  2928                                  	lleave ctx
  2929                                  
  2930                                  
  2931                                  %if _DEBUG0
  2932                                  init2_error_disp_ax_hex:	; ax
  2933                                  		xchg al,ah
  2934                                  		call init2_error_disp_al_hex	; display former ah
  2935                                  		xchg al,ah			;  and fall trough for al
  2936                                  init2_error_disp_al_hex:	; al
  2937                                  		push cx
  2938                                  		mov cl,4
  2939                                  		ror al,cl
  2940                                  		call init2_error_disp_al_lownibble_hex
  2941                                  						; display former high-nibble
  2942                                  		rol al,cl
  2943                                  		pop cx
  2944                                  						;  and fall trough for low-nibble
  2945                                  init2_error_disp_al_lownibble_hex:
  2946                                  		push ax			 ; save ax for call return
  2947                                  		and al,00001111b		; high nibble must be zero
  2948                                  		add al,'0'			; if number is 0-9, now it's the correct character
  2949                                  		cmp al,'9'
  2950                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  2951                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  2952                                   .decimalnum:
  2953                                  		call init2_error_disp_al
  2954                                  		pop ax
  2955                                  		retn
  2956                                  
  2957                                  
  2958                                  init2_error_disp_al:
  2959                                  	push dx
  2960                                  	push cx
  2961                                  	push bx
  2962                                  	push ax
  2963                                  	mov dx, sp
  2964                                  	push ds
  2965                                  	 push ss
  2966                                  	 pop ds
  2967                                  	mov cx, 1
  2968                                  	mov bx, 2
  2969                                  	mov ah, 40h
  2970                                  	int 21h
  2971                                  	pop ds
  2972                                  	pop ax
  2973                                  	pop bx
  2974                                  	pop cx
  2975                                  	pop dx
  2976                                  	retn
  2977                                  %endif
  2978                                  
  2979                                  
  2980                                  init2_disp_al:
  2981                                  	push dx
  2982                                  	push ax
  2983                                  	mov dl, al
  2984                                  	mov ah, 2
  2985                                  	int 21h
  2986                                  	pop ax
  2987                                  	pop dx
  2988                                  	retn
  2989                                  
  2990                                  
  2991                                  		; Display number in ax decimal
  2992                                  		;
  2993                                  		; INP:	ax = number
  2994                                  		; OUT:	displayed using Int21.02
  2995                                  		; CHG:	none
  2996                                  init2_disp_ax_dec:			; ax (no leading zeros)
  2997                                  		push bx
  2998                                  		xor bx, bx
  2999                                  .pushax:
  3000                                  		push dx
  3001                                  		push ax
  3002                                  		or bl, bl
  3003                                  		jz .nobl
  3004                                  		sub bl, 5
  3005                                  		neg bl
  3006                                  .nobl:
  3007                                  		push cx
  3008                                  		mov cx, 10000
  3009                                  		call .divide_out
  3010                                  		mov cx, 1000
  3011                                  		call .divide_out
  3012                                  		mov cx, 100
  3013                                  		call .divide_out
  3014                                  		mov cl, 10
  3015                                  		call .divide_out
  3016                                  							; (Divisor 1 is useless)
  3017                                  		add al, '0'
  3018                                  		call init2_disp_al
  3019                                  		pop cx
  3020                                  		pop ax
  3021                                  		pop dx
  3022                                  		pop bx					; Caller's register
  3023                                  		retn
  3024                                  
  3025                                  
  3026                                  		; INP:	ax = number
  3027                                  		;	cx = divisor
  3028                                  		; OUT:	ax = remainder of operation
  3029                                  		;	result displayed
  3030                                  .divide_out:
  3031                                  		push dx
  3032                                  		xor dx, dx
  3033                                  		div cx				; 0:ax / cx
  3034                                  		push dx				; remainder
  3035                                  		dec bl
  3036                                  		jnz .nobl2
  3037                                  		or bh, 1
  3038                                  .nobl2:
  3039                                  		or bh, al
  3040                                  		jz .leadingzero
  3041                                  		add al, '0'
  3042                                  		call init2_disp_al		; display result
  3043                                   .leadingzero:
  3044                                  		pop ax				; remainder
  3045                                  		pop dx
  3046                                  		retn
  3047                                  
  3048                                  
  3049                                  init2_msg:
  3050                                  %if _TEST_PROGRESS
  3051                                  .progress.1:		db "Info: 1"
  3052                                  .progress.1.length: equ $ - .progress.1
  3053                                  .progress.fail:		db "F"
  3054                                  .progress.fail.length: equ $ - .progress.fail
  3055                                  .progress.success:	db "S"
  3056                                  .progress.success.length: equ $ - .progress.success
  3057                                  .progress.linebreak:	db 13,10
  3058                                  .progress.linebreak.length: equ $ - .progress.linebreak
  3059                                  %endif
  3060                                  %if _WRITE_WRONG_FILE
  3061                                  .wrong_file_name:	asciz "WRONG.BIN"
  3062                                  .wrong_file_name2:	asciz "WRONG2.BIN"
  3063                                  %endif
  3064                                  .initial_error:	db "Error: Test program failed to decompress with full buffer."
  3065                                  .linebreak:	db 13,10
  3066                                  .initial_error.length: equ $ - .initial_error
  3067                                  .linebreak.length: equ $ - .linebreak
  3068                                  %if _DEBUG0
  3069                                  .rc:	db "Error: Failure code="
  3070                                  .rc.length: equ $ - .rc
  3071                                  %endif
  3072                                  %if _INCLUDE_UNCOMPRESSED
  3073                                  .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  3074                                  .initial_error_2.length: equ $ - .initial_error_2
  3075                                  .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  3076                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  3077                                  %endif
  3078                                  .cmdline_error:	db "Error: Invalid command line input.",13,10
  3079                                  .cmdline_error.length: equ $ - .cmdline_error
  3080                                  %if _RELOAD_XMS
  3081                                  .xms_error:	db "Error: XMS failure.",13,10
  3082                                  .xms_error.length: equ $ - .xms_error
  3083                                  %endif
  3084                                  %if _RELOAD_FILE
  3085                                  .file_error:	db "Error: File read failure.",13,10
  3086                                  .file_error.length: equ $ - .file_error
  3087                                  %endif
  3088                                  
  3089                                  .error_c_stdout:
  3090                                  .error_stdout:	db "0"
  3091                                  %if 0
  3092                                  		_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  3097                                  %endif
  3098                                  		db 13,10
  3099                                  .error_c_stdout.length: equ $ - .error_c_stdout
  3100                                  .error_stdout.length: equ $ - .error_stdout
  3101                                  
  3102                                  
  3103                                  		; Move paragraphs
  3104                                  		;
  3105                                  		; INP:	ax => source
  3106                                  		;	dx => destination
  3107                                  		;	cx = number of paragraphs
  3108                                  		; CHG:	-
  3109                                  		; OUT:	ax and dx unchanged
  3110                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  3111                                  		;	Do not provide a wrapped/HMA source or destination!
  3112                                  init2_movp:
  3113                                  	push cx
  3114                                  	push ds
  3115                                  	push si
  3116                                  	push es
  3117                                  	push di
  3118                                  
  3119                                  	cmp ax, dx		; source above destination ?
  3120                                  	ja .up			; yes, move up (forwards) -->
  3121                                  	je .return		; same, no need to move -->
  3122                                  	push ax
  3123                                  	add ax, cx		; (expected not to carry)
  3124                                  	cmp ax, dx		; end of source is above destination ?
  3125                                  	pop ax
  3126                                  	ja .down		; yes, move from top down -->
  3127                                  	; Here, the end of source is below-or-equal the destination,
  3128                                  	;  so they do not overlap. In this case we prefer moving up.
  3129                                  
  3130                                  .up:
  3131                                  	push ax
  3132                                  	push dx
  3133                                  .uploop:
  3134                                  	mov ds, ax
  3135                                  	mov es, dx
  3136                                  	xor di, di
  3137                                  	xor si, si		; -> start of segment
  3138                                  	sub cx, 1000h		; 64 KiB left ?
  3139                                  	jbe .uplast		; no -->
  3140                                  	push cx
  3141                                  	mov cx, 10000h /2
  3142                                  	rep movsw		; move 64 KiB
  3143                                  	pop cx
  3144                                  	add ax, 1000h
  3145                                  	add dx, 1000h		; -> next segment
  3146                                  	jmp short .uploop	; proceed for more -->
  3147                                  .uplast:
  3148                                  	add cx, 1000h		; restore counter
  3149                                  	shl cx, 1
  3150                                  	shl cx, 1
  3151                                  	shl cx, 1		; *8, paragraphs to words
  3152                                  	rep movsw		; move last part
  3153                                  	pop dx
  3154                                  	pop ax
  3155                                  	jmp short .return
  3156                                  
  3157                                  .down:
  3158                                  	std			; _AMD_ERRATUM_109_WORKAROUND as below
  3159                                  .dnloop:
  3160                                  	sub cx, 1000h		; 64 KiB left ?
  3161                                  	jbe .dnlast		; no -->
  3162                                  	push ax
  3163                                  	push dx
  3164                                  	add ax, cx
  3165                                  	add dx, cx
  3166                                  	mov ds, ax		; -> 64 KiB not yet moved
  3167                                  	mov es, dx
  3168                                  	pop dx
  3169                                  	pop ax
  3170                                  	mov di, -2
  3171                                  	mov si, di		; moved from last word down
  3172                                  	push cx
  3173                                  	mov cx, 10000h /2
  3174                                  	rep movsw		; move 64 KiB
  3175                                  	pop cx
  3176                                  	jmp short .dnloop	; proceed for more -->
  3177                                  .dnlast:
  3178                                  	add cx, 1000h		; restore counter
  3179                                  	shl cx, 1
  3180                                  	shl cx, 1
  3181                                  	shl cx, 1		; *8, paragraphs to words
  3182                                  	mov di, cx
  3183                                  	dec di
  3184                                  	shl di, 1		; words to offset, -> last word
  3185                                  	mov si, di
  3186                                  	mov ds, ax
  3187                                  	mov es, dx		; first segment correct
  3188                                  
  3189                                  		; Refer to comment in init0_movp.
  3190                                  %if _AMD_ERRATUM_109_WORKAROUND
  3191                                  	jcxz @FF
  3192                                  	cmp cx, 20
  3193                                  	ja @FF
  3194                                  @@:
  3195                                  	movsw
  3196                                  	loop @B
  3197                                  @@:
  3198                                  %endif
  3199                                  	rep movsw		; move first part
  3200                                  	cld
  3201                                  .return:
  3202                                  	pop di
  3203                                  	pop es
  3204                                  	pop si
  3205                                  	pop ds
  3206                                  	pop cx
  3207                                  	retn
  3208                                  
  3209                                  
  3210                                  	align 4
  3211                                  %if _RELOAD_XMS
  3212                                  init2_xmsm_from_save:
  3213                                  	istruc XMSM
  3214                                  at XMSM.size_,	dd payload_end - payload
  3215                                  	iend
  3216                                  init2_xmsm_to_save:
  3217                                  	istruc XMSM
  3218                                  at XMSM.size_,	dd payload_end - payload
  3219                                  	iend
  3220                                  %endif
  3221                                  
  3222                                  	align 16
  3223                                  
  3224                                  %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE
  3225                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  3226                                  payload_uncompressed:
  3227                                  	incbin _UNCOMPRESSED_FILE
  3228                                  .end:
  3229                                  	db 38
  3230                                  	align 16, db 38
  3231                                  %endif
  3232                                  init2_end:
  3233                                  %endif
  3234                                  
