     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 EXEC_OFFSET,	0
    67                                  	numdef EXEC_SEGMENT,	0
    68                                  	numdef IMAGE_EXE,	0
    69                                  %if ! _IMAGE_EXE && _TEST_PROGRAM
    70                                   %error Test program can only be used as EXE.
    71                                  %endif
    72                                  	numdef IMAGE_EXE_CS,	-16	; relative-segment for CS
    73                                  	numdef IMAGE_EXE_IP,	256 +64	; value for IP
    74                                  		; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0.
    75                                  	numdef IMAGE_EXE_SS,	-16	; relative-segment for SS
    76                                  	numdef IMAGE_EXE_SP,	0FFFEh	; value for SP (0 underflows)
    77                                  	numdef IMAGE_EXE_AUTO_STACK,	0, 2048	; use stack behind image
    78                                  		; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of
    79                                  		;  the same name. This one is only used as a flag; if non-zero,
    80                                  		;  keep the stack given to us by iniload; if zero, set up the
    81                                  		;  stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP.
    82                                  	numdef IMAGE_EXE_GET_COM_STACK, 0
    83                                  					; set up stack for flat .COM style entry
    84                                  	numdef DEVICE,			0
    85                                  	gendef DEVICE_NAME,		""
    86                                  	numdef DEVICE_ATTRIBUTE,	8000h
    87                                  	numdef DEVICE_ZERO_ENTRYPOINT,	0
    88                                  	numdef BOOTLDR,		1	; support boot loaded entrypoint
    89                                  
    90                                  	numdef BRIEFLZ,		0
    91                                  	numdef LZ4,		0
    92                                  	numdef SNAPPY,		0
    93                                  	numdef EXODECR,		0
    94                                  	numdef X,		0
    95                                  	numdef HEATSHRINK,	0
    96                                  	numdef LZD,		0
    97                                  	numdef LZO,		0
    98                                  	numdef LZSA2,		0
    99                                  	numdef APL,		0
   100                                  	numdef BZP,		0
   101                                  	numdef ZEROCOMP,	0
   102                                  	numdef MVCOMP,		0
   103                                  	numdef LZEXEDAT,	0
   104                                  %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK 	+ !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP 	+ !!_MVCOMP + !!_LZEXEDAT) != 1
   107                                   %fatal Exactly one compression method must be selected.
   108                                  %endif
   109                                  %assign ADDITIONAL_MEMORY 0
   110                                  %if _BRIEFLZ
   111                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BLZ"
   112                                  %elif _LZ4
   113                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ4"
   114                                  %elif _SNAPPY
   115                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SZ"
   116                                  %elif _EXODECR
   117                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.EXO"
   118                                  %elif _X
   119                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.X"
   120                                  %elif _HEATSHRINK
   121                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.HS"
   122                                  %elif _LZD
   123                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ"
   124                                  %elif _LZO
   125                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZO"
   126                                  %elif _LZSA2
   127                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SA2"
   128                                  %elif _APL
   129                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.APL"
   130                                  %elif _BZP
   131                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BZP"
   132                                  %elif _ZEROCOMP
   133                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.ZER"
   134                                  %elif _MVCOMP
   135                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.MV"
   136                                  %elif _LZEXEDAT
   137                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZE"
   138                                  %endif
   139                                  	numdef PAYLOAD_KERNEL_MAX_PARAS,	0, 0
   140                                  %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE)
   141                                   %error Kernel mode max paras requires building dual-mode or triple-mode executable
   142                                  %endif
   143                                  	numdef COUNTER,		0, 32
   144                                  %if (_COUNTER - 1) & _COUNTER
   145                                   %error COUNTER must be a power of two
   146                                  %endif
   147                                  	numdef PROGRESS,	0, 1
   148                                  	numdef PROGRESSAMOUNT,	0, 0
   149                                  	numdef PROGRESSMULTI,	1
   150                                  	numdef PROGRESSVAR,	1
   151                                  	numdef PROGRESSVARNAME, ""
   152                                  	numdef PROGRESSDEFAULT,	0
   153                                  	numdef PROGRESSDEFAULTAPP,	_PROGRESSDEFAULT
   154                                  	numdef PROGRESSDEFAULTDEVICE,	_PROGRESSDEFAULT
   155                                  	numdef PROGRESSDEFAULTBOOT,1
   156                                  	numdef PASSLCFG, 0
   157                                  	numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG
   158                                  
   159                                  
   160                                  %define MODULE inicomp
   161                                  	strdef INILOAD_CFG, ""
   162                                  %ifnidn _INILOAD_CFG, ""
   163                                   %include _INILOAD_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> strdef INILOAD_SIGNATURE, "OS"
     3                              <1> %assign _DEVICE 0
     4                              <1> %ifidni module, lkernpl
     5                              <1>  %define _PAYLOAD_FILE "msbio.bin"
     6                              <1> %endif
     7                              <1> %define _PAYLOAD_BIO_FILE "msbio.bin"
     8                              <1> %define _PAYLOAD_DOS_FILE "empty.bin"
     9                              <1> %ifn _TEST_PROGRAM
    10                              <1>  numdef SECOND_PAYLOAD_EXE, 1
    11                              <1>  strdef SECOND_PAYLOAD_FILE, "tmp/payload2.bin"
    12                              <1>  numdef SECOND_PAYLOAD_EXE_IP, 256
    13                              <1>  numdef SECOND_PAYLOAD_EXE_AUTO_STACK, 2048, 2048
    14                              <1>  numdef SECOND_PAYLOAD_EXE_MIN, 68048
    15                              <1> 
    16                              <1>  numdef SECOND_PAYLOAD_EXE_MAX, 0
    17                              <1>  strdef EXE_TRAIL_INCBIN, "tmp/trail.bin"
    18                              <1> %endif
   164                                  %endif
   165                                  	strdef LCFG_CFG, ""
   166                                  
   167                                  %if _DEVICE
   168                                   %ifidn _DEVICE_NAME, ""
   169                                    %error Device name must be set
   170                                   %endif
   171                                  %endif
   172                                  
   173                                  
   174                                  	cpu 8086
   175                                  	addsection INIT0, start=0 vstart=0
   176                                  init0_start:
   177                                  %if _DEVICE
   178                                  		; The device header is of a fixed format.
   179                                  		;  For our purposes, the 4-byte code for
   180                                  		;  each the strategy entry and the
   181                                  		;  interrupt entry is part of this format.
   182                                  		; (DOS may read the attributes or entrypoint
   183                                  		;  offsets before calling either, so in the inicomp
   184                                  		;  stage we need to recreate in the entrypoints part
   185                                  		;  exactly what the application has here.)
   186                                  		; _PASSLCFG: The lCFG block is passed in the dword
   187                                  		;  behind the interrupt entry.
   188                                  device_header:
   189                                  .next:
   190                                   %if _DEVICE_ZERO_ENTRYPOINT
   191                                  	fill 2, -1, jmp strict short j_zero_entrypoint
   192                                  	dw -1
   193                                   %else
   194                                  	dd -1				; link to next device
   195                                   %endif
   196                                  .attributes:
   197                                  	dw _DEVICE_ATTRIBUTE		; attributes
   198                                  .strategy:
   199                                  	dw .strategy_entry		; -> strategy entry
   200                                  .interrupt:
   201                                  	dw .interrupt_entry		; -> interrupt entry
   202                                  .name:
   203                                  	fill 8, 32, db _DEVICE_NAME	; character device name,
   204                                  					;  or block device number of units
   205                                  					;  + optional name
   206                                  .strategy_entry:
   207                                  	fill 4, 90h, jmp device_entrypoint
   208                                  .interrupt_entry:
   209                                  	fill 4, 90h, retf
   210                                  .pass_lcfg:
   211                                  %endif
   212                                  
   213                                  
   214                                  %if _IMAGE_EXE || _DEVICE
   215 00000000 90                      	nop
   216 00000001 90<rep 1Fh>             	align 32, nop
   217                                  init0_kernel_entry:
   218                                  		; cs:ip = load seg : 32 here
   219                                  %if ($ - $$) != 32
   220                                   %error Wrong kernel mode entrypoint
   221                                  %endif
   222                                  %if _TEST_PROGRAM
   223                                  @@:
   224 00000020 CC                      	int3
   225 00000021 FB                      	sti
   226 00000022 F4                      	hlt
   227 00000023 EBFB                    	jmp @B
   228                                  %endif
   229                                  %if _BOOTLDR
   230                                  %if ! _IMAGE_EXE
   231                                  j_zero_entrypoint:
   232                                  %endif
   233 00000025 31DB                    	xor bx, bx		; 0 = kernel mode
   234 00000027 50                      	push ax
   235 00000028 8CC8                    	mov ax, cs
   236 0000002A 83C040                  	add ax, (init0_end - init0_start) >> 4
   237 0000002D 8B56E2                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   238 00000030 BE6000                  	mov si, 60h		; => destination
   239 00000033 EB7E                    	jmp init0_common
   240                                  %endif
   241                                  
   242                                   %if _IMAGE_EXE
   243 00000035 90<rep Bh>              	align 64, nop
   244                                  j_zero_entrypoint:
   245                                  init0_exe_entry:
   246                                  		; NOTE:	This part is called with ip = 256 + 64, cs = PSP.
   247                                  %if ($ - $$) != 64
   248                                   %error Wrong EXE mode entrypoint
   249                                  %endif
   250                                  %if _IMAGE_EXE_GET_COM_STACK
   251                                  	mov bx, ds		; => PSP
   252                                  	dec bx			; => MCB
   253                                  	mov ds, bx
   254                                  	add bx, word [3]	; add size of memory block
   255                                  	sub bx, -1 + paras(512)	; add one, then subtract enough paragraphs
   256                                  	cli
   257                                  	mov ss, bx
   258                                  	mov sp, 512		; -> new stack
   259                                  	sti
   260                                  %endif
   261 00000040 BB0100                  	mov bx, 1		; EXE mode
   262 00000043 50                      	push ax
   263                                    %if _TEST_PROGRAM
   264 00000044 BE8100                  	mov si, 81h
   265 00000047 31D2                    	xor dx, dx
   266 00000049 31C0                    	xor ax, ax
   267                                  cmdline:
   268                                  .:
   269 0000004B AC                      	lodsb
   270 0000004C 3C09                    	cmp al, 9
   271 0000004E 74FB                    	je .
   272 00000050 3C20                    	cmp al, 32
   273 00000052 74F7                    	je .
   274 00000054 3C0D                    	cmp al, 13
   275 00000056 744E                    	je .end
   276 00000058 3C30                    	cmp al, '0'
   277 0000005A 721E                    	jb .notdigit
   278 0000005C 3C39                    	cmp al, '9'
   279 0000005E 771A                    	ja .notdigit
   280                                  .digit:
   281 00000060 2C30                    	sub al, '0'
   282 00000062 89D1                    	mov cx, dx		; times 1
   283 00000064 01D2                    	add dx, dx
   284 00000066 722A                    	jc .invalid
   285 00000068 01D2                    	add dx, dx		; times 4
   286 0000006A 7226                    	jc .invalid
   287 0000006C 01CA                    	add dx, cx		; times 5
   288 0000006E 7222                    	jc .invalid
   289 00000070 01D2                    	add dx, dx		; times 10
   290 00000072 721E                    	jc .invalid
   291 00000074 01C2                    	add dx, ax		; add in low digit
   292 00000076 721A                    	jc .invalid
   293 00000078 EBD1                    	jmp .
   294                                  
   295                                  .notdigit:
   296 0000007A 3C41                    	cmp al, 'A'
   297 0000007C 7419                    	je .a
   298 0000007E 3C61                    	cmp al, 'a'
   299 00000080 7415                    	je .a
   300 00000082 3C42                    	cmp al, 'B'
   301 00000084 7416                    	je .b
   302 00000086 3C62                    	cmp al, 'b'
   303 00000088 7412                    	je .b
   304 0000008A 3C43                    	cmp al, 'C'
   305 0000008C 7413                    	je .c
   306 0000008E 3C63                    	cmp al, 'c'
   307 00000090 740F                    	je .c
   308                                  .invalid:
   309 00000092 BAFFFF                  	mov dx, -1		; invalid
   310 00000095 EB0F                    	jmp .end
   311                                  
   312                                  .a:
   313 00000097 80E77F                  	and bh, ~ 80h		; A mode. determine min alloc size
   314 0000009A EBAF                    	jmp .
   315                                  
   316                                  .b:
   317 0000009C 80CF80                  	or bh, 80h		; B mode. repeat depack, counter in command line
   318 0000009F EBAA                    	jmp .
   319                                  
   320                                  .c:
   321 000000A1 80CF40                  	or bh, 40h		; C mode. how often would the counter be called
   322 000000A4 EBA5                    	jmp .
   323                                  
   324                                  .end:
   325 000000A6 52                      	push dx
   326                                    %endif
   327 000000A7 8CD2                    	mov dx, ss		; => after end of available space
   328 000000A9 8CC8                    	mov ax, cs
   329 000000AB 83C050                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   330 000000AE 8CCE                    	mov si, cs
   331 000000B0 83C610                  	add si, 256 >> 4	; => destination
   332                                   %endif
   333                                  
   334                                  init0_common:
   335                                  		; REM:	This part must be position-independent, as it is
   336                                  		;	 called either with ip = init0_common (kernel mode
   337                                  		;	 or device mode)
   338                                  		;	 or ip = init0_common + 256 (application mode).
   339                                  		; INP:	si => depack destination
   340                                  		;	ax => source of payload + INIT1
   341                                  		;	dx => behind available memory
   342                                  		; OUT:	cs:ip -> init1_start:
   343                                  		;	ax => INIT1
   344                                  		;	dx => payload source
   345                                  		;	si => depack destination
   346                                  		;	bx = mode
   347 000000B3 FC                      	cld
   348                                  %if _TEST_PROGRAM
   349 000000B4 81EAA70D                	sub dx, ( (payload_end - payload) ) >> 4
   350 000000B8 721A                    	jc .error
   351 000000BA B9FD21                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   357 000000BD 29CA                    	sub dx, cx
   358 000000BF 7213                    	jc .error
   359 000000C1 39C2                    	cmp dx, ax
   360 000000C3 720F                    	jb .error
   361                                  %else
   362                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   367                                  				; cx = amount paragraphs in INIT0B + payload + INIT1
   368                                  	sub dx, cx		; => destination for INIT0B + payload + INIT1
   369                                  				;  (highest possible spot in available memory)
   370                                  %endif
   371 000000C5 56                      	push si			; preserve destination
   372 000000C6 E86700                  	call init0_movp		; move up payload + INIT1
   373 000000C9 5E                      	pop si
   374                                  %else
   375                                  	cld
   376                                  	mov ax, cs
   377                                  	add ax, (init0_end - init0_start) >> 4
   378                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   383                                  	mov dx, word [ bp + ldLoadTop ]
   384                                  	sub dx, cx
   385                                  	call init0_movp
   386                                  %endif
   387                                  
   388                                  %if _LCFG && ! _TEST_PROGRAM
   389                                  	push cs
   390                                  	call @F			; position-independent far pointer
   391                                  @@:
   392                                  	pop ax
   393                                  	add ax, lcfg - @B	; -> lCFG block
   394                                  	push ax
   395                                  %endif
   396                                  
   397 000000CA 89D0                    	mov ax, dx		; => INIT0B
   398                                  				;  (same as => payload if INIT0B is empty)
   399                                  %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM
   400                                  	add dx, ( 		+ (init0b_end - init0b_start) 		) >> 4		; => payload
   403                                  %else
   404                                   %if _TEST_PROGRAM
   405 000000CC 05070E                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4		; => INIT2
   410                                   %else
   411                                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   415                                   %endif
   416                                  %endif
   417 000000CF 31C9                    	xor cx, cx
   418 000000D1 50                      	push ax
   419 000000D2 51                      	push cx
   420 000000D3 CB                      	retf			; jump to relocated
   421                                  				;  INIT0B:init0b_start
   422                                  				;  or INIT1:init1_start
   423                                  				;  or INIT2:init2_start
   424                                  
   425                                  
   426                                  %if _TEST_PROGRAM
   427                                  .error:
   428 000000D4 89DF                    	mov di, bx		; whichtest
   429                                  
   430 000000D6 0E                      	push cs
   431 000000D7 1F                      	pop ds
   432 000000D8 BA[B202]                	mov dx, init0_msg.error_stderr + 256
   433 000000DB B92500                  	mov cx, init0_msg.error_stderr.length
   434 000000DE BB0200                  	mov bx, 2
   435 000000E1 B440                    	mov ah, 40h
   436 000000E3 CD21                    	int 21h
   437                                  
   438 000000E5 F7C70040                	test di, 4000h		; whichtest
   439 000000E9 7408                    	jz @F
   440 000000EB BA[D702]                	mov dx, init0_msg.error_c_stdout + 256
   441 000000EE B90300                  	mov cx, init0_msg.error_c_stdout.length
   442 000000F1 EB0A                    	jmp @FF
   443                                  @@:
   444 000000F3 85FF                    	test di, di		; whichtest
   445 000000F5 780D                    	js @FF
   446 000000F7 BA[D702]                	mov dx, init0_msg.error_stdout + 256
   447 000000FA B90300                  	mov cx, init0_msg.error_stdout.length
   448                                  @@:
   449 000000FD BB0100                  	mov bx, 1
   450 00000100 B440                    	mov ah, 40h
   451 00000102 CD21                    	int 21h
   452                                  @@:
   453 00000104 B8FF4C                  	mov ax, 4CFFh
   454 00000107 CD21                    	int 21h
   455                                  %endif
   456                                  
   457                                  
   458                                  %if _LCFG
   459                                  	%imacro lcfgoption 3+.nolist
   460                                  	_fill %1, 0, lcfg
   461                                  %%start:
   462                                  	%2
   463                                  	%3
   464                                  %%end:
   465                                  %assign %%index %%start - lcfg
   466                                  %rep %%end - %%start
   467                                  %assign LCFGINUSE LCFGINUSE | (1 << %%index)
   468                                   %assign %%index %%index + 1
   469                                  %endrep
   470                                  	%endmacro
   471                                  %assign LCFGINUSE 0
   472                                  
   473 00000109 90<rep 7h>              	align 16
   474                                  lcfg:
   475 00000110 EB1E                    .:		jmp strict short .end
   476 00000112 6C434647                lcfgoption 2,,	db "lCFG"
   477 00000116 3030                    lcfgoption 6,,	db "00"
   478 00000118 FCFFF50C00000000        lcfgoption 8,,	dq .inuse
   479                                   %if _PROGRESS && _PROGRESSMULTI
   480                                    %if _IMAGE_EXE
   481 00000120 00                      lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP
   482                                    %endif
   483                                    %if _DEVICE
   484                                  lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE
   485                                    %endif
   486                                    %if _BOOTLDR
   487 00000121 0001                    lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT
   488                                    %endif
   489                                   %endif
   490                                  
   491                                  %ifnidn _LCFG_CFG, ""
   492                                   %include _LCFG_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> %include "src/INC/scanptab.mac"
     1                              <2> 
     2                              <2> %if 0
     3                              <2> 
     4                              <2> scanptab - Scan partition table (macros)
     5                              <2>  2019, 2025 by E. C. Masloch
     6                              <2> 
     7                              <2> Usage of the works is permitted provided that this
     8                              <2> instrument is retained with the works, so that any entity
     9                              <2> that uses the works is notified of this instrument.
    10                              <2> 
    11                              <2> DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                              <2> 
    13                              <2> %endif
    14                              <2> 
    15                              <2> mode_all_ext5			equ 00b
    16                              <2> mode_ignore_ext5		equ 01b
    17                              <2> mode_first_ext5			equ 10b
    18                              <2> mode_first_type_ext5		equ 11b
    19                              <2> 
    20                              <2> mode_all_ext15			equ 00b << 2
    21                              <2> mode_ignore_ext15		equ 01b << 2
    22                              <2> mode_first_ext15		equ 10b << 2
    23                              <2> mode_first_type_ext15		equ 11b << 2
    24                              <2> 
    25                              <2> mode_all_ext85			equ 00b << 4
    26                              <2> mode_ignore_ext85		equ 01b << 4
    27                              <2> mode_first_ext85		equ 10b << 4
    28                              <2> mode_first_type_ext85		equ 11b << 4
    29                              <2> 
    30                              <2> mode_ignore_subsequent_nested	equ            1_00_00_00b
    31                              <2> mode_ignore_subsequent_logical	equ           10_00_00_00b
    32                              <2> mode_ignore_subsequent_primary	equ          100_00_00_00b
    33                              <2> mode_traditional_order_logical	equ         1000_00_00_00b
    34                              <2> mode_active_priority		equ       1_0000_00_00_00b
    35                              <2> mode_subsequent_primary_after	equ      10_0000_00_00_00b
    36                              <2> mode_disable_fat32		equ 00_1000_0000_00_00_00b
    37                              <2> mode_disable_lba		equ 01_0000_0000_00_00_00b
    38                              <2> mode_dlasort_zero		equ 10_0000_0000_00_00_00b
     3                              <1> %include "src/INC/verbose.mac"
     1                              <2> 
     2                              <2> ; Public Domain, 2025 by E. C. Masloch
     3                              <2> 
     4                              <2> verbose_intro	equ 1
     5                              <2> verbose_xms	equ 2
     6                              <2> verbose_cds	equ 4
     4                              <1> %include "src/INC/haltflag.mac"
     1                              <2> 
     2                              <2> ; Public Domain
     3                              <2> 
     4                              <2> flag_no_halt_tagcrash	equ 1
     5                              <2> flag_no_halt_mcb	equ 2
     6                              <2> flag_no_halt_hmcb	equ 4
     7                              <2> flag_no_halt_hmcb_free	equ 8
     5 00000123 0000                <1> lcfgoption 20, .checkdebugger:, db 0
     6 00000125 01                  <1> lcfgoption 21, .verbose:, db verbose_intro
     7 00000126 0000                <1> lcfgoption 22, .scanmode:, dw 0
     8 00000128 00<rep 2h>0C00      <1> lcfgoption 26, .haltflag:, dw 0 | flag_no_halt_hmcb | flag_no_halt_hmcb_free
   493                                  %endif
   494                                  
   495 0000012C 00<rep 4h>              lcfgoption 32,,
   496                                  .end:
   497                                  .size: equ .end - .
   498                                  .inuse equ LCFGINUSE
   499                                  %endif
   500                                  
   501                                  
   502                                  %if _DEVICE
   503                                  device_entrypoint:
   504                                  %if _TEST_PROGRAM
   505                                  @@:
   506                                  	int3
   507                                  	sti
   508                                  	hlt
   509                                  	jmp @B
   510                                  %endif
   511                                  	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   512                                  	je @F
   513                                  
   514                                  	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   515                                  	retf
   516                                  
   517                                  @@:
   518                                  	or word [cs:device_header.next], -1
   519                                  	push cs
   520                                  	push word [cs:device_header.strategy]
   521                                  					; -> far return to payload's strategy
   522                                  	push bp
   523                                  	push ds
   524                                  	push si
   525                                  	push di
   526                                  	push dx
   527                                  	push cx
   528                                  	push ax
   529                                  	push bx
   530                                  	push es
   531                                  
   532                                  	mov dx, word [es:bx + 14]
   533                                  	mov cl, 4
   534                                  	shr dx, cl		; = how many full paragraphs (rounded down)
   535                                  	add dx, word [es:bx + 14 + 2]
   536                                  				; ax => behind end
   537                                  
   538                                  	mov di, cs
   539                                  image_size: equ  ( 		+ (init0_end - init0_start) 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   545                                  	add di, image_size >> 4		; di => end of image
   546                                  
   547                                  	cmp dx, di			; enough memory to hold all of us ?
   548                                  	jb @F				; no -->
   549                                  				; yes
   550                                  .have_some_memory:
   551                                  				; dx => after end of memory
   552                                  	mov bx, 2		; device mode
   553                                  	push ax
   554                                  	mov ax, cs
   555                                  	add ax, (init0_end - init0_start) >> 4
   556                                  	mov si, cs		; => destination
   557                                  	jmp init0_common
   558                                  
   559                                  
   560                                  @@:
   561                                  	push cs
   562                                  	pop ds
   563                                  	mov dx, .msg_no_memory
   564                                  	mov ah, 09h
   565                                  	int 21h
   566                                  
   567                                  	mov ax, 3000h
   568                                  	int 21h
   569                                  	cmp al, 5
   570                                  	jae @F
   571                                  	mov dx, .msg_dos_below_5
   572                                  	mov ah, 09h
   573                                  	int 21h
   574                                  @@:
   575                                  
   576                                  	mov dx, .msg_linebreak
   577                                  	mov ah, 09h
   578                                  	int 21h
   579                                  
   580                                  		; tear down the stack frame and modify the request header
   581                                  	pop es
   582                                  	pop bx
   583                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   584                                  	mov byte [es:bx + 13], 0	; set number of units = 0
   585                                  	mov word [es:bx + 14 + 2], cs
   586                                  	and word [es:bx + 14], 0	; -> after end of memory to allocate
   587                                  	pop ax
   588                                  	pop cx
   589                                  	pop dx
   590                                  	pop di
   591                                  	pop si
   592                                  	pop ds
   593                                  	pop bp
   594                                  	add sp, 4		; discard far return to payload's strategy
   595                                  	retf			; return to DOS
   596                                  
   597                                  
   598                                  .msg_no_memory:		ascic "Load error: Not enough memory."
   599                                  .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   600                                  .msg_linebreak:		ascic 13,10
   601                                  %endif
   602                                  
   603                                  
   604                                  		; Move paragraphs
   605                                  		;
   606                                  		; INP:	ax => source
   607                                  		;	dx => destination
   608                                  		;	cx = number of paragraphs
   609                                  		; CHG:	cx, ds, si, es, di
   610                                  		; OUT:	ax and dx unchanged
   611                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   612                                  		;	Do not provide a wrapped/HMA source or destination!
   613                                  init0_movp:
   614 00000130 39D0                    	cmp ax, dx		; source above destination ?
   615 00000132 770A                    	ja .up			; yes, move up (forwards) -->
   616 00000134 747B                    	je .return		; same, no need to move -->
   617 00000136 50                      	push ax
   618 00000137 01C8                    	add ax, cx		; (expected not to carry)
   619 00000139 39D0                    	cmp ax, dx		; end of source is above destination ?
   620 0000013B 58                      	pop ax
   621 0000013C 7730                    	ja .down		; yes, move from top down -->
   622                                  	; Here, the end of source is below-or-equal the destination,
   623                                  	;  so they do not overlap. In this case we prefer moving up.
   624                                  
   625                                  .up:
   626 0000013E 50                      	push ax
   627 0000013F 52                      	push dx
   628                                  .uploop:
   629 00000140 8ED8                    	mov ds, ax
   630 00000142 8EC2                    	mov es, dx
   631 00000144 31FF                    	xor di, di
   632 00000146 31F6                    	xor si, si		; -> start of segment
   633 00000148 81E90010                	sub cx, 1000h		; 64 KiB left ?
   634 0000014C 7610                    	jbe .uplast		; no -->
   635 0000014E 51                      	push cx
   636 0000014F B90080                  	mov cx, 10000h /2
   637 00000152 F3A5                    	rep movsw		; move 64 KiB
   638 00000154 59                      	pop cx
   639 00000155 050010                  	add ax, 1000h
   640 00000158 81C20010                	add dx, 1000h		; -> next segment
   641 0000015C EBE2                    	jmp short .uploop	; proceed for more -->
   642                                  .uplast:
   643 0000015E 81C10010                	add cx, 1000h		; restore counter
   644 00000162 D1E1                    	shl cx, 1
   645 00000164 D1E1                    	shl cx, 1
   646 00000166 D1E1                    	shl cx, 1		; *8, paragraphs to words
   647 00000168 F3A5                    	rep movsw		; move last part
   648 0000016A 5A                      	pop dx
   649 0000016B 58                      	pop ax
   650 0000016C EB43                    	jmp short .return
   651                                  
   652                                  .down:
   653 0000016E FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   654                                  .dnloop:
   655 0000016F 81E90010                	sub cx, 1000h		; 64 KiB left ?
   656 00000173 761A                    	jbe .dnlast		; no -->
   657 00000175 50                      	push ax
   658 00000176 52                      	push dx
   659 00000177 01C8                    	add ax, cx
   660 00000179 01CA                    	add dx, cx
   661 0000017B 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   662 0000017D 8EC2                    	mov es, dx
   663 0000017F 5A                      	pop dx
   664 00000180 58                      	pop ax
   665 00000181 BFFEFF                  	mov di, -2
   666 00000184 89FE                    	mov si, di		; moved from last word down
   667 00000186 51                      	push cx
   668 00000187 B90080                  	mov cx, 10000h /2
   669 0000018A F3A5                    	rep movsw		; move 64 KiB
   670 0000018C 59                      	pop cx
   671 0000018D EBE0                    	jmp short .dnloop	; proceed for more -->
   672                                  .dnlast:
   673 0000018F 81C10010                	add cx, 1000h		; restore counter
   674 00000193 D1E1                    	shl cx, 1
   675 00000195 D1E1                    	shl cx, 1
   676 00000197 D1E1                    	shl cx, 1		; *8, paragraphs to words
   677 00000199 89CF                    	mov di, cx
   678 0000019B 4F                      	dec di
   679 0000019C D1E7                    	shl di, 1		; words to offset, -> last word
   680 0000019E 89FE                    	mov si, di
   681 000001A0 8ED8                    	mov ds, ax
   682 000001A2 8EC2                    	mov es, dx		; first segment correct
   683                                  
   684                                  
   685                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   686                                  %if 0
   687                                  
   688                                  Jack R. Ellis pointed out this erratum:
   689                                  
   690                                  Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
   691                                  
   692                                  109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
   693                                  
   694                                  Description
   695                                  
   696                                  In certain situations a REP MOVS instruction may lead to
   697                                  incorrect results. An incorrect address size, data size
   698                                  or source operand segment may be used or a succeeding
   699                                  instruction may be skipped. This may occur under the
   700                                  following conditions:
   701                                  
   702                                  * EFLAGS.DF=1 (the string is being moved in the reverse direction).
   703                                  
   704                                  * The number of items being moved (RCX) is between 1 and 20.
   705                                  
   706                                  * The REP MOVS instruction is preceded by some microcoded instruction
   707                                    that has not completely retired by the time the REP MOVS begins
   708                                    execution. The set of such instructions includes BOUND, CLI, LDS,
   709                                    LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
   710                                  
   711                                  Potential Effect on System
   712                                  
   713                                  Incorrect results may be produced or the system may hang.
   714                                  
   715                                  Suggested Workaround
   716                                  
   717                                  Contact your AMD representative for information on a BIOS update.
   718                                  
   719                                  %endif
   720                                  
   721                                  %if _AMD_ERRATUM_109_WORKAROUND
   722 000001A4 E308                    	jcxz @FF
   723 000001A6 83F914                  	cmp cx, 20
   724 000001A9 7703                    	ja @FF
   725                                  @@:
   726 000001AB A5                      	movsw
   727 000001AC E2FD                    	loop @B
   728                                  @@:
   729                                  %endif
   730 000001AE F3A5                    	rep movsw		; move first part
   731 000001B0 FC                      	cld
   732                                  .return:
   733 000001B1 C3                      	retn
   734                                  
   735                                  
   736                                  	addsection INIT0B, align=16 vstart=0 follows=INIT0
   737                                  		; INP:	ax:cx = cs:ip = cs:0
   738                                  		;	ax => INIT0B
   739                                  		;	dx => payload source
   740                                  		;	ss:sp -> (dword pointer to lCFG block)
   741                                  		;	if app/device mode supported:
   742                                  		;	 si => depack destination
   743                                  		;	 bx = mode
   744                                  init0b_start:
   745                                  %if _LCFG || _PROGRESS
   746                                  
   747 00000000 05B80D                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   751                                  
   752                                  %if _LCFG && _PASSLCFG
   753                                   %if (_IMAGE_EXE || _DEVICE)
   754 00000003 89F1                    	mov cx, si		; preserve si
   755                                   %endif
   756 00000005 5E                      	pop si
   757 00000006 1F                      	pop ds			; -> lCFG block
   758 00000007 8EC0                    	mov es, ax
   759 00000009 BF[D004]                	mov di, transfer_lcfg_block
   760                                  				; -> destination
   761                                   %if (_IMAGE_EXE || _DEVICE)
   762 0000000C 51                      	push cx
   763                                   %endif
   764 0000000D 57                      	push di
   765 0000000E B91000                  	mov cx, words(lcfg.size)
   766 00000011 F3A5                    	rep movsw		; cx = 0
   767 00000013 5F                      	pop di			; es:di -> relocated lCFG block, same difference
   768                                   %if (_IMAGE_EXE || _DEVICE)
   769 00000014 5E                      	pop si			; preserve si
   770                                   %endif
   771                                  %elif _LCFG
   772                                  	pop di
   773                                  	pop es			; es:di -> (original) lCFG block
   774                                  %endif
   775                                  
   776 00000015 50                      	push ax
   777 00000016 51                      	push cx			; -> far return address to init1_start
   778                                  
   779                                  %if _PROGRESS && _PROGRESSMULTI
   780                                   %if (_IMAGE_EXE || _DEVICE)
   781 00000017 56                      	push si
   782 00000018 53                      	push bx
   783                                   %endif
   784                                   %if _BOOTLDR
   785                                    %if _LCFG
   786 00000019 31C0                    	xor ax, ax
   787 0000001B 268A4512                	mov al, byte [es:di + lcfg.progress_boot - lcfg]
   788 0000001F 97                      	xchg di, ax		; di = boot default progress
   789                                  				; es:ax -> lCFG block
   790                                    %else			; _LCFG
   791                                  	mov di, _PROGRESSDEFAULTBOOT
   792                                    %endif		; _LCFG
   793                                   %endif			; _BOOTLDR
   794                                   %if (_IMAGE_EXE || _DEVICE)
   795                                    %if _BOOTLDR
   796 00000020 85DB                    	test bx, bx
   797 00000022 7503E9A700              	jz .default
   798                                    %endif		; _BOOTLDR
   799                                    %if _LCFG
   800 00000027 06                      	push es
   801                                     %if _BOOTLDR
   802 00000028 50                      	push ax			; -> lCFG block
   803                                     %else		; _BOOTLDR
   804                                  	push di
   805                                     %endif		; _BOOTLDR
   806                                    %endif		; _LCFG
   807                                    %if _PROGRESSVAR
   808 00000029 B451                    	mov ah, 51h
   809 0000002B CD21                    	int 21h
   810                                  @@:
   811 0000002D 8EDB                    	mov ds, bx
   812 0000002F A12C00                  	mov ax, word [2Ch]
   813 00000032 85C0                    	test ax, ax
   814 00000034 7510                    	jnz .gotenv
   815 00000036 A11600                  	mov ax, word [16h]
   816 00000039 40                      	inc ax
   817 0000003A 7469                    	jz .default_nonboot
   818 0000003C 48                      	dec ax
   819 0000003D 7466                    	jz .default_nonboot
   820 0000003F 39C3                    	cmp bx, ax
   821 00000041 7462                    	je .default_nonboot
   822 00000043 93                      	xchg bx, ax
   823 00000044 EBE7                    	jmp @B
   824                                  
   825                                  .gotenv:
   826 00000046 0E                      	push cs
   827 00000047 1F                      	pop ds				; => cs
   828 00000048 8EC0                    	mov es, ax			; => environment
   829                                   %ifnidni _PROGRESSVARNAME, ""
   830 0000004A BB[FA00]                	mov bx, progressvarname1
   831 0000004D E80C00                  	call .findenv
   832 00000050 732E                    	jnc .foundenv			; match -->
   833 00000052 BB[FD00]                	mov bx, progressvarname2
   834                                   %endif
   835 00000055 E80400                  	call .findenv
   836 00000058 7326                    	jnc .foundenv			; match -->
   837 0000005A EB49                    	jmp .default_nonboot
   838                                  
   839                                  .findenv:
   840 0000005C 31FF                    	xor di, di
   841                                  @@:
   842                                   %ifnidni _PROGRESSVARNAME, ""
   843 0000005E 89DE                    	mov si, bx			; -> variable name
   844                                   %else
   845                                  	mov si, progressvarname2	; -> variable name
   846                                   %endif
   847 00000060 31C0                    	xor ax, ax
   848 00000062 AC                      	lodsb				; get length
   849 00000063 91                      	xchg cx, ax			; cx = length
   850 00000064 57                      	push di
   851 00000065 F3A6                    	repe cmpsb			; match ?
   852 00000067 7415                    	je .findret_pop			; (NC) yes -->
   853 00000069 5F                      	pop di
   854 0000006A B90080                  	mov cx, 8000h			; maximum env size
   855 0000006D 29F9                    	sub cx, di			; any left ?
   856 0000006F 760B                    	jbe .findret_CY			; no -->
   857 00000071 B000                    	mov al, 0
   858 00000073 F2AE                    	repne scasb			; find next NUL
   859 00000075 7505                    	jne .findret_CY
   860 00000077 263805                  	cmp byte [es:di], al		; double NUL ?
   861 0000007A 75E2                    	jne @B				; no, loop -->
   862                                  .findret_CY:
   863 0000007C F9                      	stc				; not found
   864 0000007D C3                      	retn
   865                                  
   866                                  .findret_pop:
   867 0000007E 59                      	pop cx
   868 0000007F C3                      	retn
   869                                  
   870                                  .foundenv:
   871                                  %if _LCFG
   872 00000080 5E                      	pop si
   873 00000081 5E                      	pop si				; discard far pointer to lCFG
   874                                  %endif
   875 00000082 89FE                    	mov si, di			; es:si -> var content
   876 00000084 31FF                    	xor di, di			; = 0
   877 00000086 31C0                    	xor ax, ax			; ah = 0
   878                                  @@:
   879 00000088 26AC                    	es lodsb			; next candidate digit
   880 0000008A 2C30                    	sub al, '0'			; digit ?
   881 0000008C 7212                    	jb @F				; no -->
   882 0000008E 3C09                    	cmp al, 9
   883 00000090 770E                    	ja @F				; no -->
   884 00000092 01FF                    	add di, di			; times 2
   885 00000094 89FB                    	mov bx, di
   886 00000096 01FF                    	add di, di			; times 4
   887 00000098 01FF                    	add di, di			; times 8
   888 0000009A 01DF                    	add di, bx			; times 8 + times 2 = times 10
   889 0000009C 01C7                    	add di, ax			; add in next digit
   890 0000009E EBE8                    	jmp @B				; and loop
   891                                  
   892                                  @@:
   893 000000A0 83E71F                  	and di, 31			; mask to low 5 bits
   894 000000A3 EB0B                    	jmp @F
   895                                    %endif	; _PROGRESSVAR
   896                                  
   897                                  .default_nonboot:
   898                                  %if _LCFG
   899 000000A5 5F                      	pop di
   900 000000A6 07                      	pop es			; -> lCFG block
   901 000000A7 5B                      	pop bx			; = 1 if app, = 2 if device
   902 000000A8 53                      	push bx
   903 000000A9 268B4510                	mov ax, word [es:di + lcfg.progress_app - lcfg]
   904                                   %if _DEVICE
   905                                    %if lcfg.progress_app + 1 != lcfg.progress_dev
   906                                     %error Unexpected layout
   907                                    %endif
   908                                  				; al = app, ah = device
   909                                  	dec bx
   910                                  	jz .default_app
   911                                  	xchg al, ah		; al = device
   912                                  .default_app:
   913                                   %endif			; _DEVICE
   914 000000AD B400                    	mov ah, 0		; ax = default
   915 000000AF 97                      	xchg di, ax		; di = default
   916                                  %else			; _LCFG
   917                                  	mov di, _PROGRESSDEFAULT
   918                                  %endif			; _LCFG
   919                                  @@:
   920 000000B0 F7C71000                	test di, 16
   921 000000B4 7405                    	jz @F
   922 000000B6 83E7EF                  	and di, ~16
   923 000000B9 EB13                    	jmp .outputdevice	; if 16 set skip device check
   924                                  @@:
   925 000000BB 52                      	push dx
   926 000000BC B80044                  	mov ax, 4400h		; IOCTL get device information
   927 000000BF BB0100                  	mov bx, 1		; StdOut
   928 000000C2 B283                    	mov dl, 83h		; default if 21.4400 fails
   929 000000C4 CD21                    	int 21h
   930 000000C6 F6C280                  	test dl, 80h
   931 000000C9 5A                      	pop dx
   932 000000CA 7502                    	jnz .outputdevice
   933 000000CC 31FF                    	xor di, di		; stdout is a file: force no progress marker
   934                                  .outputdevice:
   935                                   %endif			; (_IMAGE_EXE || _DEVICE)
   936                                  
   937                                  .default:
   938                                   %if (_IMAGE_EXE || _DEVICE)
   939 000000CE 5B                      	pop bx
   940 000000CF 5E                      	pop si
   941                                   %endif
   942 000000D0 83FF05                  	cmp di, step_progress_table.amount
   943                                  					; valid ?
   944 000000D3 7202                    	jb @F				; yes -->
   945 000000D5 31FF                    	xor di, di			; disable
   946                                  @@:
   947 000000D7 D1E7                    	shl di, 1			; = word index
   948 000000D9 59                      	pop cx				; = 0
   949 000000DA 1F                      	pop ds				; ds => INIT1
   950                                  
   951 000000DB 2E8B85[F000]            	mov ax, word [cs:step_progress_table + di]
   952                                  					; ax = rel16 for step progress handler
   953 000000E0 1E                      	push ds
   954 000000E1 51                      	push cx				; -> init1_start
   955 000000E2 A3[7200]                	mov word [step_progress.handler], ax
   956                                  					; patch it
   957                                  
   958 000000E5 83FF04                  	cmp di, 2 * 2			; none or dots ?
   959 000000E8 7305                    	jae @F				; no, skip -->
   960 000000EA C606[0600]A9            	mov byte [..@empty_step_progress], __TEST_IMM16
   961                                  					; for none and dots do not call here
   962                                  @@:
   963                                  %endif			;  _PROGRESS && _PROGRESSMULTI
   964 000000EF CB                      	retf
   965                                  %endif
   966                                  
   967                                  %if _PROGRESS && _PROGRESSMULTI
   968                                  		align 2, db 0
   969                                  step_progress_table:
   970                                  .:
   971 000000F0 1600                    		dw step_progress.0_step - step_progress.base
   972 000000F2 3B00                    		dw step_progress.1_step - step_progress.base
   973 000000F4 0000                    		dw step_progress.2_step - step_progress.base
   974 000000F6 4100                    		dw step_progress.3_step - step_progress.base
   975 000000F8 8600                    		dw step_progress.4_step - step_progress.base
   976                                  .amount equ ($ - .) / 2
   977                                  
   978                                   %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE)
   979                                    %ifnidni _PROGRESSVARNAME, ""
   980 000000FA 02003D                  progressvarname1:	counted _PROGRESSVARNAME, '='
   981                                    %endif
   982 000000FD 0D4C444F5350524F47-     progressvarname2:	counted "LDOSPROGRESS="
   982 00000106 524553533D         
   983                                   %endif
   984                                  %endif
   985                                  
   986 0000010B 90<rep 5h>              	align 16
   987                                  init0b_end:
   988                                  
   989                                  
   990                                  	addsection PAYLOAD, align=16 follows=INIT0B
   991                                  payload:
   992 00000000 <bin DA6Ch>             	incbin _PAYLOAD_FILE
   993                                  .end:
   994 0000DA6C 26<rep 4h>              	align 16, db 38
   995                                  payload_end:
   996                                  
   997                                  %if _OPTIMISE_INPUT_SMALL
   998                                   %ifn (payload_end - payload) <= 65_520
   999                                    %error Input declared small is not small
  1000                                   %endif
  1001                                  %else
  1002                                   %if (payload_end - payload) <= 65_520
  1003                                    %warning Input could be declared small
  1003          ******************       warning: Input could be declared small [-w+user]
  1004                                   %endif
  1005                                  %endif
  1006                                  
  1007                                  
  1008                                  	addsection INIT1, align=16 follows=PAYLOAD vstart=0
  1009                                  init1_start:
  1010                                  		; INP:	ax = cs = INIT1
  1011                                  		;	dx = cs - (payload_end - payload) >> 4 => source data
  1012                                  		;	if kernel mode:
  1013                                  		;	 ss:bp -> LOADDATA and LOADSTACKVARS
  1014                                  		;	 ss:sp -> valid stack above [bp + ldLoadTop]
  1015                                  		;	 60h => destination
  1016                                  		;	any mode:
  1017                                  		;	 ss:sp -> word value for ax
  1018                                  		;	 bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode
  1019                                  		;	 si => destination (60h for kernel mode,
  1020                                  		;		after PSP for EXE mode,
  1021                                  		;		at device header for device mode)
  1022                                  		;		(not set if only kernel mode supported)
  1023                                  		;	 if EXE mode:
  1024                                  		;	  ss:sp -> valid stack above INIT1
  1025                                  		;	  bp = unset
  1026                                  		;	 if device mode:
  1027                                  		;	  ss:sp -> device entrypoint stack
  1028                                  		;	  holds: es, bx, ax, cx, dx, di, si, ds, bp,
  1029                                  		;		  far address of payload strategy entrypoint,
  1030                                  		;		  far return address to DOS
  1031                                  		;	  bp = unset
  1032                                  		; STT:	UP
  1033                                  		; CHG:	ax, bx, cx, dx, es, ds, si, di
  1034                                  %if _IMAGE_EXE || _DEVICE
  1035                                  	lframe
  1036 00000000 5589E5                  	lenter
  1037                                  	lvar word,	exemode		; must be bp - 2!
  1038 00000003 53                      	 push bx
  1039                                   %if ?exemode != -2
  1040                                    %error exemode variable must be directly below bp
  1041                                   %endif
  1042 00000004 56                      	push si
  1043                                   %if _PROGRESS
  1044 00000005 F8                      	clc			; NC
  1045                                   %endif
  1046                                  %else
  1047                                  	xor bx, bx		; always tell them it is kernel mode (NC)
  1048                                  %endif
  1049                                  
  1050                                  %if _PROGRESS
  1051                                  	; clc
  1052                                  ..@empty_step_progress:		; SMC, byte patched to __TEST_IMM16 if none or dots
  1053                                   %if _TEST_PROGRAM
  1054 00000006 90<rep 3h>              	times 3 nop
  1055                                   %else
  1056                                  	call step_progress.CF	; display empty / 0.0%
  1057                                   %endif
  1058                                  @@:
  1059                                  %endif
  1060                                  
  1061                                  %if _IMAGE_EXE || _DEVICE
  1062 00000009 8EC6                    	mov es, si		; es => destination
  1063                                  %else
  1064                                  	mov ax, 60h
  1065                                  	mov es, ax		; es => destination
  1066                                  %endif
  1067 0000000B 31FF                    	xor di, di		; -> destination
  1068                                  
  1069 0000000D 8EDA                    	mov ds, dx
  1070 0000000F 31F6                    	xor si, si		; -> source
  1071                                  
  1072 00000011 B96CDA                  	mov cx, (payload.end - payload) & 0FFFFh
  1073                                  %if (payload.end - payload) >> 16
  1074                                  	mov dx, (payload.end - payload) >> 16	; = length of source
  1075                                  %else
  1076 00000014 31D2                    	xor dx, dx
  1077                                  %endif
  1078                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  1079                                  	mov ax, _PAYLOAD_KERNEL_MAX_PARAS
  1080                                  	test bx, bx
  1081                                  	jz @F
  1082                                  %endif
  1083 00000016 B8FFFF                  	mov ax, -1
  1084                                  @@:
  1085                                  
  1086                                  		; INP:	ds:si -> source
  1087                                  		;	dx:cx = length of source
  1088                                  		;	es:di -> destination (below source)
  1089                                  		;	bx = EXE mode flag
  1090                                  		;	 (1 if EXE mode, 0 if kernel mode)
  1091                                  		;	 (always 0 if this is a build without EXE mode)
  1092                                  		;	if _PAYLOAD_KERNEL_MAX_PARAS:
  1093                                  		;	 ax = maximum amount in paragraphs of destination needed
  1094                                  		;	 (-1 if full source should be decompressed)
  1095                                  		;	else:
  1096                                  		;	 ax = -1
  1097                                  		; Note:	The destination reaches up to below the source.
  1098 00000019 E8E701                  	call depack
  1099                                  %ifn _TEST_PROGRAM
  1100                                  	jc strict short error	; -2 (replaced by retf \ nop)
  1101                                  %endif
  1102                                  %if _IMAGE_EXE || _DEVICE
  1103 0000001C 5E                      	pop si			; si
  1104                                   %if _TEST_PROGRAM
  1105 0000001D 58                      	pop ax			; (discard ?exemode, leave bx as returned)
  1106                                   %else
  1107                                  	pop bx			; ?exemode
  1108                                   %endif
  1109 0000001E 5D                      	pop bp			; bp
  1110 0000001F 58                      	pop ax			; ax
  1111                                  	lleave ctx
  1112                                  %endif
  1113                                  %if _TEST_PROGRAM
  1114 00000020 CB                      	retf			; +1 (replace jc error)
  1115 00000021 90                      	nop			; +1
  1116                                  %endif
  1117                                  
  1118                                  %if _DEVICE
  1119                                  	test bl, 2
  1120                                  	jz .jmp_exe_or_kernel_mode
  1121                                  
  1122                                  .jmp_device_mode:
  1123                                  	mov ds, si
  1124                                  	or word [device_header.next], -1
  1125                                  %if _LCFG && _PASSLCFG
  1126                                  	mov word [device_header.pass_lcfg], transfer_lcfg_block
  1127                                  	mov word [device_header.pass_lcfg + 2], cs
  1128                                  %endif
  1129                                  	pop es
  1130                                  	pop bx
  1131                                  	pop ax
  1132                                  	pop cx
  1133                                  	pop dx
  1134                                  	pop di
  1135                                  	pop si
  1136                                  	pop ds
  1137                                  	pop bp
  1138                                  	retf			; transfer to payload strategy entrypoint
  1139                                  				; still on stack: far return address to DOS
  1140                                  
  1141                                  .jmp_exe_or_kernel_mode:
  1142                                  %endif
  1143                                  
  1144                                  %if _IMAGE_EXE
  1145 00000022 F6C301                  	test bl, 1
  1146 00000025 7415                    	jz .jmp_kernel_mode
  1147                                  
  1148                                  .jmp_exe_mode:
  1149                                  %if ! _IMAGE_EXE_AUTO_STACK
  1150                                  	mov cx, cs
  1151                                  	lea dx, [si + _IMAGE_EXE_SS]
  1152                                  	push dx			; stack = relocated ss value
  1153                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
  1154                                  	cmp cx, dx		; INIT1 code is above intended stack ?
  1155                                  	jae @F			; yes -->
  1156                                  
  1157                                  	lframe
  1158                                  	lenter
  1159                                  	lvar	word, exemode
  1160                                  	 push bx
  1161                                   %if ?exemode != -2
  1162                                    %error exemode variable must be directly below bp
  1163                                   %endif
  1164                                  	mov bx, -1		; unimplemented, return error
  1165                                  	jmp error
  1166                                  	lleave ctx
  1167                                  @@:
  1168                                  	cli
  1169                                  	pop ss			; = relocated ss value
  1170                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
  1171                                  	sti
  1172                                  %endif
  1173                                  
  1174 00000027 31C9                    	xor cx, cx
  1175 00000029 51                      	push cx			; put zero on top of stack
  1176                                  
  1177                                  %if _IMAGE_EXE_IP < 256
  1178                                  	mov cl, _IMAGE_EXE_IP
  1179                                  %elif (_IMAGE_EXE_IP & 255) == 0
  1180                                  	mov ch, _IMAGE_EXE_IP >> 8
  1181                                  %else
  1182 0000002A B94001                  	mov cx, _IMAGE_EXE_IP
  1183                                  %endif
  1184                                  
  1185                                  %if _IMAGE_EXE_CS == -16
  1186 0000002D 83C6F0                  	add si, -16
  1187 00000030 8EDE                    	mov ds, si
  1188 00000032 8EC6                    	mov es, si
  1189                                  %else
  1190                                  	lea dx, [si - 10h]	; => PSP
  1191                                  	mov ds, dx
  1192                                  	mov es, dx		; ds = es => PSP
  1193                                   %if _IMAGE_EXE_CS
  1194                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
  1195                                   %endif
  1196                                  %endif
  1197 00000034 56                      	push si
  1198 00000035 51                      	push cx
  1199                                  %if _LCFG && _PASSLCFG
  1200 00000036 BF[D004]                	mov di, transfer_lcfg_block
  1201 00000039 8CC9                    	mov cx, cs
  1202                                  %endif
  1203 0000003B CB                      	retf			; jump to EXE mode of image
  1204                                  
  1205                                  %endif
  1206                                  .jmp_kernel_mode:
  1207                                  %if _LCFG && _PASSLCFG
  1208 0000003C BF[D004]                	mov di, transfer_lcfg_block
  1209 0000003F 8CC9                    	mov cx, cs
  1210                                  %endif
  1211 00000041 EA01006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
  1212                                  
  1213                                  
  1214                                  %if _TEST_PROGRAM
  1215                                  disp_al_counter:
  1216 00000046 2EFF06[4C00]            	inc word [cs:init1_c_mode_counter]	; 5 bytes
  1217 0000004B C3                      	retn					; 1 byte
  1218                                  
  1219 0000004C 0000                    init1_c_mode_counter:		dw 0		; 2 bytes, total 8
  1220                                  %else
  1221                                   %if _PROGRESS
  1222                                  disp_al_counter equ step_progress
  1223                                   %else
  1224                                  disp_al_counter equ disp_al
  1225                                   %endif
  1226                                  %endif
  1227                                  
  1228                                  
  1229                                  error:
  1230                                   %ifn _TEST_PROGRAM		; 2 bytes
  1231                                  	push cs
  1232                                  	pop ds
  1233                                   %endif
  1234                                  %if _DEBUG0
  1235                                  	mov si, msg.error_begin
  1236                                  	call disp_error
  1237                                  	xchg ax, bx			; ax = error code
  1238                                  	call disp_ax_hex
  1239                                   %ifn _TEST_PROGRAM		; 3 bytes
  1240                                  	mov si, msg.error_end
  1241                                   %endif
  1242                                  %else
  1243                                   %ifn _TEST_PROGRAM		; 3 bytes
  1244                                  	mov si, msg.error
  1245                                   %endif
  1246                                  %endif
  1247                                   %ifn _TEST_PROGRAM		; 3 bytes, total 2 + 3 + 3 = 8
  1248                                  	call disp_error
  1249                                   %endif
  1250                                  %if _DEVICE
  1251                                  	test byte [bp - 2], 2
  1252                                  	jz .exit_app_or_kernel
  1253                                  
  1254                                  	pop si				; => device segment
  1255                                  	pop bx				; mode word
  1256                                  	pop bp
  1257                                  	pop ax
  1258                                  	mov es, si
  1259                                  	xor di, di			; -> device header
  1260                                  	 push cs
  1261                                  	 pop ds
  1262                                  	mov si, device_header_copy	; -> to reset header
  1263                                  	mov cx, words(device_header_copy.length)
  1264                                  	rep movsw		; overwrite device header with default
  1265                                  				;  (reset to a valid state after unsuccessful
  1266                                  				;  decompression, which may have partially
  1267                                  				;  written the header already)
  1268                                  	 push es
  1269                                  	 pop ds				; -> device segment
  1270                                  	pop es
  1271                                  	pop bx
  1272                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1273                                  	mov byte [es:bx + 13], 0	; set number of units = 0
  1274                                  	mov word [es:bx + 14 + 2], ds
  1275                                  	and word [es:bx + 14], 0	; -> after end of memory to allocate
  1276                                  	pop ax
  1277                                  	pop cx
  1278                                  	pop dx
  1279                                  	pop di
  1280                                  	pop si
  1281                                  	pop ds
  1282                                  	pop bp
  1283                                  	add sp, 4		; discard far return to payload's strategy
  1284                                  	retf			; return to DOS
  1285                                  
  1286                                  
  1287                                  .exit_app_or_kernel:
  1288                                  %endif
  1289                                  
  1290                                  %if _IMAGE_EXE
  1291                                  %if _BOOTLDR
  1292 0000004E F646FE01                	test byte [bp - 2], 1
  1293 00000052 7405                    	jz .exit_kernel_mode
  1294                                  %endif
  1295                                  
  1296 00000054 B87F4C                  	mov ax, 4C7Fh
  1297 00000057 CD21                    	int 21h
  1298                                  
  1299                                  .exit_kernel_mode:
  1300                                  %endif
  1301                                  %if _BOOTLDR
  1302 00000059 31C0                    	xor ax, ax
  1303 0000005B CD16                    	int 16h
  1304 0000005D CD19                    	int 19h
  1305                                  %endif
  1306                                  
  1307                                  
  1308                                  %if _PROGRESS
  1309                                  step_progress:
  1310 0000005F F9                      	stc
  1311                                  .CF:
  1312 00000060 53                      	push bx
  1313 00000061 51                      	push cx
  1314 00000062 52                      	push dx
  1315 00000063 1E                      	push ds
  1316 00000064 56                      	push si
  1317 00000065 57                      	push di
  1318 00000066 50                      	push ax
  1319                                  
  1320 00000067 0E                      	push cs
  1321 00000068 1F                      	pop ds
  1322                                  
  1323 00000069 8316[9A01]00            	adc word [.counter], 0
  1324 0000006E A1[9A01]                	mov ax, word [.counter]
  1325                                  
  1326                                   %if _PROGRESSMULTI
  1327                                    %if _IMAGE_EXE || _DEVICE
  1328                                     %assign defaultprogresshandler _PROGRESSDEFAULT
  1329                                    %else
  1330                                     %assign defaultprogresshandler _PROGRESSDEFAULTBOOT
  1331                                    %endif
  1332 00000071 E91600                  	jmp strict near . %+ defaultprogresshandler %+ _step
  1333                                  .handler: equ $ - 2		; SMC, patched to dispatch to handler
  1334                                  .base:
  1335                                   %endif
  1336                                  
  1337                                  .2_step:
  1338 00000074 BAE803                  	mov dx, 1000
  1339 00000077 F7E2                    	mul dx			; dx:ax = counter times 1000
  1340                                  %if _PROGRESSAMOUNT
  1341 00000079 B90100                  	mov cx, _PROGRESSAMOUNT
  1342 0000007C F7F1                    	div cx			; ax = 0..1000
  1343                                  %else
  1344                                   %warning Progress amount is zero
  1345                                  	mov ax, 1
  1346                                  %endif
  1347                                  
  1348                                  %if 0
  1349                                  	cmp word [.display], ax
  1350                                  	je .ret
  1351                                  	mov word [.display], ax
  1352                                  %endif
  1353 0000007E BE[A301]                	mov si, .message_number_end - 1
  1354 00000081 E80E00                  	call .format_percentage
  1355                                  
  1356 00000084 BE[9C01]                	mov si, .message
  1357 00000087 E82A01                  	call disp_error
  1358                                  
  1359                                  .ret:
  1360 0000008A 58                      	pop ax
  1361                                  .ret_ax:
  1362 0000008B 5F                      	pop di
  1363 0000008C 5E                      	pop si
  1364 0000008D 1F                      	pop ds
  1365 0000008E 5A                      	pop dx
  1366 0000008F 59                      	pop cx
  1367 00000090 5B                      	pop bx
  1368                                  .retn:
  1369 00000091 C3                      	retn
  1370                                  
  1371                                  
  1372                                  .format_percentage:
  1373 00000092 BB0200                  	mov bx, 2		; skip dot
  1374                                  
  1375 00000095 B90A00                  	mov cx, 10		; base
  1376                                  @@:
  1377 00000098 31D2                    	xor dx, dx		; dx:ax = current number
  1378 0000009A F7F1                    	div cx			; dl = remainder, ax = next number
  1379 0000009C 80C230                  	add dl, '0'		; make decit
  1380 0000009F 8814                    	mov byte [si], dl	; store
  1381 000000A1 29DE                    	sub si, bx		; -> next digit slot
  1382 000000A3 80FB02                  	cmp bl, 2		; did we just store fractional ?
  1383 000000A6 B301                    	mov bl, 1		; ! next iteration do not skip dot
  1384 000000A8 74EE                    	je @B			; yes, loop always -->
  1385 000000AA 85C0                    	test ax, ax		; nonzero left ?
  1386 000000AC 75EA                    	jnz @B			; yes, loop if so -->
  1387 000000AE C3                      	retn
  1388                                  
  1389                                  
  1390                                   %if _PROGRESSMULTI
  1391                                  .0_step: equ .ret
  1392                                  
  1393                                  .1_step:
  1394 000000AF 58                      	pop ax
  1395 000000B0 E80F01                  	call disp_al
  1396 000000B3 EBD6                    	jmp .ret_ax
  1397                                  
  1398                                  .3_step:
  1399 000000B5 BB4B00                  	mov bx, 80 - 1 - 4
  1400 000000B8 F7E3                    	mul bx			; dx:ax = counter times 75
  1401                                  %if _PROGRESSAMOUNT
  1402 000000BA B90100                  	mov cx, _PROGRESSAMOUNT
  1403 000000BD F7F1                    	div cx			; ax = 0..75
  1404                                  %else
  1405                                   %warning Progress amount is zero
  1406                                  	mov ax, 1
  1407                                  %endif
  1408                                  
  1409 000000BF 3906[9801]              	cmp word [.display], ax
  1410 000000C3 74C5                    	je .ret
  1411 000000C5 A3[9801]                	mov word [.display], ax
  1412                                  
  1413 000000C8 50                      	push ax
  1414 000000C9 91                      	xchg cx, ax
  1415 000000CA B00D                    	mov al, 13
  1416 000000CC E8F300                  	call disp_al
  1417 000000CF B05B                    	mov al, '['
  1418 000000D1 E8EE00                  	call disp_al
  1419 000000D4 B020                    	mov al, 32
  1420 000000D6 E8E900                  	call disp_al
  1421                                  
  1422 000000D9 B023                    	mov al, '#'
  1423 000000DB E305                    	jcxz @FF
  1424                                  @@:
  1425 000000DD E8E200                  	call disp_al
  1426 000000E0 E2FB                    	loop @B
  1427                                  @@:
  1428                                  
  1429 000000E2 B020                    	mov al, 32
  1430 000000E4 59                      	pop cx
  1431 000000E5 29CB                    	sub bx, cx
  1432 000000E7 7607                    	jbe @FF
  1433 000000E9 89D9                    	mov cx, bx
  1434                                  @@:
  1435 000000EB E8D400                  	call disp_al
  1436 000000EE E2FB                    	loop @B
  1437                                  @@:
  1438                                  
  1439                                  .m4done:
  1440 000000F0 E8CF00                  	call disp_al
  1441 000000F3 B05D                    	mov al, ']'
  1442 000000F5 E8CA00                  	call disp_al
  1443 000000F8 EB90                    	jmp .ret
  1444                                  
  1445                                  
  1446                                  .4_step:
  1447 000000FA 50                      	push ax
  1448                                  
  1449 000000FB BAE803                  	mov dx, 1000
  1450 000000FE F7E2                    	mul dx			; dx:ax = counter times 1000
  1451                                  %if _PROGRESSAMOUNT
  1452 00000100 B90100                  	mov cx, _PROGRESSAMOUNT
  1453 00000103 F7F1                    	div cx			; ax = 0..1000
  1454                                  %else
  1455                                   %warning Progress amount is zero
  1456                                  	mov ax, 1
  1457                                  %endif
  1458                                  
  1459 00000105 BE[AD01]                	mov si, .message_4_number_end - 1
  1460 00000108 E887FF                  	call .format_percentage
  1461                                  
  1462 0000010B 58                      	pop ax
  1463 0000010C BB4B00                  	mov bx, 80 - 1 - 4
  1464 0000010F F7E3                    	mul bx			; dx:ax = counter times 75
  1465                                  %if _PROGRESSAMOUNT
  1466 00000111 B90100                  	mov cx, _PROGRESSAMOUNT
  1467 00000114 F7F1                    	div cx			; ax = 0..75
  1468                                  %else
  1469                                   %warning Progress amount is zero
  1470                                  	mov ax, 1
  1471                                  %endif
  1472                                  
  1473 00000116 50                      	push ax
  1474 00000117 91                      	xchg cx, ax
  1475 00000118 B00D                    	mov al, 13
  1476 0000011A E8A500                  	call disp_al
  1477 0000011D B05B                    	mov al, '['
  1478 0000011F E8A000                  	call disp_al
  1479 00000122 B020                    	mov al, 32
  1480 00000124 E89B00                  	call disp_al
  1481                                  
  1482 00000127 31FF                    	xor di, di
  1483 00000129 BA2200                  	mov dx, (80 - 1 - 4 - .message_4_length) / 2
  1484 0000012C 803E[A901]20            	cmp byte [.message_4_number], 32
  1485 00000131 7401                    	je @F
  1486 00000133 47                      	inc di
  1487                                  @@:
  1488 00000134 29FA                    	sub dx, di
  1489                                  
  1490 00000136 B023                    	mov al, '#'
  1491 00000138 E306                    	jcxz @FF
  1492                                  @@:
  1493 0000013A E88500                  	call disp_al
  1494 0000013D 4A                      	dec dx
  1495 0000013E E0FA                    	loopnz @B
  1496                                  @@:
  1497                                  
  1498 00000140 85D2                    	test dx, dx
  1499 00000142 752E                    	jnz .notyetm4
  1500                                  
  1501 00000144 BE[A901]                	mov si, .message_4
  1502 00000147 29FE                    	sub si, di
  1503 00000149 E86800                  	call disp_error
  1504                                  
  1505 0000014C 29F9                    	sub cx, di
  1506 0000014E 760E                    	jbe @FF
  1507 00000150 83E907                  	sub cx, .message_4_length
  1508 00000153 7609                    	jbe @FF
  1509 00000155 89CA                    	mov dx, cx
  1510 00000157 B023                    	mov al, '#'
  1511                                  @@:
  1512 00000159 E86600                  	call disp_al
  1513 0000015C E2FB                    	loop @B
  1514                                  @@:
  1515 0000015E 59                      	pop cx
  1516 0000015F B020                    	mov al, 32
  1517 00000161 83EB29                  	sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length
  1518 00000164 29D3                    	sub bx, dx
  1519 00000166 7607                    	jbe @FF
  1520 00000168 89D9                    	mov cx, bx
  1521                                  @@:
  1522 0000016A E85500                  	call disp_al
  1523 0000016D E2FB                    	loop @B
  1524                                  @@:
  1525 0000016F E97EFF                  	jmp .m4done
  1526                                  
  1527                                  .notyetm4:
  1528 00000172 B020                    	mov al, 32
  1529 00000174 59                      	pop cx
  1530 00000175 29CB                    	sub bx, cx
  1531 00000177 7608                    	jbe @FF
  1532 00000179 89D9                    	mov cx, bx
  1533                                  @@:
  1534 0000017B E84400                  	call disp_al
  1535 0000017E 4A                      	dec dx
  1536 0000017F E0FA                    	loopnz @B
  1537                                  @@:
  1538                                  
  1539 00000181 BE[A901]                	mov si, .message_4
  1540 00000184 29FE                    	sub si, di
  1541 00000186 E82B00                  	call disp_error
  1542                                  
  1543 00000189 B020                    	mov al, 32
  1544 0000018B 29F9                    	sub cx, di
  1545 0000018D 83E907                  	sub cx, .message_4_length
  1546                                  	; jbe @FF
  1547                                  @@:
  1548 00000190 E82F00                  	call disp_al
  1549 00000193 E2FB                    	loop @B
  1550                                  @@:
  1551 00000195 E958FF                  	jmp .m4done
  1552                                  %endif
  1553                                  
  1554                                  	align 2, db 0
  1555                                   %if _PROGRESSMULTI
  1556 00000198 FFFF                    .display:	dw -1
  1557                                   %endif
  1558 0000019A 0000                    .counter:	dw 0
  1559 0000019C 0D5B20                  .message:	db 13,"[ "
  1560 0000019F 2020312E30              .message_number:db "  1.0"	; enough digit slots for 100.0%,
  1561                                  				;  blanks are pre-init until written
  1562                                  .message_number_end:
  1563 000001A4 25205D00                		db "% ]",0
  1564                                   %if _PROGRESSMULTI
  1565 000001A8 20                      		db " "
  1566                                  .message_4:
  1567 000001A9 2020312E30              .message_4_number:db "  1.0"	; enough digit slots for 100.0%,
  1568                                  				;  blanks are pre-init until written
  1569                                  .message_4_number_end:
  1570 000001AE 252000                  		db "% ",0
  1571                                  .message_4_length: equ $ - 1 - .message_4
  1572                                   %endif
  1573                                  %endif
  1574                                  
  1575                                  
  1576                                  %if _DEVICE
  1577                                  	align 16
  1578                                  device_header_copy:
  1579                                  .:
  1580                                  .next:
  1581                                  	dd -1				; already initialised
  1582                                  .attributes:
  1583                                  	dw _DEVICE_ATTRIBUTE
  1584                                  .strategy:
  1585                                  	dw .strategy_entry - .		; -> strategy entry
  1586                                  .interrupt:
  1587                                  	dw .interrupt_entry - .		; -> interrupt entry
  1588                                  .name:
  1589                                  	fill 8, 32, db _DEVICE_NAME
  1590                                  
  1591                                  .strategy_entry:
  1592                                  	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
  1593                                  .interrupt_entry:
  1594                                  	fill 4, 90h, retf
  1595                                  
  1596                                  .set_error:
  1597                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1598                                  	retf
  1599                                  .length: equ $ - .
  1600                                  %endif
  1601                                  
  1602                                  
  1603                                  disp_error.loop:
  1604 000001B1 E80E00                  	call disp_al
  1605                                  disp_error:
  1606 000001B4 AC                      	lodsb
  1607 000001B5 84C0                    	test al, al
  1608 000001B7 75F8                    	jnz .loop
  1609 000001B9 C3                      	retn
  1610                                  
  1611                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
  1612                                  disp_ax_hex:			; ax
  1613                                  		xchg al,ah
  1614                                  		call disp_al_hex		; display former ah
  1615                                  		xchg al,ah			;  and fall trough for al
  1616                                  disp_al_hex:			; al
  1617                                  		push cx
  1618                                  		mov cl,4
  1619                                  		ror al,cl
  1620                                  		call disp_al_lownibble_hex	; display former high-nibble
  1621                                  		rol al,cl
  1622                                  		pop cx
  1623                                  						;  and fall trough for low-nibble
  1624                                  disp_al_lownibble_hex:
  1625                                  		push ax			 ; save ax for call return
  1626                                  		and al,00001111b		; high nibble must be zero
  1627                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1628                                  		cmp al,'9'
  1629                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1630                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1631                                   .decimalnum:
  1632                                  		call disp_al
  1633                                  		pop ax
  1634                                  		retn
  1635                                  %endif
  1636                                  
  1637                                  
  1638                                  disp_al_for_progress:
  1639                                  %if _PROGRESS && _PROGRESSMULTI
  1640 000001BA 2E833E[7200]16          	cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base
  1641 000001C0 741B                    	je disp_al.retn
  1642                                  %endif
  1643                                  disp_al:
  1644                                  %if _TEST_PROGRAM
  1645 000001C2 C3                      	retn
  1646                                  %else
  1647                                  	push ax
  1648                                  %endif
  1649                                  %if _BOOTLDR
  1650 000001C3 53                      	push bx
  1651 000001C4 55                      	push bp
  1652 000001C5 B40E                    	mov ah, 0Eh
  1653 000001C7 BB0700                  	mov bx, 7
  1654                                  %endif
  1655                                  %if _IMAGE_EXE || _DEVICE
  1656 000001CA 52                      	push dx
  1657                                  
  1658                                  %if _BOOTLDR
  1659 000001CB F646FE03                	test byte [bp - 2], 1 | 2
  1660 000001CF 7406                    	jz .display_kernel_mode
  1661                                  %endif
  1662                                  
  1663 000001D1 92                      	xchg dx, ax				; dl = input al
  1664 000001D2 B402                    	mov ah, 02h
  1665 000001D4 CD21                    	int 21h
  1666                                  %if _BOOTLDR
  1667 000001D6 A9                      	db __TEST_IMM16				; (skip int)
  1668                                  %endif
  1669                                  
  1670                                  .display_kernel_mode:
  1671                                  %endif
  1672                                  %if _BOOTLDR
  1673 000001D7 CD10                    	int 10h
  1674                                  %endif
  1675                                  %if _IMAGE_EXE
  1676 000001D9 5A                      	pop dx
  1677                                  %endif
  1678                                  %if _BOOTLDR
  1679 000001DA 5D                      	pop bp
  1680 000001DB 5B                      	pop bx
  1681                                  %endif
  1682 000001DC 58                      	pop ax
  1683                                  .retn:
  1684                                  disp_error.ret:
  1685 000001DD C3                      	retn
  1686                                  
  1687                                  
  1688                                  msg:
  1689                                  %if _DEBUG0
  1690                                  .error_begin:	db "Load error: Decompression failure, code ",0
  1691                                  .error_end:	db "h.",13,10,0
  1692                                  %else
  1693 000001DE 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
  1693 000001E7 723A204465636F6D70-
  1693 000001F0 72657373696F6E2066-
  1693 000001F9 61696C7572652E0D0A-
  1693 00000202 00                 
  1694                                  %endif
  1695                                  
  1696                                  
  1697                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
  1698                                  %assign NEED_NORMALISE_BOTH_POINTERS 1
  1699                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
  1700                                  %assign CHECK_POINTERS_VARIABLE_DST 1
  1701                                  
  1702                                  		; Specific depacker's file is included within label msg.
  1703                                  		; In the file, lframe is used and lleave ctx is not used.
  1704                                  
  1705                                  %if _BRIEFLZ
  1706                                  	%include "brieflz.asm"
  1707                                  %endif
  1708                                  
  1709                                  
  1710                                  %if _LZ4
  1711                                  	%include "lz4.asm"
  1712                                  %endif
  1713                                  
  1714                                  
  1715                                  %if _SNAPPY
  1716                                  	%include "snappy.asm"
  1717                                  %endif
  1718                                  
  1719                                  
  1720                                  %if _EXODECR
  1721                                  	%include "exodecr.asm"
  1722                                  %endif
  1723                                  
  1724                                  
  1725                                  %if _X
  1726                                  	%include "x.asm"
  1727                                  %endif
  1728                                  
  1729                                  
  1730                                  %if _HEATSHRINK
  1731                                  	%include "heatshr.asm"
  1732                                  %endif
  1733                                  
  1734                                  
  1735                                  %if _LZD
  1736                                  	%include "lzd.asm"
  1737                                  %endif
  1738                                  
  1739                                  
  1740                                  %if _LZO
  1741                                  	%include "lzo.asm"
  1742                                  %endif
  1743                                  
  1744                                  
  1745                                  %if _LZSA2
  1746                                  	%include "lzsa2.asm"
     1                              <1> 
     2                              <1> ; 8086 Assembly lDOS iniload payload LZSA2 depacker
     3                              <1> ;  by E. C. Masloch, 2021
     4                              <1> ;
     5                              <1> ;  based on:
     6                              <1> ;  decompress_small.S - space-efficient decompressor implementation for 8088
     7                              <1> ;
     8                              <1> ;  Copyright (C) 2019 Emmanuel Marty
     9                              <1> ;
    10                              <1> ;  This software is provided 'as-is', without any express or implied
    11                              <1> ;  warranty.  In no event will the authors be held liable for any damages
    12                              <1> ;  arising from the use of this software.
    13                              <1> ;
    14                              <1> ;  Permission is granted to anyone to use this software for any purpose,
    15                              <1> ;  including commercial applications, and to alter it and redistribute it
    16                              <1> ;  freely, subject to the following restrictions:
    17                              <1> ;
    18                              <1> ;  1. The origin of this software must not be misrepresented; you must not
    19                              <1> ;     claim that you wrote the original software. If you use this software
    20                              <1> ;     in a product, an acknowledgment in the product documentation would be
    21                              <1> ;     appreciated but is not required.
    22                              <1> ;  2. Altered source versions must be plainly marked as such, and must not be
    23                              <1> ;     misrepresented as being the original software.
    24                              <1> ;  3. This notice may not be removed or altered from any source distribution.
    25                              <1> 
    26                              <1> 
    27                              <1> 	numdef COUNTER,		0, 128
    28                              <1> %if (_COUNTER - 1) & _COUNTER
    29                              <1>  %error COUNTER must be a power of two
    30                              <1> %endif
    31                              <1> 
    32                              <1> %assign CHECK_POINTERS_VARIABLE_SRC 0
    33                              <1> %assign CHECK_POINTERS_VARIABLE_DST 0
    34                              <1> 
    35                              <1> 
    36                              <1> 		; INP:	ds:si -> source
    37                              <1> 		;	dx:cx = length of source
    38                              <1> 		;	es:di -> destination (below source)
    39                              <1> 		;	if _IMAGE_EXE:
    40                              <1> 		;	 bx = EXE mode flag (bit 0)
    41                              <1> 		;	else:
    42                              <1> 		;	 bx = 0
    43                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
    44                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
    45                              <1> 		;	 (-1 if full source should be decompressed)
    46                              <1> 		;	else:
    47                              <1> 		;	 ax = -1
    48                              <1> 		; OUT:	NC if success
    49                              <1> 		;	CY if error,
    50                              <1> 		;	 bx = ?errordata (if _DEBUG0)
    51                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
    52                              <1> 		; STT:	UP
    53                              <1> 		;
    54                              <1> 		; Note:	The destination reaches up to below the source.
    55                              <1> 		; Note:	The input pointers need not be normalised yet.
    56                              <1> 		;	 Normalised means that the offset part is below 16.
    57                              <1> depack:
    58                              <1> 	lframe near
    59                              <1> %if _IMAGE_EXE || _DEBUG0 || _COUNTER
    60 00000203 5589E5              <1> 	lenter early
    61                              <1>  %if _IMAGE_EXE
    62                              <1> 	lvar word,	exemode	; must be bp - 2!
    63 00000206 53                  <1> 	 push bx
    64                              <1>   %if ?exemode != -2
    65                              <1>    %error exemode variable must be directly below bp
    66                              <1>   %endif
    67                              <1>  %endif
    68                              <1>  %if _DEBUG0 || _COUNTER
    69 00000207 31DB                <1> 	xor bx, bx
    70                              <1>  %endif
    71                              <1>  %if _DEBUG0
    72                              <1> 	lvar word,	errordata
    73                              <1> 	 push bx
    74                              <1>  %endif
    75                              <1> %endif
    76                              <1> 	lvar word,	counter
    77                              <1> %if _COUNTER
    78 00000209 53                  <1> 	 push bx		; initialise counter (high byte) to zero
    79                              <1> %endif
    80                              <1> 	lvar dword,	length_of_source_after_block
    81                              <1> 	lvar word,	matchlength
    82 0000020A 8D66F6              <1> 	lenter
    83                              <1> 
    84 0000020D E83502              <1> 	call normalise_both_pointers
    85                              <1> 
    86                              <1> 	lvar dword,	src
    87 00000210 1E                  <1> 	 push ds
    88 00000211 56                  <1> 	 push si
    89                              <1> 	lvar dword,	original_dst
    90 00000212 06                  <1> 	 push es
    91 00000213 57                  <1> 	 push di
    92                              <1> 	lvar dword,	dst
    93 00000214 06                  <1> 	 push es
    94 00000215 57                  <1> 	 push di
    95                              <1> 	lvar dword,	length_of_source
    96 00000216 52                  <1> 	 push dx
    97 00000217 51                  <1> 	 push cx
    98                              <1> 
    99                              <1> %if 0 ; && _PAYLOAD_KERNEL_MAX_PARAS
   100                              <1> 	cmp ax, -1		; no maximum specified ?
   101                              <1> 	je @FF			; retain -1 in ax -->
   102                              <1> 	test di, di		; do we need an additional paragraph ?
   103                              <1> 	jz @F			; no -->
   104                              <1> 	inc ax			; es + ax => paragraph after necessary part
   105                              <1> @@:
   106                              <1> 	mov dx, es
   107                              <1> 	add ax, dx		; => paragraph after necessary part
   108                              <1> 		; If the normalised destination pointer's segment grows
   109                              <1> 		;  to this segment then enough has been decompressed.
   110                              <1> d0	mov byte [bp + ?errordata], 40h
   111                              <1> 	jc .error		; should not carry
   112                              <1> @@:
   113                              <1> 	lvar word,	dst_max_segment
   114                              <1> 	 push ax
   115                              <1> %endif
   116                              <1> 
   117 00000218 1E                  <1> 	 push ds
   118 00000219 56                  <1> 	 push si
   119 0000021A E88802              <1> 	call pointer_to_linear
   120                              <1> 
   121 0000021D 89D3                <1> 	mov bx, dx
   122 0000021F 91                  <1> 	xchg cx, ax		; bx:cx = source linear
   123                              <1> 
   124 00000220 06                  <1> 	 push es
   125 00000221 57                  <1> 	 push di
   126 00000222 E88002              <1> 	call pointer_to_linear
   127                              <1> 
   128                              <1> %if _ALLOW_OVERLAPPING
   129 00000225 034EE6              <1> 	add cx, word [bp + ?length_of_source]
   130 00000228 135EE8              <1> 	adc bx, word [bp + ?length_of_source + 2]
   131                              <1> 		; In case of allowing overlapping source and destination,
   132                              <1> 		;  the ?length_of_destination variable is set to
   133                              <1> 		;  ?src + ?length_of_source - ?dst, allowing to write to
   134                              <1> 		;  all of the source buffer (with the checks already in place
   135                              <1> 		;  from the default handling). Additional checks are done by
   136                              <1> 		;  calling check_pointers_not_overlapping. This is done after
   137                              <1> 		;  every change of ?dst to verify that the write pointer stays
   138                              <1> 		;  below-or-equal the read pointer.
   139                              <1> 		; This means the remaining source data may be corrupted by a
   140                              <1> 		;  write, but nothing after the source data is written to,
   141                              <1> 		;  so the error handling (in INIT1 after the data) still works.
   142                              <1> %endif
   143                              <1> 
   144 0000022B 29C1                <1> 	sub cx, ax
   145 0000022D 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   146                              <1> 
   147                              <1> 	lvar dword,	length_of_destination
   148 0000022F 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   149 00000230 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   150                              <1> 
   151                              <1> %if _ALLOW_OVERLAPPING
   152 00000231 E8FD01              <1> 	call check_pointers_not_overlapping
   153                              <1> 		; Note:	We initially check here that the write pointer is
   154                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   155                              <1> 		;	 Doing this check here (as well as after any
   156                              <1> 		;	 copied match) allows us to drop the check done
   157                              <1> 		;	 after moving literal bytes.
   158                              <1> d0	mov byte [bp + ?errordata], 1Bh
   159 00000234 7268                <1> 	jc .error
   160                              <1> %endif
   161                              <1> 
   162 00000236 E88200              <1> 	call .lodsw
   163 00000239 3D7B9E              <1> 	cmp ax, 7Bh | (9Eh << 8)	; signature
   164 0000023C 7560                <1> 	jne .error
   165 0000023E E86E00              <1> 	call .lodsb
   166 00000241 3C20                <1> 	cmp al, 1 << 5			; traits byte, check for lzsa2
   167 00000243 7559                <1> 	jne .error
   168                              <1> 
   169                              <1> .loop:
   170 00000245 E8FD01              <1> 	call normalise_both_pointers
   171                              <1> 
   172 00000248 31D2                <1> 	xor dx, dx
   173 0000024A E86E00              <1> 	call .lodsw			; bits 0 to 15 of length
   174 0000024D 92                  <1> 	xchg ax, dx
   175 0000024E E85E00              <1> 	call .lodsb
   176 00000251 A87F                <1> 	test al, 0111_1111b		; reserved bits + bit 16 of length
   177 00000253 7549                <1> 	jnz .error			; error if nonzero -->
   178                              <1> 
   179 00000255 E8F401              <1> 	call normalise_dssi_pointer
   180                              <1> 
   181                              <1> 		; This first check is only really relevant
   182                              <1> 		;  for uncompressed blocks.
   183 00000258 89FB                <1> 	mov bx, di
   184 0000025A 01D3                <1> 	add bx, dx			; fits in destination segment ?
   185 0000025C 7240                <1> 	jc .error			;  (assuming bit 16 = 0)
   186                              <1> 		; This second check is to insure we don't
   187                              <1> 		;  have to normalise the source pointer
   188                              <1> 		;  until after the end of the block.
   189 0000025E 89F3                <1> 	mov bx, si
   190 00000260 01D3                <1> 	add bx, dx			; fits in source segment ?
   191 00000262 723A                <1> 	jc .error
   192                              <1> 
   193 00000264 84C0                <1> 	test al, al			; uncompressed ?
   194 00000266 92                  <1> 	xchg ax, dx
   195 00000267 7905                <1> 	jns .compressed			; no -->
   196                              <1> .uncompressed:
   197 00000269 91                  <1> 	xchg ax, cx
   198 0000026A F3A4                <1> 	rep movsb			; copy this
   199 0000026C EBD7                <1> 	jmp .loop
   200                              <1> 
   201                              <1> .compressed:
   202 0000026E 8B4EE6              <1> 	mov cx, word [bp + ?length_of_source]
   203 00000271 8B5EE8              <1> 	mov bx, word [bp + ?length_of_source + 2]
   204                              <1> 
   205 00000274 85C0                <1> 	test ax, ax
   206 00000276 7421                <1> 	jz .end
   207                              <1> 
   208 00000278 29C1                <1> 	sub cx, ax
   209 0000027A 83DB00              <1> 	sbb bx, 0
   210 0000027D 721F                <1> 	jc .error
   211 0000027F 894EF8              <1> 	mov word [bp + ?length_of_source_after_block], cx
   212 00000282 895EFA              <1> 	mov word [bp + ?length_of_source_after_block + 2], bx
   213                              <1> 
   214 00000285 06                  <1> 	push es
   215 00000286 57                  <1> 	push di
   216 00000287 E83D00              <1> 	call lzsa2_decompress
   217 0000028A 83F801              <1> 	cmp ax, 1			; CY if ax == 0
   218 0000028D 91                  <1> 	xchg cx, ax
   219 0000028E 19DB                <1> 	sbb bx, bx			; -1 if cx == 0, else 0
   220 00000290 F7DB                <1> 	neg bx				; 1 if cx == 0, else 0
   221 00000292 E8E101              <1> 	call normalise_pointer_with_displacement_bxcx
   222 00000295 5F                  <1> 	pop di
   223 00000296 07                  <1> 	pop es
   224 00000297 EBAC                <1> 	jmp .loop
   225                              <1> 
   226                              <1> .end:
   227 00000299 09CB                <1> 	or bx, cx
   228 0000029B 7501                <1> 	jnz .error
   229                              <1> 
   230                              <1> .ret:
   231 0000029D A8                  <1> 	db __TEST_IMM8		; (skip stc, NC)
   232                              <1> .error:
   233 0000029E F9                  <1> 	stc
   234                              <1> 
   235                              <1> %if _COUNTER
   236 0000029F 9F                  <1> 	lahf
   237 000002A0 B00D                <1> 	mov al, 13
   238 000002A2 E815FF              <1> 	call disp_al_for_progress
   239 000002A5 B00A                <1> 	mov al, 10
   240 000002A7 E810FF              <1> 	call disp_al_for_progress
   241 000002AA 9E                  <1> 	sahf
   242                              <1> %endif
   243                              <1> d0	mov bx, word [bp + ?errordata]
   244 000002AB 89EC5D              <1> 	lleave code
   245 000002AE C3                  <1> 	lret
   246                              <1> 
   247                              <1> 
   248                              <1> 		; INP:	ds:si -> source data
   249                              <1> 		;	?length_of_source
   250                              <1> 		; OUT:	CY if error (source buffer too small)
   251                              <1> 		;	NC if success,
   252                              <1> 		;	 al = value read
   253                              <1> 		;	 ds:si incremented (NOT normalised)
   254                              <1> 		;	 ?length_of_source decremented
   255                              <1> .lodsb:
   256 000002AF 836EE601            <1> 	sub word [bp + ?length_of_source], 1
   257 000002B3 835EE800            <1> 	sbb word [bp + ?length_of_source + 2], 0
   258 000002B7 72E5                <1> 	jb .error
   259 000002B9 AC                  <1> 	lodsb
   260                              <1> .retn:
   261 000002BA C3                  <1> 	retn
   262                              <1> 
   263                              <1> 
   264                              <1> 		; INP:	ds:si -> source data
   265                              <1> 		;	?length_of_source
   266                              <1> 		; OUT:	CY if error (source buffer too small)
   267                              <1> 		;	NC if success,
   268                              <1> 		;	 ax = value read
   269                              <1> 		;	 ds:si incremented (NOT normalised)
   270                              <1> 		;	 ?length_of_source decremented
   271                              <1> .lodsw:
   272 000002BB 836EE602            <1> 	sub word [bp + ?length_of_source], 2
   273 000002BF 835EE800            <1> 	sbb word [bp + ?length_of_source + 2], 0
   274 000002C3 72D9                <1> 	jb .error
   275 000002C5 AD                  <1> 	lodsw
   276 000002C6 C3                  <1> 	retn
   277                              <1> 
   278                              <1> 
   279                              <1> 		; Decompress LZSA2 block
   280                              <1> 		;
   281                              <1> 		; INP:	ds:si -> LZSA2 block
   282                              <1> 		;	es:di -> output buffer
   283                              <1> 		;	?length_of_source
   284                              <1> 		;	?length_of_source_after_block = block end target
   285                              <1> 		;	?original_dst -> lowest valid back reference
   286                              <1> 		; OUT:	ax = decompressed size (0 means 64 KiB)
   287                              <1> 		;	ds:si -> behind source data
   288                              <1> 		;	jumps to depack.error if error condition detected
   289                              <1> 		; CHG:	all except bp
   290                              <1> lzsa2_decompress:
   291                              <1> .lodsb equ depack.lodsb
   292                              <1> .lodsw equ depack.lodsw
   293                              <1> 
   294 000002C7 57                  <1>    push di                 ; remember decompression offset
   295                              <1> 
   296 000002C8 BB0001              <1>    mov bx,0100H
   297 000002CB 8366F600            <1>    and word [bp + ?matchlength], 0
   298                              <1> 
   299                              <1> .decode_token_clear_cx:
   300 000002CF 31C9                <1>    xor cx,cx
   301                              <1> .decode_token:
   302                              <1> %if _COUNTER
   303 000002D1 FE46FC              <1> 	inc byte [bp + ?counter]
   304 000002D4 F646FC7F            <1> 	test byte [bp + ?counter], _COUNTER - 1
   305 000002D8 7505                <1> 	jnz @F
   306 000002DA B02E                <1> 	mov al, '.'
   307 000002DC E867FD              <1> 	call disp_al_counter
   308                              <1> @@:
   309                              <1> %endif
   310 000002DF 8B46E6              <1> 	mov ax, word [bp + ?length_of_source]
   311 000002E2 8B56E8              <1> 	mov dx, word [bp + ?length_of_source + 2]
   312                              <1> 
   313 000002E5 3956FA              <1> 	cmp word [bp + ?length_of_source_after_block + 2], dx
   314 000002E8 7503                <1> 	jne @F
   315 000002EA 3946F8              <1> 	cmp word [bp + ?length_of_source_after_block], ax
   316                              <1> @@:
   317 000002ED 7503E91B01          <1> 	je .end
   318 000002F2 77AA                <1> 	ja depack.error
   319                              <1> 
   320 000002F4 89C8                <1>    mov ax,cx               ; clear ah - cx is zero from above or from after rep movsb in .copy_match
   321 000002F6 E8B6FF              <1> 	call .lodsb		; read token byte: XYZ|LL|MMMM
   322 000002F9 89C2                <1>    mov dx,ax               ; keep token in dl
   323                              <1>    
   324 000002FB 2418                <1>    and al,018H             ; isolate literals length in token (LL)
   325 000002FD B103                <1>    mov cl,3
   326 000002FF D2E8                <1>    shr al,cl               ; shift literals length into place
   327                              <1> 
   328 00000301 3C03                <1>    cmp al,03H              ; LITERALS_RUN_LEN_V2?
   329 00000303 7513                <1>    jne .got_literals       ; no, we have the full literals count from the token, go copy
   330                              <1> 
   331 00000305 E81701              <1>    call .get_nibble        ; get extra literals length nibble
   332 00000308 00C8                <1>    add al,cl               ; add len from token to nibble 
   333 0000030A 3C12                <1>    cmp al,012H             ; LITERALS_RUN_LEN_V2 + 15 ?
   334 0000030C 750A                <1>    jne .got_literals       ; if not, we have the full literals count, go copy
   335                              <1> 
   336 0000030E E89EFF              <1> 	call .lodsb		; grab extra length byte
   337 00000311 0412                <1>    add al,012H             ; overflow?
   338 00000313 7303                <1>    jnc .got_literals       ; if not, we have the full literals count, go copy
   339                              <1> 
   340 00000315 E8A3FF              <1> 	call .lodsw		; grab 16-bit extra length
   341                              <1> 
   342                              <1> .got_literals:
   343 00000318 91                  <1>    xchg cx,ax
   344 00000319 294EE6              <1> 	sub word [bp + ?length_of_source], cx
   345 0000031C 835EE800            <1> 	sbb word [bp + ?length_of_source + 2], 0
   346 00000320 7303E979FF          <1> 	jb depack.error
   347 00000325 294EE2              <1> 	sub word [bp + ?length_of_destination], cx
   348 00000328 835EE400            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   349 0000032C 7303E96DFF          <1> 	jb depack.error
   350 00000331 F3A4                <1>    rep movsb               ; copy cx literals from ds:si to es:di
   351                              <1> 
   352 00000333 52                  <1> 	push dx
   353 00000334 50                  <1> 	push ax
   354 00000335 8B46E6              <1> 	mov ax, word [bp + ?length_of_source]
   355 00000338 8B56E8              <1> 	mov dx, word [bp + ?length_of_source + 2]
   356                              <1> 
   357 0000033B 3956FA              <1> 	cmp word [bp + ?length_of_source_after_block + 2], dx
   358 0000033E 7503                <1> 	jne @F
   359 00000340 3946F8              <1> 	cmp word [bp + ?length_of_source_after_block], ax
   360                              <1> @@:
   361 00000343 58                  <1> 	pop ax
   362 00000344 5A                  <1> 	pop dx
   363 00000345 7503E9C300          <1> 	je .end
   364 0000034A 7603E94FFF          <1> 	ja depack.error
   365                              <1> 
   366 0000034F F6C2C0              <1>    test dl,0C0h            ; check match offset mode in token (X bit)
   367 00000352 7819                <1>    js .rep_match_or_large_offset
   368                              <1> 
   369                              <1>    ;;cmp dl,040H             ; check if this is a 5 or 9-bit offset (Y bit)
   370                              <1>                            ; discovered via the test with bit 6 set
   371 00000354 91                  <1>    xchg cx,ax              ; clear ah - cx is zero from the rep movsb above
   372 00000355 7508                <1>    jne .offset_9_bit
   373                              <1> 
   374                              <1>                            ; 5 bit offset
   375 00000357 80FA20              <1>    cmp dl,020H             ; test bit 5
   376 0000035A E8B500              <1>    call .get_nibble_x
   377 0000035D EB0A                <1>    jmp short .dec_offset_top
   378                              <1> 
   379                              <1> .offset_9_bit:             ; 9 bit offset
   380 0000035F E84DFF              <1> 	call .lodsb		; get 8 bit offset from stream in A
   381 00000362 FECC                <1>    dec ah                  ; set offset bits 15-8 to 1
   382 00000364 F6C220              <1>    test dl,020H            ; test bit Z (offset bit 8)
   383 00000367 741F                <1>    je .get_match_length
   384                              <1> .dec_offset_top:
   385 00000369 FECC                <1>    dec ah                  ; clear bit 8 if Z bit is clear
   386                              <1>                            ; or set offset bits 15-8 to 1
   387 0000036B EB1B                <1>    jmp short .get_match_length
   388                              <1> 
   389                              <1> .rep_match_or_large_offset:
   390                              <1>    ;;cmp dl,0c0H             ; check if this is a 13-bit offset or a 16-bit offset/rep match (Y bit)
   391 0000036D 7A0C                <1>    jpe .rep_match_or_16_bit
   392                              <1> 
   393                              <1>                            ; 13 bit offset
   394                              <1> 
   395 0000036F 80FAA0              <1>    cmp dl,0A0H             ; test bit 5 (knowing that bit 7 is also set)
   396 00000372 86E0                <1>    xchg ah,al
   397 00000374 E89B00              <1>    call .get_nibble_x
   398 00000377 2C02                <1>    sub al,2                ; substract 512
   399 00000379 EB08                <1>    jmp short .get_match_length_1
   400                              <1> 
   401                              <1> .rep_match_or_16_bit:
   402 0000037B F6C220              <1>    test dl,020H            ; test bit Z (offset bit 8)
   403 0000037E 750B                <1>    jne .repeat_match       ; rep-match
   404                              <1> 
   405                              <1>                            ; 16 bit offset
   406 00000380 E82CFF              <1> 	call .lodsb		; Get 2-byte match offset
   407                              <1> 
   408                              <1> .get_match_length_1:
   409 00000383 86E0                <1>    xchg ah,al
   410 00000385 E827FF              <1> 	call .lodsb		; load match offset bits 0-7
   411                              <1> 
   412                              <1> .get_match_length:
   413 00000388 8746F6              <1> 	xchg word [bp + ?matchlength], ax
   414                              <1> 			; bp: offset
   415                              <1> .repeat_match:
   416 0000038B 92                  <1>    xchg ax,dx              ; ax: original token
   417 0000038C 2407                <1>    and al,07H              ; isolate match length in token (MMM)
   418 0000038E 0402                <1>    add al,2                ; add MIN_MATCH_SIZE_V2
   419                              <1> 
   420 00000390 3C09                <1>    cmp al,09H              ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2?
   421 00000392 7518                <1>    jne .got_matchlen       ; no, we have the full match length from the token, go copy
   422                              <1> 
   423 00000394 E88800              <1>    call .get_nibble        ; get extra literals length nibble
   424 00000397 00C8                <1>    add al,cl               ; add len from token to nibble 
   425 00000399 3C18                <1>    cmp al,018H             ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15?
   426 0000039B 750F                <1>    jne .got_matchlen       ; no, we have the full match length from the token, go copy
   427                              <1> 
   428 0000039D E80FFF              <1> 	call .lodsb		; grab extra length byte
   429 000003A0 0418                <1>    add al,018H             ; overflow?
   430 000003A2 7308                <1>    jnc .got_matchlen       ; if not, we have the entire length
   431 000003A4 7503E9F5FE          <1> 	je depack.error		; detect EOD code
   432                              <1> 
   433 000003A9 E80FFF              <1> 	call .lodsw		; grab 16-bit length
   434                              <1> 
   435                              <1> .got_matchlen:
   436 000003AC 91                  <1>    xchg cx,ax              ; copy match length into cx
   437 000003AD 1E                  <1>    push ds                 ; save ds:si (current pointer to compressed data)
   438 000003AE 96                  <1>    xchg si,ax          
   439 000003AF 06                  <1>    push es
   440 000003B0 1F                  <1>    pop ds
   441 000003B1 89FE                <1> 	mov si, di
   442 000003B3 0376F6              <1> 	add si, word [bp + ?matchlength]
   443                              <1> 			; ds:si now points at back reference in output data
   444 000003B6 7225                <1> 	jc @FF		; simple case branches here -->
   445 000003B8 53                  <1> 	push bx
   446 000003B9 51                  <1> 	push cx
   447 000003BA 8B4EF6              <1> 	mov cx, word [bp + ?matchlength]
   448 000003BD BBFFFF              <1> 	mov bx, -1
   449 000003C0 06                  <1> 	 push es
   450 000003C1 57                  <1> 	 push di
   451 000003C2 E8B100              <1> 	call normalise_pointer_with_displacement_bxcx
   452 000003C5 5E                  <1> 	 pop si
   453 000003C6 5B                  <1> 	 pop bx
   454 000003C7 7203E9D2FE          <1> 	jnc depack.error
   455 000003CC 3B5EF0              <1> 	cmp bx, word [bp + ?original_dst + 2]
   456 000003CF 7503                <1> 	jne @F
   457 000003D1 3B76EE              <1> 	cmp si, word [bp + ?original_dst]
   458                              <1> @@:
   459 000003D4 7303E9C5FE          <1> 	jb depack.error
   460 000003D9 8EDB                <1> 	mov ds, bx
   461 000003DB 59                  <1> 	pop cx
   462 000003DC 5B                  <1> 	pop bx
   463                              <1> @@:
   464 000003DD 294EE2              <1> 	sub word [bp + ?length_of_destination], cx
   465 000003E0 835EE400            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   466 000003E4 7303E9B5FE          <1> 	jb depack.error
   467 000003E9 F3A4                <1>    rep movsb               ; copy match
   468 000003EB 96                  <1>    xchg si,ax              ; restore ds:si
   469 000003EC 1F                  <1>    pop ds
   470                              <1> %if _ALLOW_OVERLAPPING
   471 000003ED 53                  <1> 	push bx
   472 000003EE 85FF                <1> 	test di, di
   473 000003F0 740C                <1> 	jz .zero
   474 000003F2 E83C00              <1> 	call check_pointers_not_overlapping
   475                              <1> .waszero:
   476 000003F5 5B                  <1> 	pop bx
   477 000003F6 7303E9A3FE          <1> 	jc depack.error
   478 000003FB E9D1FE              <1> 	jmp .decode_token_clear_cx
   479                              <1> 				; go decode another token
   480                              <1> 
   481                              <1> .zero:
   482 000003FE 06                  <1> 	push es
   483 000003FF 8CC3                <1> 	mov bx, es		; => our block
   484 00000401 81C30010            <1> 	add bx, 1000h		; => next 64 KiB block
   485 00000405 8EC3                <1> 	mov es, bx		; es:di -> after our block
   486 00000407 E82700              <1> 	call check_pointers_not_overlapping
   487 0000040A 07                  <1> 	pop es
   488 0000040B EBE8                <1> 	jmp .waszero
   489                              <1> %else
   490                              <1> 	jmp .decode_token
   491                              <1> 				; go decode another token
   492                              <1> %endif
   493                              <1> 
   494                              <1> .end:
   495 0000040D 58                  <1>    pop ax                  ; retrieve the original decompression offset
   496 0000040E 97                  <1>    xchg di,ax              ; compute decompressed size
   497 0000040F 29F8                <1>    sub ax,di
   498 00000411 C3                  <1>    ret                     ; done
   499                              <1> 
   500                              <1> .get_nibble_x:
   501 00000412 F5                  <1>    cmc                     ; carry set if bit 4 was set
   502 00000413 D0D8                <1>    rcr al,1
   503 00000415 E80700              <1>    call .get_nibble        ; get nibble for offset bits 0-3
   504 00000418 08C8                <1>    or al,cl                ; merge nibble
   505 0000041A D0C0                <1>    rol al,1
   506 0000041C 34E1                <1>    xor al,0E1H             ; set offset bits 7-5 to 1
   507 0000041E C3                  <1>    ret
   508                              <1> 
   509                              <1> .get_nibble:
   510 0000041F F6DF                <1>    neg bh                  ; nibble ready?
   511 00000421 7905                <1>    jns .has_nibble
   512                              <1>    
   513 00000423 93                  <1>    xchg bx,ax
   514 00000424 E888FE              <1> 	call .lodsb		; load two nibbles
   515 00000427 93                  <1>    xchg bx,ax
   516                              <1> 
   517                              <1> .has_nibble:
   518 00000428 B104                <1>    mov cl,4                ; swap 4 high and low bits of nibble
   519 0000042A D2CB                <1>    ror bl,cl
   520 0000042C B10F                <1>    mov cl,0FH
   521 0000042E 20D9                <1>    and cl,bl
   522 00000430 C3                  <1>    ret
  1747                                  %endif
  1748                                  
  1749                                  
  1750                                  %if _APL
  1751                                  	%include "apl.asm"
  1752                                  %endif
  1753                                  
  1754                                  
  1755                                  %if _BZP
  1756                                  	%include "bzp.asm"
  1757                                  %endif
  1758                                  
  1759                                  
  1760                                  %if _ZEROCOMP
  1761                                  	%include "zerocomp.asm"
  1762                                  %endif
  1763                                  
  1764                                  
  1765                                  %if _MVCOMP
  1766                                  	%include "mvcomp.asm"
  1767                                  %endif
  1768                                  
  1769                                  
  1770                                  %if _LZEXEDAT
  1771                                  	%include "lzexedat.asm"
  1772                                  %endif
  1773                                  
  1774                                  
  1775                                  %if _ALLOW_OVERLAPPING
  1776                                  		; INP:	?src, ?dst
  1777                                  		; OUT:	CY if error (?src < ?dst)
  1778                                  		;	NC if success
  1779                                  		; CHG:	ax, bx, cx, dx
  1780                                  check_pointers_not_overlapping:
  1781                                  %if CHECK_POINTERS_VARIABLE_DST
  1782                                  	 push word [bp + ?dst + 2]
  1783                                  	 push word [bp + ?dst]
  1784                                  %else
  1785 00000431 06                      	 push es
  1786 00000432 57                      	 push di
  1787                                  %endif
  1788 00000433 E86F00                  	call pointer_to_linear
  1789                                  
  1790 00000436 91                      	xchg cx, ax
  1791 00000437 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1792                                  
  1793                                  %if CHECK_POINTERS_VARIABLE_SRC
  1794                                  	 push word [bp + ?src + 2]
  1795                                  	 push word [bp + ?src]
  1796                                  %else
  1797 00000439 1E                      	 push ds
  1798 0000043A 56                      	 push si
  1799                                  %endif
  1800 0000043B E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1801                                  
  1802 0000043E 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1803 00000440 7502                    	jne @F
  1804 00000442 39C8                    	cmp ax, cx
  1805                                  @@:
  1806                                  					; (CY) if error (src < dst)
  1807                                  					; (NC) if no error
  1808 00000444 C3                      	retn
  1809                                  %endif
  1810                                  
  1811                                  	; This leaves the lframe context created within the
  1812                                  	;  specific depacker's file. The above function
  1813                                  	;  check_pointers_not_overlapping uses the frame.
  1814                                  	lleave ctx
  1815                                  
  1816                                  
  1817                                  		; INP:	ds:si = pointer
  1818                                  		;	es:di = pointer
  1819                                  		; OUT:	ds:si normalised
  1820                                  		;	es:di normalised
  1821                                  %if NEED_NORMALISE_BOTH_POINTERS
  1822                                  normalise_both_pointers:
  1823 00000445 06                      	 push es
  1824 00000446 57                      	 push di
  1825 00000447 E80A00                  	call normalise_pointer
  1826 0000044A 5F                      	 pop di
  1827 0000044B 07                      	 pop es
  1828                                  %endif
  1829                                  
  1830                                  normalise_dssi_pointer:
  1831 0000044C 1E                      	 push ds
  1832 0000044D 56                      	 push si
  1833 0000044E E80300                  	call normalise_pointer
  1834 00000451 5E                      	 pop si
  1835 00000452 1F                      	 pop ds
  1836 00000453 C3                      	retn
  1837                                  
  1838                                  
  1839                                  		; INP:	word [ss:sp + 2] = segment
  1840                                  		;	word [ss:sp] = offset
  1841                                  		;
  1842                                  		; Note:	Does not work correctly with pointers that point to
  1843                                  		;	 a HMA location. Do not use then!
  1844                                  normalise_pointer:
  1845                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1846                                  	lframe near
  1847                                  	lpar word,	segment
  1848                                  	lpar word,	offset
  1849                                  	lpar_return
  1850 00000454 5589E5                  	lenter
  1851                                  
  1852 00000457 837E040F                	cmp word [bp + ?offset], 15
  1853 0000045B 7617                    	jbe .ret
  1854                                  
  1855 0000045D 53                      	push bx
  1856 0000045E 51                      	push cx
  1857                                  
  1858 0000045F 31DB                    	xor bx, bx
  1859 00000461 31C9                    	xor cx, cx
  1860 00000463 FF7606                  	 push word [bp + ?segment]
  1861 00000466 FF7604                  	 push word [bp + ?offset]
  1862 00000469 E80A00                  	call normalise_pointer_with_displacement_bxcx
  1863 0000046C 8F4604                  	 pop word [bp + ?offset]
  1864 0000046F 8F4606                  	 pop word [bp + ?segment]
  1865                                  
  1866 00000472 59                      	pop cx
  1867 00000473 5B                      	pop bx
  1868                                  .ret:
  1869 00000474 5D                      	lleave
  1870 00000475 C3                      	lret
  1871                                  
  1872                                  
  1873                                  		; INP:	word [ss:sp + 2] = segment
  1874                                  		;	word [ss:sp] = offset
  1875                                  		;	bx:cx = add/sub displacement
  1876                                  		; OUT:	CY if the displacement carries
  1877                                  		;	NC if not
  1878                                  normalise_pointer_with_displacement_bxcx:
  1879                                  %endif
  1880                                  	lframe near
  1881                                  	lpar word,	segment
  1882                                  	lpar word,	offset
  1883                                  	lpar_return
  1884 00000476 5589E5                  	lenter
  1885                                  
  1886                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1887                                  	cmp word [bp + ?offset], 15
  1888                                  	jbe .ret
  1889                                  %endif
  1890                                  
  1891 00000479 50                      	push ax
  1892 0000047A 51                      	push cx
  1893 0000047B 52                      	push dx
  1894                                  
  1895 0000047C FF7606                  	 push word [bp + ?segment]
  1896 0000047F FF7604                  	 push word [bp + ?offset]
  1897 00000482 E82000                  	call pointer_to_linear
  1898                                  
  1899                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1900                                  	; push bx
  1901                                  	; 				; sign-extend cx into bx:cx
  1902                                  	; cmp cx, 8000h			; CY if < 8000h (NC if negative)
  1903                                  	; cmc				; NC if positive
  1904                                  	; sbb bx, bx			; 0 if was NC, -1 if was CY
  1905                                  
  1906 00000485 01C1                    	add cx, ax
  1907 00000487 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1908                                  	; pop bx
  1909 00000489 9F                      	lahf				; ah = flags
  1910                                  %else
  1911                                  	xchg ax, cx
  1912                                  %endif
  1913                                  
  1914                                  %if 0
  1915                                  		; Adds in HMA support for this function. Not currently used.
  1916                                  	cmp dx, 10h			; dx:ax >= 10_0000h ?
  1917                                  	jb @F				; no, linear-to-pointer normally -->
  1918                                  	; ja .error
  1919                                  
  1920                                  	add cx, 10h
  1921                                  	; jc .error
  1922                                  	mov word [bp + ?offset], cx
  1923                                  	or word [bp + ?segment], -1
  1924                                  	jmp .return
  1925                                  @@:
  1926                                  %endif
  1927                                  
  1928 0000048A 53                      	push bx
  1929 0000048B 89CB                    	mov bx, cx
  1930 0000048D 83E10F                  	and cx, 15
  1931 00000490 894E04                  	mov word [bp + ?offset], cx
  1932                                  
  1933 00000493 B104                    	mov cl, 4
  1934                                  @@:
  1935 00000495 D1EA                    	shr dx, 1
  1936 00000497 D1DB                    	rcr bx, 1
  1937 00000499 E2FA                    	loop @B
  1938                                  
  1939 0000049B 895E06                  	mov word [bp + ?segment], bx
  1940 0000049E 5B                      	pop bx
  1941                                  
  1942                                  	; test dx, dx
  1943                                  	; jnz .error
  1944                                  
  1945                                  .return:
  1946                                  
  1947                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1948 0000049F 9E                      	sahf				; restore flags from ah
  1949                                  %endif
  1950 000004A0 5A                      	pop dx
  1951 000004A1 59                      	pop cx
  1952 000004A2 58                      	pop ax
  1953                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1954                                  .ret:
  1955                                  %endif
  1956 000004A3 5D                      	lleave
  1957 000004A4 C3                      	lret
  1958                                  
  1959                                  
  1960                                  		; INP:	word [ss:sp + 2] = segment
  1961                                  		;	word [ss:sp] = offset
  1962                                  		; OUT:	dx:ax = linear address
  1963                                  pointer_to_linear:
  1964                                  	lframe near
  1965                                  	lpar word,	segment
  1966                                  	lpar word,	offset
  1967 000004A5 5589E5                  	lenter
  1968                                  
  1969 000004A8 8B4606                  	mov ax, word [bp + ?segment]
  1970 000004AB 31D2                    	xor dx, dx
  1971 000004AD 51                      	push cx
  1972 000004AE B90400                  	mov cx, 4
  1973                                  @@:
  1974 000004B1 D1E0                    	shl ax, 1
  1975 000004B3 D1D2                    	rcl dx, 1
  1976 000004B5 E2FA                    	loop @B
  1977                                  
  1978 000004B7 034604                  	add ax, word [bp + ?offset]
  1979 000004BA 11CA                    	adc dx, cx			; cx = 0 here
  1980 000004BC 59                      	pop cx
  1981                                  
  1982 000004BD 5D                      	lleave
  1983 000004BE C20400                  	lret
  1984                                  
  1985                                  
  1986                                  %if _PASSLCFG
  1987 000004C1 90<rep Fh>              	align 16
  1988                                  transfer_lcfg_block:
  1989 000004D0 90<rep 20h>             	times lcfg.size nop
  1990                                  %endif
  1991                                  	align 16
  1992                                  init1_end:
  1993                                  
  1994                                  
  1995                                  	usesection INIT0
  1996                                  %if _TEST_PROGRAM
  1997                                  init0_msg:
  1998 000001B2 4572726F723A204E6F-     .error_stderr:	db "Error: Not enough memory allocated.",13,10
  1998 000001BB 7420656E6F75676820-
  1998 000001C4 6D656D6F727920616C-
  1998 000001CD 6C6F63617465642E0D-
  1998 000001D6 0A                 
  1999                                  .error_stderr.length: equ $ - .error_stderr
  2000                                  .error_c_stdout:
  2001 000001D7 30                      .error_stdout:	db "0"
  2002                                  %if 0
  2003                                  		_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  2008                                  %endif
  2009 000001D8 0D0A                    		db 13,10
  2010                                  .error_c_stdout.length: equ $ - .error_c_stdout
  2011                                  .error_stdout.length: equ $ - .error_stdout
  2012                                  
  2013 000001DA 90<rep 226h>            	align 1024
  2014                                  %if ($ - $$) != 1024
  2015                                   %error Wrong INIT0 size
  2016                                  %endif
  2017                                  %endif
  2018                                  
  2019                                  	align 16
  2020                                  init0_end:
  2021                                  
  2022                                  
  2023                                  %assign num (init1_end - init1_start) + (init0_end - init0_start)
  2024                                  %if _BRIEFLZ
  2025                                  %define which iniblz
  2026                                  %elif _LZ4
  2027                                  %define which inilz4
  2028                                  %elif _SNAPPY
  2029                                  %define which inisz
  2030                                  %elif _EXODECR
  2031                                  %define which iniexo
  2032                                  %elif _X
  2033                                  %define which inix
  2034                                  %elif _HEATSHRINK
  2035                                  %define which inihs
  2036                                  %elif _LZD
  2037                                  %define which inilz
  2038                                  %elif _LZO
  2039                                  %define which inilzo
  2040                                  %elif _LZSA2
  2041                                  %define which inilzsa2
  2042                                  %elif _APL
  2043                                  %define which iniapl
  2044                                  %elif _BZP
  2045                                  %define which inibzp
  2046                                  %elif _ZEROCOMP
  2047                                  %define which inizero
  2048                                  %elif _MVCOMP
  2049                                  %define which inimv
  2050                                  %elif _LZEXEDAT
  2051                                  %define which inilzexe
  2052                                  %endif
  2053                                  %warning which: num bytes used for depacker
  2053          ******************       warning: inilzsa2: 2288 bytes used for depacker [-w+user]
  2054                                  
  2055                                  
  2056                                  %if _TEST_PROGRAM
  2057                                  	addsection INIT2, align=16 follows=INIT1 vstart=0
  2058                                  init2_start:
  2059                                  		; si => after PSP
  2060                                  		; cs => INIT2
  2061                                  		; psp, free, payload, init1, init2, payload space, stack
  2062                                  		;
  2063                                  		; The correct allocation for the test program
  2064                                  		;  is image size (init0, payload, init1, init2)
  2065                                  		;  minus init0 plus compressed payload size
  2066                                  		;  plus decompressed size plus stack. For
  2067                                  		;  simplicity, init0 subtraction may be skipped.
  2068                                  
  2069                                  		; ss:sp -> word amount repetitions, word ax
  2070                                  		; bx = 1 if A mode test,
  2071                                  		;	8001h if B mode test,
  2072                                  		;	4001h if C mode test
  2073 00000000 53                      	push bx
  2074                                  
  2075                                  	lframe 0
  2076                                  	lpar word,	repetitions
  2077                                  	lpar word,	whichtest
  2078 00000001 5589E5                  	lenter
  2079                                  
  2080 00000004 8B5604                  	mov dx, word [bp + ?repetitions]
  2081 00000007 83FAFF                  	cmp dx, -1
  2082 0000000A 7509                    	jne @F
  2083                                  
  2084                                  .cmdline_error:
  2085                                  %if _DEBUG0
  2086                                  	mov bx, -1
  2087                                  %endif
  2088 0000000C BA[D602]                	mov dx, init2_msg.cmdline_error
  2089 0000000F B92400                  	mov cx, init2_msg.cmdline_error.length
  2090 00000012 E98401                  	jmp init2_error
  2091                                  
  2092                                  
  2093                                  @@:
  2094 00000015 F6460340                	testopt [bp + ?whichtest], 4000h
  2095 00000019 750C                    	jnz .a_or_c
  2096 0000001B F6460380                	testopt [bp + ?whichtest], 8000h
  2097 0000001F 7406                    	jz .a_or_c
  2098                                  .b:
  2099 00000021 85D2                    	test dx, dx
  2100 00000023 74E7                    	jz .cmdline_error
  2101 00000025 EB04                    	jmp @F
  2102                                  
  2103                                  .a_or_c:
  2104 00000027 85D2                    	test dx, dx
  2105 00000029 75E1                    	jnz .cmdline_error
  2106                                  @@:
  2107                                  
  2108 0000002B 8CCA                    	mov dx, cs
  2109 0000002D 81C2F613                	add dx, (init2_end - init2_start) >> 4
  2110                                  				; => payload saving area
  2111 00000031 8CC8                    	mov ax, cs
  2112 00000033 2DF60D                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2115 00000036 B9A70D                  	mov cx, (payload_end - payload) >> 4
  2116 00000039 E8C102                  	call init2_movp		; copy payload to payload saving area
  2117                                  		; We save away the payload here because a failure
  2118                                  		;  to decompress generally overwrites part of that
  2119                                  		;  payload which was used as source.
  2120                                  
  2121 0000003C 89C2                    	mov dx, ax		; dx => payload source to use
  2122 0000003E 8CC8                    	mov ax, cs
  2123 00000040 83E84F                  	sub ax, (init1_end - init1_start) >> 4
  2124                                  				; ax => INIT1
  2125 00000043 BB0100                  	mov bx, 1		; say we're in EXE mode
  2126 00000046 52                      	push dx
  2127 00000047 50                      	push ax
  2128 00000048 56                      	push si			; si => target
  2129 00000049 0E                      	 push cs
  2130 0000004A E80D01                  	 call .transfer		; call decompression
  2131 0000004D 5E                      	pop si
  2132 0000004E 58                      	pop ax
  2133 0000004F 5A                      	pop dx
  2134                                  		; Returns here after decompression.
  2135                                  		; CY if error.
  2136 00000050 7309                    	jnc @F
  2137                                  
  2138 00000052 BA[2702]                	mov dx, init2_msg.initial_error
  2139 00000055 B93C00                  	mov cx, init2_msg.initial_error.length
  2140 00000058 E93E01                  	jmp init2_error
  2141                                  
  2142                                  @@:
  2143                                  	numdef INCLUDE_UNCOMPRESSED
  2144                                  	numdef WRITE_WRONG_FILE
  2145                                  %if _INCLUDE_UNCOMPRESSED
  2146                                  payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed
  2147                                  
  2148 0000005B E80201                  	call checkdecompressed
  2149 0000005E 7409                    	je @F
  2150                                  
  2151                                  %if _WRITE_WRONG_FILE
  2152                                  	call writefiles
  2153                                  %endif
  2154                                  
  2155                                  %if _DEBUG0
  2156                                  	mov bx, -1
  2157                                  %endif
  2158 00000060 BA[6302]                	mov dx, init2_msg.initial_error_2
  2159 00000063 B93C00                  	mov cx, init2_msg.initial_error_2.length
  2160 00000066 E93001                  	jmp init2_error
  2161                                  
  2162                                  @@:
  2163                                  %endif
  2164                                  
  2165 00000069 F6460340                	testopt [bp + ?whichtest], 4000h
  2166 0000006D 741D                    	jz @F
  2167 0000006F 8CC8                    	mov ax, cs
  2168 00000071 83E84F                  	sub ax, (init1_end - init1_start) >> 4
  2169                                  				; ax => INIT1
  2170 00000074 8EC0                    	mov es, ax
  2171 00000076 26A1[4C00]              	mov ax, word [es:init1_c_mode_counter]
  2172 0000007A E85601                  	call init2_disp_ax_dec
  2173 0000007D B00D                    	mov al, 13
  2174 0000007F E84601                  	call init2_disp_al
  2175 00000082 B00A                    	mov al, 10
  2176 00000084 E84101                  	call init2_disp_al
  2177 00000087 B8004C                  	mov ax, 4C00h
  2178 0000008A CD21                    	int 21h
  2179                                  
  2180                                  @@:
  2181                                  	lvar word,	upperbound
  2182 0000008C 52                      	 push dx
  2183                                  	lvar word,	lowerbound
  2184 0000008D 56                      	 push si
  2185                                  	lvar word,	current_init1
  2186 0000008E 50                      	 push ax
  2187                                  
  2188                                  %if _TEST_PROGRESS
  2189 0000008F BA[1C02]                	mov dx, init2_msg.progress.1
  2190 00000092 B90700                  	mov cx, init2_msg.progress.1.length
  2191                                  .loop:
  2192 00000095 0E                      	push cs
  2193 00000096 1F                      	pop ds
  2194 00000097 BB0200                  	mov bx, 2
  2195 0000009A B440                    	mov ah, 40h
  2196 0000009C CD21                    	int 21h
  2197                                  %else
  2198                                  .loop:
  2199                                  %endif
  2200                                  
  2201 0000009E 8B56FE                  	mov dx, [bp + ?upperbound]
  2202                                  
  2203 000000A1 F6460380                	testopt [bp + ?whichtest], 8000h
  2204 000000A5 7419                    	jz @F
  2205                                  
  2206 000000A7 FF4E04                  	dec word [bp + ?repetitions]
  2207 000000AA 751E                    	jnz .test_b_skip_bound
  2208                                  
  2209                                  %if _TEST_PROGRESS
  2210 000000AC 0E                      	push cs
  2211 000000AD 1F                      	pop ds
  2212 000000AE BA[2502]                	mov dx, init2_msg.progress.linebreak
  2213 000000B1 B90200                  	mov cx, init2_msg.progress.linebreak.length
  2214 000000B4 BB0200                  	mov bx, 2
  2215 000000B7 B440                    	mov ah, 40h
  2216 000000B9 CD21                    	int 21h
  2217                                  %endif
  2218 000000BB B8004C                  	mov ax, 4C00h
  2219 000000BE CD21                    	int 21h
  2220                                  
  2221                                  
  2222                                  @@:
  2223 000000C0 2B56FC                  	sub dx, [bp + ?lowerbound]
  2224 000000C3 746C                    	jz .found
  2225 000000C5 D1EA                    	shr dx, 1
  2226                                  		; Rounding down, so that we never retry upper bound.
  2227                                  		;  The upper bound is known to be working.
  2228 000000C7 0356FC                  	add dx, [bp + ?lowerbound]
  2229                                  
  2230                                  .test_b_skip_bound:
  2231 000000CA 52                      	push dx
  2232 000000CB 81C2A70D                	add dx, (payload_end - payload) >> 4
  2233 000000CF 8B46FA                  	mov ax, [bp + ?current_init1]
  2234 000000D2 B94F00                  	mov cx, (init1_end - init1_start) >> 4
  2235 000000D5 E82502                  	call init2_movp
  2236 000000D8 8956FA                  	mov [bp + ?current_init1], dx
  2237 000000DB 5A                      	pop dx
  2238                                  
  2239 000000DC 8CC8                    	mov ax, cs
  2240 000000DE 05F613                  	add ax, (init2_end - init2_start) >> 4
  2241                                  				; => payload in saving area
  2242 000000E1 B9A70D                  	mov cx, (payload_end - payload) >> 4
  2243 000000E4 E81602                  	call init2_movp		; copy payload from payload saving area
  2244                                  
  2245                                  		; dx => source
  2246 000000E7 8B46FA                  	mov ax, [bp + ?current_init1]
  2247 000000EA BB0100                  	mov bx, 1
  2248 000000ED 52                      	push dx
  2249 000000EE 56                      	push si
  2250 000000EF 0E                      	 push cs
  2251 000000F0 E86700                  	 call .transfer
  2252 000000F3 5E                      	pop si
  2253 000000F4 5A                      	pop dx
  2254                                  		; Returns here after decompression.
  2255                                  		; CY if error.
  2256 000000F5 7312                    	jnc @F
  2257                                  
  2258 000000F7 F6460380                	testopt [bp + ?whichtest], 8000h
  2259 000000FB 7511                    	jnz .test_b_fail
  2260                                  
  2261                                  		; error: this attempt is one below the new lower bound
  2262 000000FD 42                      	inc dx
  2263 000000FE 8956FC                  	mov word [bp + ?lowerbound], dx
  2264                                  
  2265                                  %if _TEST_PROGRESS
  2266 00000101 BA[2302]                	mov dx, init2_msg.progress.fail
  2267 00000104 B90100                  	mov cx, init2_msg.progress.fail.length
  2268                                  %endif
  2269 00000107 EB8C                    	jmp .loop
  2270                                  
  2271                                  @@:
  2272                                  %if _INCLUDE_UNCOMPRESSED
  2273 00000109 E85400                  	call checkdecompressed
  2274 0000010C 7417                    	je @F
  2275                                  
  2276                                  %if _WRITE_WRONG_FILE
  2277                                  	call writefiles
  2278                                  %endif
  2279                                  
  2280                                  .test_b_fail:
  2281                                  %if _TEST_PROGRESS
  2282 0000010E 0E                      	push cs
  2283 0000010F 1F                      	pop ds
  2284 00000110 BA[2502]                	mov dx, init2_msg.progress.linebreak
  2285 00000113 B90200                  	mov cx, init2_msg.progress.linebreak.length
  2286 00000116 BB0200                  	mov bx, 2
  2287 00000119 B440                    	mov ah, 40h
  2288 0000011B CD21                    	int 21h
  2289                                  %endif
  2290                                  %if _DEBUG0
  2291                                  	mov bx, -2
  2292                                  %endif
  2293 0000011D BA[9F02]                	mov dx, init2_msg.subsequent_error_2
  2294 00000120 B93700                  	mov cx, init2_msg.subsequent_error_2.length
  2295 00000123 EB74                    	jmp init2_error
  2296                                  
  2297                                  @@:
  2298                                  %endif
  2299                                  		; success: this attempt is the new upper bound
  2300 00000125 8956FE                  	mov word [bp + ?upperbound], dx
  2301                                  %if _TEST_PROGRESS
  2302 00000128 BA[2402]                	mov dx, init2_msg.progress.success
  2303 0000012B B90100                  	mov cx, init2_msg.progress.success.length
  2304                                  %endif
  2305 0000012E E964FF                  	jmp .loop
  2306                                  
  2307                                  .found:
  2308                                  %if _TEST_PROGRESS
  2309 00000131 0E                      	push cs
  2310 00000132 1F                      	pop ds
  2311 00000133 BA[2502]                	mov dx, init2_msg.progress.linebreak
  2312 00000136 B90200                  	mov cx, init2_msg.progress.linebreak.length
  2313 00000139 BB0200                  	mov bx, 2
  2314 0000013C B440                    	mov ah, 40h
  2315 0000013E CD21                    	int 21h
  2316                                  %endif
  2317 00000140 8B46FE                  	mov ax, word [bp + ?upperbound]
  2318 00000143 29F0                    	sub ax, si		; = how many paragraphs in buffer before source
  2319 00000145 05F60D                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  2321                                  				; = how many paragraphs needed for process
  2322 00000148 E88800                  	call init2_disp_ax_dec
  2323 0000014B B00D                    	mov al, 13
  2324 0000014D E87800                  	call init2_disp_al
  2325 00000150 B00A                    	mov al, 10
  2326 00000152 E87300                  	call init2_disp_al
  2327 00000155 B8004C                  	mov ax, 4C00h
  2328 00000158 CD21                    	int 21h
  2329                                  
  2330                                  
  2331                                  .transfer:
  2332 0000015A 31FF                    	xor di, di
  2333 0000015C 57                      	push di			; placeholder ax value on stack
  2334 0000015D 50                      	push ax			; INIT1 segment
  2335 0000015E 57                      	push di			; zero = init1_start
  2336 0000015F CB                      	retf			; transfer to INIT1:init1_start
  2337                                  
  2338                                  
  2339                                  
  2340                                  %if _INCLUDE_UNCOMPRESSED
  2341                                  
  2342                                  
  2343                                  %if _WRITE_WRONG_FILE
  2344                                  writefiles:
  2345                                  	push cs
  2346                                  	pop ds
  2347                                  	mov dx, init2_msg.wrong_file_name
  2348                                  	xor cx, cx
  2349                                  	mov ah, 3Ch
  2350                                  	int 21h
  2351                                  	jc .notfile
  2352                                  
  2353                                  	mov bx, ax
  2354                                  	mov cx, payload_uncompressed_size >> 4
  2355                                  	xor dx, dx
  2356                                  .loopfile:
  2357                                  	mov ds, si
  2358                                  	mov ah, 40h
  2359                                  	push cx
  2360                                  	mov cx, 16
  2361                                  	int 21h
  2362                                  	pop cx
  2363                                  	inc si
  2364                                  	loop .loopfile
  2365                                  
  2366                                  	mov ds, si
  2367                                  	mov cx, payload_uncompressed_size & 15
  2368                                  	mov ah, 40h
  2369                                  	int 21h
  2370                                  
  2371                                  	mov ah, 3Eh
  2372                                  	int 21h
  2373                                  
  2374                                  .notfile:
  2375                                  
  2376                                  	push cs
  2377                                  	pop ds
  2378                                  	mov dx, init2_msg.wrong_file_name2
  2379                                  	xor cx, cx
  2380                                  	mov ah, 3Ch
  2381                                  	int 21h
  2382                                  	jc .notfile2
  2383                                  
  2384                                  	mov bx, ax
  2385                                  	mov cx, payload_uncompressed_size >> 4
  2386                                  	mov si, cs
  2387                                  	add si, (payload_uncompressed - init2_start) >> 4
  2388                                  	xor dx, dx
  2389                                  .loopfile2:
  2390                                  	mov ds, si
  2391                                  	mov ah, 40h
  2392                                  	push cx
  2393                                  	mov cx, 16
  2394                                  	int 21h
  2395                                  	pop cx
  2396                                  	inc si
  2397                                  	loop .loopfile2
  2398                                  
  2399                                  	mov ds, si
  2400                                  	mov cx, payload_uncompressed_size & 15
  2401                                  	mov ah, 40h
  2402                                  	int 21h
  2403                                  
  2404                                  	mov ah, 3Eh
  2405                                  	int 21h
  2406                                  
  2407                                  .notfile2:
  2408                                  	retn
  2409                                  %endif
  2410                                  
  2411                                  		; INP:	si => decompressed image
  2412                                  		; OUT:	ZR if matching
  2413                                  		;	NZ if mismatching
  2414                                  		; CHG:	es, ds, di, bx, cx
  2415                                  		; STT:	UP
  2416                                  checkdecompressed:
  2417 00000160 50                      	push ax
  2418 00000161 52                      	push dx
  2419 00000162 56                      	push si
  2420                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  2421                                  	mov cx, _PAYLOAD_KERNEL_MAX_PARAS
  2422                                  	mov bx, 0
  2423                                  %else
  2424 00000163 B9BC13                  	mov cx, payload_uncompressed_size >> 4
  2425 00000166 BB0000                  	mov bx, payload_uncompressed_size & 15
  2426                                  %endif
  2427 00000169 8CCF                    	mov di, cs
  2428 0000016B 83C739                  	add di, (payload_uncompressed - init2_start) >> 4
  2429 0000016E E319                    	jcxz .end
  2430                                  .loop:
  2431 00000170 51                      	push cx
  2432 00000171 B90800                  	mov cx, 8
  2433 00000174 8EDE                    	mov ds, si
  2434 00000176 8EC7                    	mov es, di
  2435 00000178 46                      	inc si
  2436 00000179 47                      	inc di
  2437 0000017A 56                      	push si
  2438 0000017B 57                      	push di
  2439 0000017C 31F6                    	xor si, si
  2440 0000017E 31FF                    	xor di, di
  2441 00000180 F3A7                    	repe cmpsw
  2442 00000182 5F                      	pop di
  2443 00000183 5E                      	pop si
  2444 00000184 59                      	pop cx
  2445 00000185 750E                    	jne .ret
  2446 00000187 E2E7                    	loop .loop
  2447                                  .end:
  2448 00000189 8EDE                    	mov ds, si
  2449 0000018B 8EC7                    	mov es, di
  2450 0000018D 31F6                    	xor si, si
  2451 0000018F 31FF                    	xor di, di		; (ZR)
  2452 00000191 89D9                    	mov cx, bx
  2453 00000193 F3A6                    	repe cmpsb
  2454                                  .ret:
  2455 00000195 5E                      	pop si
  2456 00000196 5A                      	pop dx
  2457 00000197 58                      	pop ax
  2458 00000198 C3                      	retn
  2459                                  %endif
  2460                                  
  2461                                  
  2462                                  init2_error:
  2463                                  %if _DEBUG0
  2464                                  	push bx
  2465                                  %endif
  2466 00000199 0E                      	push cs
  2467 0000019A 1F                      	pop ds
  2468 0000019B BB0200                  	mov bx, 2
  2469 0000019E B440                    	mov ah, 40h
  2470 000001A0 CD21                    	int 21h
  2471                                  
  2472                                  %if _DEBUG0
  2473                                  	mov dx, init2_msg.rc
  2474                                  	mov cx, init2_msg.rc.length
  2475                                  	mov bx, 2
  2476                                  	mov ah, 40h
  2477                                  	int 21h
  2478                                  	pop ax
  2479                                  	call init2_error_disp_ax_hex
  2480                                  	mov dx, init2_msg.linebreak
  2481                                  	mov cx, init2_msg.linebreak.length
  2482                                  	mov bx, 2
  2483                                  	mov ah, 40h
  2484                                  	int 21h
  2485                                  %endif
  2486                                  
  2487 000001A2 F6460340                	testopt [bp + ?whichtest], 4000h
  2488 000001A6 7408                    	jz @F
  2489 000001A8 BA[FA02]                	mov dx, init2_msg.error_c_stdout
  2490 000001AB B90300                  	mov cx, init2_msg.error_c_stdout.length
  2491 000001AE EB0C                    	jmp @FF
  2492                                  @@:
  2493 000001B0 F6460380                	testopt [bp + ?whichtest], 8000h
  2494 000001B4 750D                    	jnz @FF
  2495 000001B6 BA[FA02]                	mov dx, init2_msg.error_stdout
  2496 000001B9 B90300                  	mov cx, init2_msg.error_stdout.length
  2497                                  @@:
  2498 000001BC BB0100                  	mov bx, 1
  2499 000001BF B440                    	mov ah, 40h
  2500 000001C1 CD21                    	int 21h
  2501                                  @@:
  2502 000001C3 B8FF4C                  	mov ax, 4CFFh
  2503 000001C6 CD21                    	int 21h
  2504                                  
  2505                                  	lleave ctx
  2506                                  
  2507                                  
  2508                                  %if _DEBUG0
  2509                                  init2_error_disp_ax_hex:	; ax
  2510                                  		xchg al,ah
  2511                                  		call init2_error_disp_al_hex	; display former ah
  2512                                  		xchg al,ah			;  and fall trough for al
  2513                                  init2_error_disp_al_hex:	; al
  2514                                  		push cx
  2515                                  		mov cl,4
  2516                                  		ror al,cl
  2517                                  		call init2_error_disp_al_lownibble_hex
  2518                                  						; display former high-nibble
  2519                                  		rol al,cl
  2520                                  		pop cx
  2521                                  						;  and fall trough for low-nibble
  2522                                  init2_error_disp_al_lownibble_hex:
  2523                                  		push ax			 ; save ax for call return
  2524                                  		and al,00001111b		; high nibble must be zero
  2525                                  		add al,'0'			; if number is 0-9, now it's the correct character
  2526                                  		cmp al,'9'
  2527                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  2528                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  2529                                   .decimalnum:
  2530                                  		call init2_error_disp_al
  2531                                  		pop ax
  2532                                  		retn
  2533                                  
  2534                                  
  2535                                  init2_error_disp_al:
  2536                                  	push dx
  2537                                  	push cx
  2538                                  	push bx
  2539                                  	push ax
  2540                                  	mov dx, sp
  2541                                  	push ds
  2542                                  	 push ss
  2543                                  	 pop ds
  2544                                  	mov cx, 1
  2545                                  	mov bx, 2
  2546                                  	mov ah, 40h
  2547                                  	int 21h
  2548                                  	pop ds
  2549                                  	pop ax
  2550                                  	pop bx
  2551                                  	pop cx
  2552                                  	pop dx
  2553                                  	retn
  2554                                  %endif
  2555                                  
  2556                                  
  2557                                  init2_disp_al:
  2558 000001C8 52                      	push dx
  2559 000001C9 50                      	push ax
  2560 000001CA 88C2                    	mov dl, al
  2561 000001CC B402                    	mov ah, 2
  2562 000001CE CD21                    	int 21h
  2563 000001D0 58                      	pop ax
  2564 000001D1 5A                      	pop dx
  2565 000001D2 C3                      	retn
  2566                                  
  2567                                  
  2568                                  		; Display number in ax decimal
  2569                                  		;
  2570                                  		; INP:	ax = number
  2571                                  		; OUT:	displayed using Int21.02
  2572                                  		; CHG:	none
  2573                                  init2_disp_ax_dec:			; ax (no leading zeros)
  2574 000001D3 53                      		push bx
  2575 000001D4 31DB                    		xor bx, bx
  2576                                  .pushax:
  2577 000001D6 52                      		push dx
  2578 000001D7 50                      		push ax
  2579 000001D8 08DB                    		or bl, bl
  2580 000001DA 7405                    		jz .nobl
  2581 000001DC 80EB05                  		sub bl, 5
  2582 000001DF F6DB                    		neg bl
  2583                                  .nobl:
  2584 000001E1 51                      		push cx
  2585 000001E2 B91027                  		mov cx, 10000
  2586 000001E5 E81B00                  		call .divide_out
  2587 000001E8 B9E803                  		mov cx, 1000
  2588 000001EB E81500                  		call .divide_out
  2589 000001EE B96400                  		mov cx, 100
  2590 000001F1 E80F00                  		call .divide_out
  2591 000001F4 B10A                    		mov cl, 10
  2592 000001F6 E80A00                  		call .divide_out
  2593                                  							; (Divisor 1 is useless)
  2594 000001F9 0430                    		add al, '0'
  2595 000001FB E8CAFF                  		call init2_disp_al
  2596 000001FE 59                      		pop cx
  2597 000001FF 58                      		pop ax
  2598 00000200 5A                      		pop dx
  2599 00000201 5B                      		pop bx					; Caller's register
  2600 00000202 C3                      		retn
  2601                                  
  2602                                  
  2603                                  		; INP:	ax = number
  2604                                  		;	cx = divisor
  2605                                  		; OUT:	ax = remainder of operation
  2606                                  		;	result displayed
  2607                                  .divide_out:
  2608 00000203 52                      		push dx
  2609 00000204 31D2                    		xor dx, dx
  2610 00000206 F7F1                    		div cx				; 0:ax / cx
  2611 00000208 52                      		push dx				; remainder
  2612 00000209 FECB                    		dec bl
  2613 0000020B 7503                    		jnz .nobl2
  2614 0000020D 80CF01                  		or bh, 1
  2615                                  .nobl2:
  2616 00000210 08C7                    		or bh, al
  2617 00000212 7405                    		jz .leadingzero
  2618 00000214 0430                    		add al, '0'
  2619 00000216 E8AFFF                  		call init2_disp_al		; display result
  2620                                   .leadingzero:
  2621 00000219 58                      		pop ax				; remainder
  2622 0000021A 5A                      		pop dx
  2623 0000021B C3                      		retn
  2624                                  
  2625                                  
  2626                                  init2_msg:
  2627                                  %if _TEST_PROGRESS
  2628 0000021C 496E666F3A2031          .progress.1:		db "Info: 1"
  2629                                  .progress.1.length: equ $ - .progress.1
  2630 00000223 46                      .progress.fail:		db "F"
  2631                                  .progress.fail.length: equ $ - .progress.fail
  2632 00000224 53                      .progress.success:	db "S"
  2633                                  .progress.success.length: equ $ - .progress.success
  2634 00000225 0D0A                    .progress.linebreak:	db 13,10
  2635                                  .progress.linebreak.length: equ $ - .progress.linebreak
  2636                                  %endif
  2637                                  %if _WRITE_WRONG_FILE
  2638                                  .wrong_file_name:	asciz "WRONG.BIN"
  2639                                  .wrong_file_name2:	asciz "WRONG2.BIN"
  2640                                  %endif
  2641 00000227 4572726F723A205465-     .initial_error:	db "Error: Test program failed to decompress with full buffer."
  2641 00000230 73742070726F677261-
  2641 00000239 6D206661696C656420-
  2641 00000242 746F206465636F6D70-
  2641 0000024B 726573732077697468-
  2641 00000254 2066756C6C20627566-
  2641 0000025D 6665722E           
  2642 00000261 0D0A                    .linebreak:	db 13,10
  2643                                  .initial_error.length: equ $ - .initial_error
  2644                                  .linebreak.length: equ $ - .linebreak
  2645                                  %if _DEBUG0
  2646                                  .rc:	db "Error: Failure code="
  2647                                  .rc.length: equ $ - .rc
  2648                                  %endif
  2649                                  %if _INCLUDE_UNCOMPRESSED
  2650 00000263 4572726F723A205465-     .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  2650 0000026C 73742070726F677261-
  2650 00000275 6D206465636F6D7072-
  2650 0000027E 65737365642077726F-
  2650 00000287 6E676C792077697468-
  2650 00000290 2066756C6C20627566-
  2650 00000299 6665722E0D0A       
  2651                                  .initial_error_2.length: equ $ - .initial_error_2
  2652 0000029F 4572726F723A205465-     .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  2652 000002A8 73742070726F677261-
  2652 000002B1 6D206465636F6D7072-
  2652 000002BA 65737365642077726F-
  2652 000002C3 6E676C792064757269-
  2652 000002CC 6E6720746573742E0D-
  2652 000002D5 0A                 
  2653                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  2654                                  %endif
  2655 000002D6 4572726F723A20496E-     .cmdline_error:	db "Error: Invalid command line input.",13,10
  2655 000002DF 76616C696420636F6D-
  2655 000002E8 6D616E64206C696E65-
  2655 000002F1 20696E7075742E0D0A 
  2656                                  .cmdline_error.length: equ $ - .cmdline_error
  2657                                  
  2658                                  .error_c_stdout:
  2659 000002FA 30                      .error_stdout:	db "0"
  2660                                  %if 0
  2661                                  		_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  2666                                  %endif
  2667 000002FB 0D0A                    		db 13,10
  2668                                  .error_c_stdout.length: equ $ - .error_c_stdout
  2669                                  .error_stdout.length: equ $ - .error_stdout
  2670                                  
  2671                                  
  2672                                  		; Move paragraphs
  2673                                  		;
  2674                                  		; INP:	ax => source
  2675                                  		;	dx => destination
  2676                                  		;	cx = number of paragraphs
  2677                                  		; CHG:	-
  2678                                  		; OUT:	ax and dx unchanged
  2679                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  2680                                  		;	Do not provide a wrapped/HMA source or destination!
  2681                                  init2_movp:
  2682 000002FD 51                      	push cx
  2683 000002FE 1E                      	push ds
  2684 000002FF 56                      	push si
  2685 00000300 06                      	push es
  2686 00000301 57                      	push di
  2687                                  
  2688 00000302 39D0                    	cmp ax, dx		; source above destination ?
  2689 00000304 770A                    	ja .up			; yes, move up (forwards) -->
  2690 00000306 747B                    	je .return		; same, no need to move -->
  2691 00000308 50                      	push ax
  2692 00000309 01C8                    	add ax, cx		; (expected not to carry)
  2693 0000030B 39D0                    	cmp ax, dx		; end of source is above destination ?
  2694 0000030D 58                      	pop ax
  2695 0000030E 7730                    	ja .down		; yes, move from top down -->
  2696                                  	; Here, the end of source is below-or-equal the destination,
  2697                                  	;  so they do not overlap. In this case we prefer moving up.
  2698                                  
  2699                                  .up:
  2700 00000310 50                      	push ax
  2701 00000311 52                      	push dx
  2702                                  .uploop:
  2703 00000312 8ED8                    	mov ds, ax
  2704 00000314 8EC2                    	mov es, dx
  2705 00000316 31FF                    	xor di, di
  2706 00000318 31F6                    	xor si, si		; -> start of segment
  2707 0000031A 81E90010                	sub cx, 1000h		; 64 KiB left ?
  2708 0000031E 7610                    	jbe .uplast		; no -->
  2709 00000320 51                      	push cx
  2710 00000321 B90080                  	mov cx, 10000h /2
  2711 00000324 F3A5                    	rep movsw		; move 64 KiB
  2712 00000326 59                      	pop cx
  2713 00000327 050010                  	add ax, 1000h
  2714 0000032A 81C20010                	add dx, 1000h		; -> next segment
  2715 0000032E EBE2                    	jmp short .uploop	; proceed for more -->
  2716                                  .uplast:
  2717 00000330 81C10010                	add cx, 1000h		; restore counter
  2718 00000334 D1E1                    	shl cx, 1
  2719 00000336 D1E1                    	shl cx, 1
  2720 00000338 D1E1                    	shl cx, 1		; *8, paragraphs to words
  2721 0000033A F3A5                    	rep movsw		; move last part
  2722 0000033C 5A                      	pop dx
  2723 0000033D 58                      	pop ax
  2724 0000033E EB43                    	jmp short .return
  2725                                  
  2726                                  .down:
  2727 00000340 FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
  2728                                  .dnloop:
  2729 00000341 81E90010                	sub cx, 1000h		; 64 KiB left ?
  2730 00000345 761A                    	jbe .dnlast		; no -->
  2731 00000347 50                      	push ax
  2732 00000348 52                      	push dx
  2733 00000349 01C8                    	add ax, cx
  2734 0000034B 01CA                    	add dx, cx
  2735 0000034D 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
  2736 0000034F 8EC2                    	mov es, dx
  2737 00000351 5A                      	pop dx
  2738 00000352 58                      	pop ax
  2739 00000353 BFFEFF                  	mov di, -2
  2740 00000356 89FE                    	mov si, di		; moved from last word down
  2741 00000358 51                      	push cx
  2742 00000359 B90080                  	mov cx, 10000h /2
  2743 0000035C F3A5                    	rep movsw		; move 64 KiB
  2744 0000035E 59                      	pop cx
  2745 0000035F EBE0                    	jmp short .dnloop	; proceed for more -->
  2746                                  .dnlast:
  2747 00000361 81C10010                	add cx, 1000h		; restore counter
  2748 00000365 D1E1                    	shl cx, 1
  2749 00000367 D1E1                    	shl cx, 1
  2750 00000369 D1E1                    	shl cx, 1		; *8, paragraphs to words
  2751 0000036B 89CF                    	mov di, cx
  2752 0000036D 4F                      	dec di
  2753 0000036E D1E7                    	shl di, 1		; words to offset, -> last word
  2754 00000370 89FE                    	mov si, di
  2755 00000372 8ED8                    	mov ds, ax
  2756 00000374 8EC2                    	mov es, dx		; first segment correct
  2757                                  
  2758                                  		; Refer to comment in init0_movp.
  2759                                  %if _AMD_ERRATUM_109_WORKAROUND
  2760 00000376 E308                    	jcxz @FF
  2761 00000378 83F914                  	cmp cx, 20
  2762 0000037B 7703                    	ja @FF
  2763                                  @@:
  2764 0000037D A5                      	movsw
  2765 0000037E E2FD                    	loop @B
  2766                                  @@:
  2767                                  %endif
  2768 00000380 F3A5                    	rep movsw		; move first part
  2769 00000382 FC                      	cld
  2770                                  .return:
  2771 00000383 5F                      	pop di
  2772 00000384 07                      	pop es
  2773 00000385 5E                      	pop si
  2774 00000386 1F                      	pop ds
  2775 00000387 59                      	pop cx
  2776 00000388 C3                      	retn
  2777                                  
  2778                                  
  2779 00000389 90<rep 7h>              	align 16
  2780                                  
  2781                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  2782                                  %if _INCLUDE_UNCOMPRESSED
  2783                                  payload_uncompressed:
  2784 00000390 <bin 13BC0h>            	incbin _UNCOMPRESSED_FILE
  2785                                  .end:
  2786 00013F50 26                      	db 38
  2787 00013F51 26<rep Fh>              	align 16, db 38
  2788                                  %endif
  2789                                  init2_end:
  2790                                  %endif
  2791                                  
