     1                                  
     2                                  %if 0
     3                                  
     4                                  lDOS iniload packed payload
     5                                   by 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 ALLOW_OVERLAPPING,	1	; allow overlapping src and dst
    57                                  	numdef TEST_PROGRAM,		0
    58                                  	numdef TEST_PROGRAM_DECOMPRESSED_SIZE,		0,0
    59                                  %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE
    60                                   %error Test program has to learn of decompressed size.
    61                                  %endif
    62                                  	numdef TEST_PROGRESS,	0
    63                                  
    64                                  	numdef EXEC_OFFSET,	0
    65                                  	numdef EXEC_SEGMENT,	0
    66                                  	numdef IMAGE_EXE,	0
    67                                  %if ! _IMAGE_EXE && _TEST_PROGRAM
    68                                   %error Test program can only be used as EXE.
    69                                  %endif
    70                                  	numdef IMAGE_EXE_CS,	-16	; relative-segment for CS
    71                                  	numdef IMAGE_EXE_IP,	256 +64	; value for IP
    72                                  		; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0.
    73                                  	numdef IMAGE_EXE_SS,	-16	; relative-segment for SS
    74                                  	numdef IMAGE_EXE_SP,	0FFFEh	; value for SP (0 underflows)
    75                                  	numdef IMAGE_EXE_AUTO_STACK,	0, 2048	; use stack behind image
    76                                  		; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of
    77                                  		;  the same name. This one is only used as a flag; if non-zero,
    78                                  		;  keep the stack given to us by iniload; if zero, set up the
    79                                  		;  stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP.
    80                                  	numdef IMAGE_EXE_GET_COM_STACK, 0
    81                                  					; set up stack for flat .COM style entry
    82                                  	numdef DEVICE,			0
    83                                  	gendef DEVICE_NAME,		""
    84                                  	numdef DEVICE_ATTRIBUTE,	8000h
    85                                  	numdef DEVICE_ZERO_ENTRYPOINT,	0
    86                                  	numdef BOOTLDR,		1	; support boot loaded entrypoint
    87                                  
    88                                  	numdef BRIEFLZ,		0
    89                                  	numdef LZ4,		0
    90                                  	numdef SNAPPY,		0
    91                                  	numdef EXODECR,		0
    92                                  	numdef X,		0
    93                                  	numdef HEATSHRINK,	0
    94                                  	numdef LZD,		0
    95                                  	numdef LZO,		0
    96                                  	numdef LZSA2,		0
    97                                  	numdef APL,		0
    98                                  	numdef BZP,		0
    99                                  %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK 	+ !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP) != 1
   101                                   %fatal Exactly one compression method must be selected.
   102                                  %endif
   103                                  %assign ADDITIONAL_MEMORY 0
   104                                  %if _BRIEFLZ
   105                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BLZ"
   106                                  %elif _LZ4
   107                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ4"
   108                                  %elif _SNAPPY
   109                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SZ"
   110                                  %elif _EXODECR
   111                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.EXO"
   112                                  %elif _X
   113                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.X"
   114                                  %elif _HEATSHRINK
   115                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.HS"
   116                                  %elif _LZD
   117                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ"
   118                                  %elif _LZO
   119                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZO"
   120                                  %elif _LZSA2
   121                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SA2"
   122                                  %elif _APL
   123                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.APL"
   124                                  %elif _BZP
   125                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BZP"
   126                                  %endif
   127                                  	numdef PAYLOAD_KERNEL_MAX_PARAS,	0, 0
   128                                  %if _PAYLOAD_KERNEL_MAX_PARAS && ! _IMAGE_EXE
   129                                   %error Kernel mode max paras requires building dual-mode executable
   130                                  %endif
   131                                  	numdef COUNTER,		0, 32
   132                                  %if (_COUNTER - 1) & _COUNTER
   133                                   %error COUNTER must be a power of two
   134                                  %endif
   135                                  
   136                                  	strdef INILOAD_CFG, ""
   137                                  %ifnidn _INILOAD_CFG, ""
   138                                   %include _INILOAD_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> strdef INILOAD_SIGNATURE, "eb"
     3                              <1> %assign _DEVICE 1
     4                              <1> %assign _DEVICE_ZERO_ENTRYPOINT 1
     5                              <1> %assign _DEVICE_ATTRIBUTE 8800h
     6                              <1> %define _DEVICE_NAME "LDEBUG$$"
   139                                  %endif
   140                                  
   141                                  %if _DEVICE
   142                                   %ifidn _DEVICE_NAME, ""
   143                                    %error Device name must be set
   144                                   %endif
   145                                  %endif
   146                                  
   147                                  
   148                                  	cpu 8086
   149                                  	section INIT0 start=0 vstart=0
   150                                  init0_start:
   151                                  %if _DEVICE
   152                                  		; The device header is of a fixed format.
   153                                  		;  For our purposes, the 4-byte code for
   154                                  		;  each the strategy entry and the
   155                                  		;  interrupt entry is part of this format.
   156                                  		; (DOS may read the attributes or entrypoint
   157                                  		;  offsets before calling either, so in the inicomp
   158                                  		;  stage we need to recreate in the entrypoints part
   159                                  		;  exactly what the application has here.)
   160                                  device_header:
   161                                  .next:
   162                                   %if _DEVICE_ZERO_ENTRYPOINT
   163 00000000 EB3E                    	fill 2, -1, jmp strict short j_zero_entrypoint
   164 00000002 FFFF                    	dw -1
   165                                   %else
   166                                  	dd -1				; link to next device
   167                                   %endif
   168                                  .attributes:
   169 00000004 0088                    	dw _DEVICE_ATTRIBUTE		; attributes
   170                                  .strategy:
   171 00000006 [1200]                  	dw .strategy_entry		; -> strategy entry
   172                                  .interrupt:
   173 00000008 [1600]                  	dw .interrupt_entry		; -> interrupt entry
   174                                  .name:
   175 0000000A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME	; character device name,
   176                                  					;  or block device number of units
   177                                  					;  + optional name
   178                                  .strategy_entry:
   179 00000012 E9DB0090                	fill 4, 90h, jmp device_entrypoint
   180                                  .interrupt_entry:
   181 00000016 CB90<rep 3h>            	fill 4, 90h, retf
   182                                  %endif
   183                                  
   184                                  
   185                                  %if _IMAGE_EXE || _DEVICE
   186 0000001A 90                      	nop
   187 0000001B 90<rep 5h>              	align 32, nop
   188                                  init0_kernel_entry:
   189                                  		; cs:ip = load seg : 32 here
   190                                  %if ($ - $$) != 32
   191                                   %error Wrong kernel mode entrypoint
   192                                  %endif
   193                                  %if _TEST_PROGRAM
   194                                  @@:
   195 00000020 CC                      	int3
   196 00000021 FB                      	sti
   197 00000022 F4                      	hlt
   198 00000023 EBFB                    	jmp @B
   199                                  %endif
   200                                  %if _BOOTLDR
   201                                  %if ! _IMAGE_EXE
   202                                  j_zero_entrypoint:
   203                                  %endif
   204 00000025 31DB                    	xor bx, bx		; 0 = kernel mode
   205 00000027 50                      	push ax
   206 00000028 8CC8                    	mov ax, cs
   207 0000002A 83C040                  	add ax, (init0_end - init0_start) >> 4
   208 0000002D 8B56E2                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   209 00000030 BE6000                  	mov si, 60h		; => destination
   210 00000033 EB71                    	jmp init0_common
   211                                  %endif
   212                                  
   213                                   %if _IMAGE_EXE
   214 00000035 90<rep Bh>              	align 64, nop
   215                                  j_zero_entrypoint:
   216                                  init0_exe_entry:
   217                                  		; NOTE:	This part is called with ip = 256 + 64, cs = PSP.
   218                                  %if ($ - $$) != 64
   219                                   %error Wrong EXE mode entrypoint
   220                                  %endif
   221                                  %if _IMAGE_EXE_GET_COM_STACK
   222                                  	mov bx, ds		; => PSP
   223                                  	dec bx			; => MCB
   224                                  	mov ds, bx
   225                                  	add bx, word [3]	; add size of memory block
   226                                  	sub bx, -1 + paras(512)	; add one, then subtract enough paragraphs
   227                                  	cli
   228                                  	mov ss, bx
   229                                  	mov sp, 512		; -> new stack
   230                                  	sti
   231                                  %endif
   232 00000040 BB0100                  	mov bx, 1		; EXE mode
   233 00000043 50                      	push ax
   234                                    %if _TEST_PROGRAM
   235 00000044 BE8100                  	mov si, 81h
   236 00000047 31D2                    	xor dx, dx
   237 00000049 31C0                    	xor ax, ax
   238                                  cmdline:
   239                                  .:
   240 0000004B AC                      	lodsb
   241 0000004C 3C09                    	cmp al, 9
   242 0000004E 74FB                    	je .
   243 00000050 3C20                    	cmp al, 32
   244 00000052 74F7                    	je .
   245 00000054 3C0D                    	cmp al, 13
   246 00000056 7441                    	je .end
   247 00000058 3C30                    	cmp al, '0'
   248 0000005A 721E                    	jb .notdigit
   249 0000005C 3C39                    	cmp al, '9'
   250 0000005E 771A                    	ja .notdigit
   251                                  .digit:
   252 00000060 2C30                    	sub al, '0'
   253 00000062 89D1                    	mov cx, dx		; times 1
   254 00000064 01D2                    	add dx, dx
   255 00000066 7222                    	jc .invalid
   256 00000068 01D2                    	add dx, dx		; times 4
   257 0000006A 721E                    	jc .invalid
   258 0000006C 01CA                    	add dx, cx		; times 5
   259 0000006E 721A                    	jc .invalid
   260 00000070 01D2                    	add dx, dx		; times 10
   261 00000072 7216                    	jc .invalid
   262 00000074 01C2                    	add dx, ax		; add in low digit
   263 00000076 7212                    	jc .invalid
   264 00000078 EBD1                    	jmp .
   265                                  
   266                                  .notdigit:
   267 0000007A 3C41                    	cmp al, 'A'
   268 0000007C 7411                    	je .a
   269 0000007E 3C61                    	cmp al, 'a'
   270 00000080 740D                    	je .a
   271 00000082 3C42                    	cmp al, 'B'
   272 00000084 740E                    	je .b
   273 00000086 3C62                    	cmp al, 'b'
   274 00000088 740A                    	je .b
   275                                  .invalid:
   276 0000008A BAFFFF                  	mov dx, -1		; invalid
   277 0000008D EB0A                    	jmp .end
   278                                  
   279                                  .a:
   280 0000008F 80E77F                  	and bh, ~ 80h
   281 00000092 EBB7                    	jmp .
   282                                  
   283                                  .b:
   284 00000094 80CF80                  	or bh, 80h
   285 00000097 EBB2                    	jmp .
   286                                  
   287                                  .end:
   288 00000099 52                      	push dx
   289                                    %endif
   290 0000009A 8CD2                    	mov dx, ss		; => after end of available space
   291 0000009C 8CC8                    	mov ax, cs
   292 0000009E 83C050                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   293 000000A1 8CCE                    	mov si, cs
   294 000000A3 83C610                  	add si, 256 >> 4	; => destination
   295                                   %endif
   296                                  
   297                                  init0_common:
   298                                  		; REM:	This part must be position-independent, as it is
   299                                  		;	 called either with ip = init0_common (kernel mode
   300                                  		;	 or device mode)
   301                                  		;	 or ip = init0_common + 256 (application mode).
   302                                  		; INP:	si => depack destination
   303                                  		;	ax => source of payload + INIT1
   304                                  		;	dx => behind available memory
   305                                  		; OUT:	cs:ip -> init1_start:
   306                                  		;	ax => INIT1
   307                                  		;	dx => payload source
   308                                  		;	si => depack destination
   309                                  		;	bx = mode
   310 000000A6 FC                      	cld
   311                                  %if _TEST_PROGRAM
   312 000000A7 81EAFD11                	sub dx, ( (payload_end - payload) ) >> 4
   313 000000AB 721A                    	jc .error
   314 000000AD B9572F                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   318 000000B0 29CA                    	sub dx, cx
   319 000000B2 7213                    	jc .error
   320 000000B4 39C2                    	cmp dx, ax
   321 000000B6 720F                    	jb .error
   322                                  %else
   323                                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   326                                  				; cx = amount paragraphs in payload + INIT1
   327                                  	sub dx, cx		; => destination for payload + INIT1
   328                                  				;  (highest possible spot in available memory)
   329                                  %endif
   330 000000B8 56                      	push si			; preserve destination
   331 000000B9 E82101                  	call init0_movp		; move up payload + INIT1
   332 000000BC 5E                      	pop si
   333                                  %else
   334                                  	cld
   335                                  	mov ax, cs
   336                                  	add ax, (init0_end - init0_start) >> 4
   337                                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   340                                  	mov dx, word [ bp + ldLoadTop ]
   341                                  	sub dx, cx
   342                                  	call init0_movp
   343                                  %endif
   344                                  
   345 000000BD 89D0                    	mov ax, dx		; => payload
   346                                  %if _TEST_PROGRAM
   347 000000BF 053412                  	add ax, ( 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4		; => INIT2
   351                                  %else
   352                                  	add ax, ( 		+ (payload_end - payload) 		) >> 4		; => INIT1
   355                                  %endif
   356 000000C2 31C9                    	xor cx, cx
   357 000000C4 50                      	push ax
   358 000000C5 51                      	push cx
   359 000000C6 CB                      	retf			; jump to relocated INIT1:init1_start
   360                                  				;  or INIT2:init2_start
   361                                  
   362                                  
   363                                  %if _TEST_PROGRAM
   364                                  .error:
   365 000000C7 89DF                    	mov di, bx
   366                                  
   367 000000C9 0E                      	push cs
   368 000000CA 1F                      	pop ds
   369 000000CB BA[5F03]                	mov dx, init0_msg.error_stderr + 256
   370 000000CE B92500                  	mov cx, init0_msg.error_stderr.length
   371 000000D1 BB0200                  	mov bx, 2
   372 000000D4 B440                    	mov ah, 40h
   373 000000D6 CD21                    	int 21h
   374                                  
   375 000000D8 F7C70080                	test di, 8000h
   376 000000DC 750D                    	jnz @F
   377 000000DE BA[8403]                	mov dx, init0_msg.error_stdout + 256
   378 000000E1 B90700                  	mov cx, init0_msg.error_stdout.length
   379 000000E4 BB0100                  	mov bx, 1
   380 000000E7 B440                    	mov ah, 40h
   381 000000E9 CD21                    	int 21h
   382                                  @@:
   383 000000EB B8FF4C                  	mov ax, 4CFFh
   384 000000EE CD21                    	int 21h
   385                                  %endif
   386                                  
   387                                  
   388                                  %if _DEVICE
   389                                  device_entrypoint:
   390                                  %if _TEST_PROGRAM
   391                                  @@:
   392 000000F0 CC                      	int3
   393 000000F1 FB                      	sti
   394 000000F2 F4                      	hlt
   395 000000F3 EBFB                    	jmp @B
   396                                  %endif
   397 000000F5 26807F0200              	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   398 000000FA 7407                    	je @F
   399                                  
   400 000000FC 26C747030381            	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   401 00000102 CB                      	retf
   402                                  
   403                                  @@:
   404 00000103 2E830E[0000]FF          	or word [cs:device_header.next], -1
   405 00000109 0E                      	push cs
   406 0000010A 2EFF36[0600]            	push word [cs:device_header.strategy]
   407                                  					; -> far return to payload's strategy
   408 0000010F 55                      	push bp
   409 00000110 1E                      	push ds
   410 00000111 56                      	push si
   411 00000112 57                      	push di
   412 00000113 52                      	push dx
   413 00000114 51                      	push cx
   414 00000115 50                      	push ax
   415 00000116 53                      	push bx
   416 00000117 06                      	push es
   417                                  
   418 00000118 268B4710                	mov ax, word [es:bx + 14 + 2]
   419 0000011C 31D2                    	xor dx, dx
   420 0000011E B90400                  	mov cx, 4
   421                                  @@:
   422 00000121 D1E0                    	shl ax, 1
   423 00000123 D1D2                    	rcl dx, 1
   424 00000125 E2FA                    	loop @B
   425 00000127 2603470E                	add ax, word [es:bx + 14]
   426 0000012B 83D200                  	adc dx, 0		; dx:ax = linear address behind end
   427                                  
   428 0000012E B104                    	mov cl, 4
   429                                  @@:
   430 00000130 D1EA                    	shr dx, 1
   431 00000132 D1D8                    	rcr ax, 1
   432 00000134 E2FA                    	loop @B			; ax => behind end
   433                                  
   434 00000136 8CCF                    	mov di, cs
   435                                  image_size: equ  ( (init0_end - init0_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   439 00000138 81C77412                	add di, image_size >> 4		; di => end of image
   440                                  
   441 0000013C 39F8                    	cmp ax, di			; enough memory to hold all of us ?
   442 0000013E 7203E98A00              	jae .have_some_memory		; yes -->
   443                                  
   444 00000143 0E                      	push cs
   445 00000144 1F                      	pop ds
   446 00000145 BA[8401]                	mov dx, .msg_no_memory
   447 00000148 B409                    	mov ah, 09h
   448 0000014A CD21                    	int 21h
   449                                  
   450 0000014C B80030                  	mov ax, 3000h
   451 0000014F CD21                    	int 21h
   452 00000151 3C05                    	cmp al, 5
   453 00000153 7307                    	jae @F
   454 00000155 BA[A301]                	mov dx, .msg_dos_below_5
   455 00000158 B409                    	mov ah, 09h
   456 0000015A CD21                    	int 21h
   457                                  @@:
   458                                  
   459 0000015C BA[CA01]                	mov dx, .msg_linebreak
   460 0000015F B409                    	mov ah, 09h
   461 00000161 CD21                    	int 21h
   462                                  
   463                                  		; tear down the stack frame and modify the request header
   464 00000163 07                      	pop es
   465 00000164 5B                      	pop bx
   466 00000165 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   467 0000016B 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   468 00000170 268C4F10                	mov word [es:bx + 14 + 2], cs
   469 00000174 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   470 00000179 58                      	pop ax
   471 0000017A 59                      	pop cx
   472 0000017B 5A                      	pop dx
   473 0000017C 5F                      	pop di
   474 0000017D 5E                      	pop si
   475 0000017E 1F                      	pop ds
   476 0000017F 5D                      	pop bp
   477 00000180 83C404                  	add sp, 4		; discard far return to payload's strategy
   478 00000183 CB                      	retf			; return to DOS
   479                                  
   480 00000184 4C6F6164206572726F-     .msg_no_memory:		ascic "Load error: Not enough memory."
   480 0000018D 723A204E6F7420656E-
   480 00000196 6F756768206D656D6F-
   480 0000019F 72792E24           
   481 000001A3 204E6F74653A20444F-     .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   481 000001AC 53206D757374206265-
   481 000001B5 206174206C65617374-
   481 000001BE 2076657273696F6E20-
   481 000001C7 352E24             
   482 000001CA 0D0A24                  .msg_linebreak:		ascic 13,10
   483                                  
   484                                  
   485                                  .have_some_memory:
   486 000001CD 89C2                    	mov dx, ax		; => after end of memory
   487 000001CF BB0200                  	mov bx, 2		; device mode
   488 000001D2 50                      	push ax
   489 000001D3 8CC8                    	mov ax, cs
   490 000001D5 83C040                  	add ax, (init0_end - init0_start) >> 4
   491 000001D8 8CCE                    	mov si, cs		; => destination
   492 000001DA E9C9FE                  	jmp init0_common
   493                                  %endif
   494                                  
   495                                  
   496                                  		; Move paragraphs
   497                                  		;
   498                                  		; INP:	ax => source
   499                                  		;	dx => destination
   500                                  		;	cx = number of paragraphs
   501                                  		; CHG:	cx, ds, si, es, di
   502                                  		; OUT:	ax and dx unchanged
   503                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   504                                  		;	Do not provide a wrapped/HMA source or destination!
   505                                  init0_movp:
   506 000001DD 39D0                    	cmp ax, dx		; source above destination ?
   507 000001DF 770A                    	ja .up			; yes, move up (forwards) -->
   508 000001E1 747B                    	je .return		; same, no need to move -->
   509 000001E3 50                      	push ax
   510 000001E4 01C8                    	add ax, cx		; (expected not to carry)
   511 000001E6 39D0                    	cmp ax, dx		; end of source is above destination ?
   512 000001E8 58                      	pop ax
   513 000001E9 7730                    	ja .down		; yes, move from top down -->
   514                                  	; Here, the end of source is below-or-equal the destination,
   515                                  	;  so they do not overlap. In this case we prefer moving up.
   516                                  
   517                                  .up:
   518 000001EB 50                      	push ax
   519 000001EC 52                      	push dx
   520                                  .uploop:
   521 000001ED 8ED8                    	mov ds, ax
   522 000001EF 8EC2                    	mov es, dx
   523 000001F1 31FF                    	xor di, di
   524 000001F3 31F6                    	xor si, si		; -> start of segment
   525 000001F5 81E90010                	sub cx, 1000h		; 64 KiB left ?
   526 000001F9 7610                    	jbe .uplast		; no -->
   527 000001FB 51                      	push cx
   528 000001FC B90080                  	mov cx, 10000h /2
   529 000001FF F3A5                    	rep movsw		; move 64 KiB
   530 00000201 59                      	pop cx
   531 00000202 050010                  	add ax, 1000h
   532 00000205 81C20010                	add dx, 1000h		; -> next segment
   533 00000209 EBE2                    	jmp short .uploop	; proceed for more -->
   534                                  .uplast:
   535 0000020B 81C10010                	add cx, 1000h		; restore counter
   536 0000020F D1E1                    	shl cx, 1
   537 00000211 D1E1                    	shl cx, 1
   538 00000213 D1E1                    	shl cx, 1		; *8, paragraphs to words
   539 00000215 F3A5                    	rep movsw		; move last part
   540 00000217 5A                      	pop dx
   541 00000218 58                      	pop ax
   542 00000219 EB43                    	jmp short .return
   543                                  
   544                                  .down:
   545 0000021B FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   546                                  .dnloop:
   547 0000021C 81E90010                	sub cx, 1000h		; 64 KiB left ?
   548 00000220 761A                    	jbe .dnlast		; no -->
   549 00000222 50                      	push ax
   550 00000223 52                      	push dx
   551 00000224 01C8                    	add ax, cx
   552 00000226 01CA                    	add dx, cx
   553 00000228 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   554 0000022A 8EC2                    	mov es, dx
   555 0000022C 5A                      	pop dx
   556 0000022D 58                      	pop ax
   557 0000022E BFFEFF                  	mov di, -2
   558 00000231 89FE                    	mov si, di		; moved from last word down
   559 00000233 51                      	push cx
   560 00000234 B90080                  	mov cx, 10000h /2
   561 00000237 F3A5                    	rep movsw		; move 64 KiB
   562 00000239 59                      	pop cx
   563 0000023A EBE0                    	jmp short .dnloop	; proceed for more -->
   564                                  .dnlast:
   565 0000023C 81C10010                	add cx, 1000h		; restore counter
   566 00000240 D1E1                    	shl cx, 1
   567 00000242 D1E1                    	shl cx, 1
   568 00000244 D1E1                    	shl cx, 1		; *8, paragraphs to words
   569 00000246 89CF                    	mov di, cx
   570 00000248 4F                      	dec di
   571 00000249 D1E7                    	shl di, 1		; words to offset, -> last word
   572 0000024B 89FE                    	mov si, di
   573 0000024D 8ED8                    	mov ds, ax
   574 0000024F 8EC2                    	mov es, dx		; first segment correct
   575                                  
   576                                  
   577                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   578                                  %if 0
   579                                  
   580                                  Jack R. Ellis pointed out this erratum:
   581                                  
   582                                  Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
   583                                  
   584                                  109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
   585                                  
   586                                  Description
   587                                  
   588                                  In certain situations a REP MOVS instruction may lead to
   589                                  incorrect results. An incorrect address size, data size
   590                                  or source operand segment may be used or a succeeding
   591                                  instruction may be skipped. This may occur under the
   592                                  following conditions:
   593                                  
   594                                  * EFLAGS.DF=1 (the string is being moved in the reverse direction).
   595                                  
   596                                  * The number of items being moved (RCX) is between 1 and 20.
   597                                  
   598                                  * The REP MOVS instruction is preceded by some microcoded instruction
   599                                    that has not completely retired by the time the REP MOVS begins
   600                                    execution. The set of such instructions includes BOUND, CLI, LDS,
   601                                    LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
   602                                  
   603                                  Potential Effect on System
   604                                  
   605                                  Incorrect results may be produced or the system may hang.
   606                                  
   607                                  Suggested Workaround
   608                                  
   609                                  Contact your AMD representative for information on a BIOS update.
   610                                  
   611                                  %endif
   612                                  
   613                                  %if _AMD_ERRATUM_109_WORKAROUND
   614 00000251 E308                    	jcxz @FF
   615 00000253 83F914                  	cmp cx, 20
   616 00000256 7703                    	ja @FF
   617                                  @@:
   618 00000258 A5                      	movsw
   619 00000259 E2FD                    	loop @B
   620                                  @@:
   621                                  %endif
   622 0000025B F3A5                    	rep movsw		; move first part
   623 0000025D FC                      	cld
   624                                  .return:
   625 0000025E C3                      	retn
   626                                  
   627                                  
   628                                  	section PAYLOAD align=16 follows=INIT0
   629                                  payload:
   630 00000000 <bin 11FC9h>            	incbin _PAYLOAD_FILE
   631                                  .end:
   632 00011FC9 26<rep 7h>              	align 16, db 38
   633                                  payload_end:
   634                                  
   635                                  
   636                                  	section INIT1 align=16 follows=PAYLOAD vstart=0
   637                                  init1_start:
   638                                  		; INP:	ax = cs = INIT1
   639                                  		;	dx = cs - (payload_end - payload) >> 4 => source data
   640                                  		;	if kernel mode:
   641                                  		;	 ss:bp -> LOADDATA and LOADSTACKVARS
   642                                  		;	 ss:sp -> valid stack above [bp + ldLoadTop]
   643                                  		;	 60h => destination
   644                                  		;	any mode:
   645                                  		;	 word [ss:sp] = value for ax
   646                                  		;	 bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode
   647                                  		;	 si => destination (60h for kernel mode,
   648                                  		;		after PSP for EXE mode,
   649                                  		;		at device header for device mode)
   650                                  		;		(not set if only kernel mode supported)
   651                                  		;	 if EXE mode:
   652                                  		;	  ss:sp -> valid stack above INIT1
   653                                  		;	  bp = unset
   654                                  		;	 if device mode:
   655                                  		;	  ss:sp -> device entrypoint stack
   656                                  		;	  holds: es, bx, ax, cx, dx, di, si, ds, bp,
   657                                  		;		  far address of payload strategy entrypoint,
   658                                  		;		  far return address to DOS
   659                                  		;	  bp = unset
   660                                  		; STT:	UP
   661                                  		; CHG:	ax, bx, cx, dx, es, ds, si, di
   662                                  %if _IMAGE_EXE || _DEVICE
   663                                  	lframe
   664 00000000 5589E5                  	lenter
   665                                  	lvar word,	exemode		; must be bp - 2!
   666 00000003 53                      	 push bx
   667                                   %if ?exemode != -2
   668                                    %error exemode variable must be directly below bp
   669                                   %endif
   670 00000004 56                      	push si
   671                                  %else
   672                                  	xor bx, bx		; always tell them it is kernel mode
   673                                  %endif
   674                                  
   675                                  %if _IMAGE_EXE
   676 00000005 8EC6                    	mov es, si		; es => destination
   677                                  %else
   678                                  	mov ax, 60h
   679                                  	mov es, ax		; es => destination
   680                                  %endif
   681 00000007 31FF                    	xor di, di		; -> destination
   682                                  
   683 00000009 8EDA                    	mov ds, dx
   684 0000000B 31F6                    	xor si, si		; -> source
   685                                  
   686 0000000D B9C91F                  	mov cx, (payload.end - payload) & 0FFFFh
   687                                  %if (payload.end - payload) >> 16
   688 00000010 BA0100                  	mov dx, (payload.end - payload) >> 16	; = length of source
   689                                  %else
   690                                  	xor dx, dx
   691                                  %endif
   692                                  %if _PAYLOAD_KERNEL_MAX_PARAS
   693                                  	mov ax, _PAYLOAD_KERNEL_MAX_PARAS
   694                                  	test bx, bx
   695                                  	jz @F
   696                                  %endif
   697 00000013 B8FFFF                  	mov ax, -1
   698                                  @@:
   699                                  		; INP:	ds:si -> source
   700                                  		;	dx:cx = length of source
   701                                  		;	es:di -> destination (below source)
   702                                  		;	bx = EXE mode flag
   703                                  		;	 (1 if EXE mode, 0 if kernel mode)
   704                                  		;	 (always 0 if this is a build without EXE mode)
   705                                  		;	if _PAYLOAD_KERNEL_MAX_PARAS:
   706                                  		;	 ax = maximum amount in paragraphs of destination needed
   707                                  		;	 (-1 if full source should be decompressed)
   708                                  		;	else:
   709                                  		;	 ax = -1
   710                                  		; Note:	The destination reaches up to below the source.
   711 00000016 E80201                  	call depack
   712                                  %ifn _TEST_PROGRAM
   713                                  	jc strict short error
   714                                  %endif
   715                                  %if _IMAGE_EXE
   716 00000019 5E                      	pop si			; si
   717                                   %if _TEST_PROGRAM
   718 0000001A 58                      	pop ax			; (discard ?exemode, leave bx as returned)
   719                                   %else
   720                                  	pop bx			; ?exemode
   721                                   %endif
   722 0000001B 5D                      	pop bp			; bp
   723 0000001C 58                      	pop ax			; ax
   724                                  	lleave ctx
   725                                  %endif
   726                                  %if _TEST_PROGRAM
   727 0000001D CB                      	retf
   728 0000001E 90                      	nop
   729                                  %endif
   730                                  
   731                                  %if _DEVICE
   732 0000001F F6C302                  	test bl, 2
   733 00000022 7411                    	jz .jmp_exe_or_kernel_mode
   734                                  
   735                                  .jmp_device_mode:
   736 00000024 8EDE                    	mov ds, si
   737 00000026 830E[0000]FF            	or word [device_header.next], -1
   738 0000002B 07                      	pop es
   739 0000002C 5B                      	pop bx
   740 0000002D 58                      	pop ax
   741 0000002E 59                      	pop cx
   742 0000002F 5A                      	pop dx
   743 00000030 5F                      	pop di
   744 00000031 5E                      	pop si
   745 00000032 1F                      	pop ds
   746 00000033 5D                      	pop bp
   747 00000034 CB                      	retf			; transfer to payload strategy entrypoint
   748                                  				; still on stack: far return address to DOS
   749                                  
   750                                  .jmp_exe_or_kernel_mode:
   751                                  %endif
   752                                  
   753                                  %if _IMAGE_EXE
   754 00000035 F6C301                  	test bl, 1
   755 00000038 7410                    	jz .jmp_kernel_mode
   756                                  
   757                                  .jmp_exe_mode:
   758                                  %if ! _IMAGE_EXE_AUTO_STACK
   759                                  	mov cx, cs
   760                                  	lea dx, [si + _IMAGE_EXE_SS]
   761                                  	push dx			; stack = relocated ss value
   762                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
   763                                  	cmp cx, dx		; INIT1 code is above intended stack ?
   764                                  	jae @F			; yes -->
   765                                  
   766                                  	lframe
   767                                  	lenter
   768                                  	lvar	word, exemode
   769                                  	 push bx
   770                                   %if ?exemode != -2
   771                                    %error exemode variable must be directly below bp
   772                                   %endif
   773                                  	mov bx, -1		; unimplemented, return error
   774                                  	jmp error
   775                                  	lleave ctx
   776                                  @@:
   777                                  	cli
   778                                  	pop ss			; = relocated ss value
   779                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
   780                                  	sti
   781                                  %endif
   782                                  
   783 0000003A 31C9                    	xor cx, cx
   784 0000003C 51                      	push cx			; put zero on top of stack
   785                                  
   786                                  %if _IMAGE_EXE_IP < 256
   787                                  	mov cl, _IMAGE_EXE_IP
   788                                  %elif (_IMAGE_EXE_IP & 255) == 0
   789                                  	mov ch, _IMAGE_EXE_IP >> 8
   790                                  %else
   791 0000003D B94001                  	mov cx, _IMAGE_EXE_IP
   792                                  %endif
   793                                  
   794                                  %if _IMAGE_EXE_CS == -16
   795 00000040 83C6F0                  	add si, -16
   796 00000043 8EDE                    	mov ds, si
   797 00000045 8EC6                    	mov es, si
   798                                  %else
   799                                  	lea dx, [si - 10h]	; => PSP
   800                                  	mov ds, dx
   801                                  	mov es, dx		; ds = es => PSP
   802                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
   803                                  %endif
   804 00000047 56                      	push si
   805 00000048 51                      	push cx
   806 00000049 CB                      	retf			; jump to EXE mode of image
   807                                  
   808                                  %endif
   809                                  .jmp_kernel_mode:
   810 0000004A EA20006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
   811                                  
   812                                  
   813                                  error:
   814 0000004F 0E                      	push cs
   815 00000050 1F                      	pop ds
   816                                  %if _DEBUG0
   817                                  	mov si, msg.error_begin
   818                                  	call disp_error
   819                                  	xchg ax, bx			; ax = error code
   820                                  	call disp_ax_hex
   821                                  	mov si, msg.error_end
   822                                  %else
   823 00000051 BE[F600]                	mov si, msg.error
   824                                  %endif
   825 00000054 E87D00                  	call disp_error
   826                                  
   827                                  %if _DEVICE
   828 00000057 F646FE02                	test byte [bp - 2], 2
   829 0000005B 7435                    	jz .exit_app_or_kernel
   830                                  
   831 0000005D 5E                      	pop si				; => device segment
   832 0000005E 5B                      	pop bx				; mode word
   833 0000005F 5D                      	pop bp
   834 00000060 58                      	pop ax
   835 00000061 8EC6                    	mov es, si
   836 00000063 31FF                    	xor di, di			; -> device header
   837 00000065 0E                      	 push cs
   838 00000066 1F                      	 pop ds
   839 00000067 BE[B000]                	mov si, device_header_copy	; -> to reset header
   840 0000006A B91100                  	mov cx, words(device_header_copy.length)
   841 0000006D F3A5                    	rep movsw		; overwrite device header with default
   842                                  				;  (reset to a valid state after unsuccessful
   843                                  				;  decompression, which may have partially
   844                                  				;  written the header already)
   845 0000006F 06                      	 push es
   846 00000070 1F                      	 pop ds				; -> device segment
   847 00000071 07                      	pop es
   848 00000072 5B                      	pop bx
   849 00000073 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   850 00000079 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   851 0000007E 268C5F10                	mov word [es:bx + 14 + 2], ds
   852 00000082 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   853 00000087 58                      	pop ax
   854 00000088 59                      	pop cx
   855 00000089 5A                      	pop dx
   856 0000008A 5F                      	pop di
   857 0000008B 5E                      	pop si
   858 0000008C 1F                      	pop ds
   859 0000008D 5D                      	pop bp
   860 0000008E 83C404                  	add sp, 4		; discard far return to payload's strategy
   861 00000091 CB                      	retf			; return to DOS
   862                                  
   863                                  
   864                                  .exit_app_or_kernel:
   865                                  %endif
   866                                  
   867                                  %if _IMAGE_EXE
   868                                  %if _BOOTLDR
   869 00000092 F646FE01                	test byte [bp - 2], 1
   870 00000096 7405                    	jz .exit_kernel_mode
   871                                  %endif
   872                                  
   873 00000098 B87F4C                  	mov ax, 4C7Fh
   874 0000009B CD21                    	int 21h
   875                                  
   876                                  .exit_kernel_mode:
   877                                  %endif
   878                                  %if _BOOTLDR
   879 0000009D 31C0                    	xor ax, ax
   880 0000009F CD16                    	int 16h
   881 000000A1 CD19                    	int 19h
   882                                  %endif
   883                                  
   884                                  
   885                                  %if _DEVICE
   886 000000A3 90<rep Dh>              	align 16
   887                                  device_header_copy:
   888                                  .:
   889                                  .next:
   890 000000B0 FFFFFFFF                	dd -1				; already initialised
   891                                  .attributes:
   892 000000B4 0088                    	dw _DEVICE_ATTRIBUTE
   893                                  .strategy:
   894 000000B6 1200                    	dw .strategy_entry - .		; -> strategy entry
   895                                  .interrupt:
   896 000000B8 1600                    	dw .interrupt_entry - .		; -> interrupt entry
   897                                  .name:
   898 000000BA 4C44454255472424        	fill 8, 32, db _DEVICE_NAME
   899                                  .strategy_entry:
   900 000000C2 EB0690<rep 2h>          	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
   901                                  .interrupt_entry:
   902 000000C6 CB90<rep 3h>            	fill 4, 90h, retf
   903                                  
   904                                  .set_error:
   905 000000CA 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   906 000000D0 CB                      	retf
   907                                  .length: equ $ - .
   908                                  %endif
   909                                  
   910                                  
   911                                  disp_error.loop:
   912 000000D1 E80600                  	call disp_al
   913                                  disp_error:
   914 000000D4 AC                      	lodsb
   915 000000D5 84C0                    	test al, al
   916 000000D7 75F8                    	jnz .loop
   917 000000D9 C3                      	retn
   918                                  
   919                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
   920                                  disp_ax_hex:			; ax
   921                                  		xchg al,ah
   922                                  		call disp_al_hex		; display former ah
   923                                  		xchg al,ah			;  and fall trough for al
   924                                  disp_al_hex:			; al
   925                                  		push cx
   926                                  		mov cl,4
   927                                  		ror al,cl
   928                                  		call disp_al_lownibble_hex	; display former high-nibble
   929                                  		rol al,cl
   930                                  		pop cx
   931                                  						;  and fall trough for low-nibble
   932                                  disp_al_lownibble_hex:
   933                                  		push ax			 ; save ax for call return
   934                                  		and al,00001111b		; high nibble must be zero
   935                                  		add al,'0'			; if number is 0-9, now it's the correct character
   936                                  		cmp al,'9'
   937                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
   938                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
   939                                   .decimalnum:
   940                                  		call disp_al
   941                                  		pop ax
   942                                  		retn
   943                                  %endif
   944                                  
   945                                  disp_al:
   946                                  %if _TEST_PROGRAM
   947 000000DA C3                      	retn
   948                                  %else
   949                                  	push ax
   950                                  %endif
   951                                  %if _BOOTLDR
   952 000000DB 53                      	push bx
   953 000000DC 55                      	push bp
   954 000000DD B40E                    	mov ah, 0Eh
   955 000000DF BB0700                  	mov bx, 7
   956                                  %endif
   957                                  %if _IMAGE_EXE || _DEVICE
   958 000000E2 52                      	push dx
   959                                  
   960                                  %if _BOOTLDR
   961 000000E3 F646FE03                	test byte [bp - 2], 1 | 2
   962 000000E7 7406                    	jz .display_kernel_mode
   963                                  %endif
   964                                  
   965 000000E9 92                      	xchg dx, ax				; dl = input al
   966 000000EA B402                    	mov ah, 02h
   967 000000EC CD21                    	int 21h
   968                                  %if _BOOTLDR
   969 000000EE A9                      	db __TEST_IMM16				; (skip int)
   970                                  %endif
   971                                  
   972                                  .display_kernel_mode:
   973                                  %endif
   974                                  %if _BOOTLDR
   975 000000EF CD10                    	int 10h
   976                                  %endif
   977                                  %if _IMAGE_EXE
   978 000000F1 5A                      	pop dx
   979                                  %endif
   980                                  %if _BOOTLDR
   981 000000F2 5D                      	pop bp
   982 000000F3 5B                      	pop bx
   983                                  %endif
   984 000000F4 58                      	pop ax
   985                                  disp_error.ret:
   986 000000F5 C3                      	retn
   987                                  
   988                                  
   989                                  msg:
   990                                  %if _DEBUG0
   991                                  .error_begin:	db "Load error: Decompression failure, code ",0
   992                                  .error_end:	db "h.",13,10,0
   993                                  %else
   994 000000F6 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
   994 000000FF 723A204465636F6D70-
   994 00000108 72657373696F6E2066-
   994 00000111 61696C7572652E0D0A-
   994 0000011A 00                 
   995                                  %endif
   996                                  
   997                                  
   998                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
   999                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
  1000                                  %assign CHECK_POINTERS_VARIABLE_DST 1
  1001                                  
  1002                                  		; Specific depacker's file is included within label msg.
  1003                                  		; In the file, lframe is used and lleave ctx is not used.
  1004                                  
  1005                                  %if _BRIEFLZ
  1006                                  	%include "brieflz.asm"
  1007                                  %endif
  1008                                  
  1009                                  
  1010                                  %if _LZ4
  1011                                  	%include "lz4.asm"
  1012                                  %endif
  1013                                  
  1014                                  
  1015                                  %if _SNAPPY
  1016                                  	%include "snappy.asm"
  1017                                  %endif
  1018                                  
  1019                                  
  1020                                  %if _EXODECR
  1021                                  	%include "exodecr.asm"
  1022                                  %endif
  1023                                  
  1024                                  
  1025                                  %if _X
  1026                                  	%include "x.asm"
  1027                                  %endif
  1028                                  
  1029                                  
  1030                                  %if _HEATSHRINK
  1031                                  	%include "heatshr.asm"
  1032                                  %endif
  1033                                  
  1034                                  
  1035                                  %if _LZD
  1036                                  	%include "lzd.asm"
  1037                                  %endif
  1038                                  
  1039                                  
  1040                                  %if _LZO
  1041                                  	%include "lzo.asm"
  1042                                  %endif
  1043                                  
  1044                                  
  1045                                  %if _LZSA2
  1046                                  	%include "lzsa2.asm"
  1047                                  %endif
  1048                                  
  1049                                  
  1050                                  %if _APL
  1051                                  	%include "apl.asm"
     1                              <1> 
     2                              <1> ; 8086 Assembly lDOS iniload payload aPLib depacker
     3                              <1> ;  by C. Masloch, 2021
     4                              <1> ;
     5                              <1> ;  based on:
     6                              <1> ;  aplib_8088_small.S - size-optimized aPLib decompressor for 8088 - 145 bytes
     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 0000011B 5589E5              <1> 	lenter early
    61                              <1>  %if _IMAGE_EXE
    62                              <1> 	lvar word,	exemode	; must be bp - 2!
    63 0000011E 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                              <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> %if _COUNTER
    77                              <1> 	lvar word,	counter
    78                              <1> 	 push bx		; initialise counter (high byte) to zero
    79                              <1> %endif
    80                              <1> 	lvar word,	gamma_high_word
    81                              <1> 	lvar word,	distance_high_word
    82 0000011F 8D66FA              <1> 	lenter
    83                              <1> 
    84 00000122 E8C101              <1> 	call normalise_both_pointers
    85                              <1> 
    86                              <1> 	lvar dword,	src
    87 00000125 1E                  <1> 	 push ds
    88 00000126 56                  <1> 	 push si
    89                              <1> 	lvar dword,	original_dst
    90 00000127 06                  <1> 	 push es
    91 00000128 57                  <1> 	 push di
    92                              <1> 	lvar dword,	dst
    93 00000129 06                  <1> 	 push es
    94 0000012A 57                  <1> 	 push di
    95                              <1> 	lvar dword,	length_of_source
    96 0000012B 52                  <1> 	 push dx
    97 0000012C 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 0000012D 1E                  <1> 	 push ds
   118 0000012E 56                  <1> 	 push si
   119 0000012F E81402              <1> 	call pointer_to_linear
   120                              <1> 
   121 00000132 89D3                <1> 	mov bx, dx
   122 00000134 91                  <1> 	xchg cx, ax		; bx:cx = source linear
   123                              <1> 
   124 00000135 06                  <1> 	 push es
   125 00000136 57                  <1> 	 push di
   126 00000137 E80C02              <1> 	call pointer_to_linear
   127                              <1> 
   128                              <1> %if _ALLOW_OVERLAPPING
   129 0000013A 034EEA              <1> 	add cx, word [bp + ?length_of_source]
   130 0000013D 135EEC              <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 00000140 29C1                <1> 	sub cx, ax
   145 00000142 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   146                              <1> 
   147                              <1> 	lvar dword,	length_of_destination
   148 00000144 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   149 00000145 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   150                              <1> 
   151                              <1> %if _ALLOW_OVERLAPPING
   152 00000146 E88901              <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 00000149 7303E95C01          <1> 	jc .error
   160                              <1> %endif
   161                              <1> 
   162                              <1> 
   163                              <1>         ; === register map ===
   164                              <1>         ; al: bit queue
   165                              <1>         ; ah: unused, but value is trashed
   166                              <1>         ; bx: follows_literal
   167                              <1>         ; cx: scratch register for reading gamma2 codes and storing copy length
   168                              <1>         ; dx: match offset (and rep-offset)
   169                              <1>         ; si: input (compressed data) pointer
   170                              <1>         ; di: output (decompressed data) pointer
   171                              <1> 
   172 0000014E B080                <1>         mov     al,080H         ; clear bit queue(al) and set high bit to move into carry
   173 00000150 31D2                <1>         xor     dx,dx           ; invalidate rep offset
   174 00000152 8956FA              <1> 	mov word [bp + ?distance_high_word], dx
   175                              <1> 
   176                              <1> .literal:
   177 00000155 836EE601            <1> 	sub word [bp + ?length_of_destination], 1
   178 00000159 835EE800            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   179 0000015D 7303E94801          <1> 	jb .error
   180 00000162 836EEA01            <1> 	sub word [bp + ?length_of_source], 1
   181 00000166 835EEC00            <1> 	sbb word [bp + ?length_of_source + 2], 0
   182 0000016A 7303E93B01          <1> 	jb .error
   183 0000016F A4                  <1>         movsb                   ; read and write literal byte
   184 00000170 E87301              <1> 	call normalise_both_pointers
   185                              <1> .next_command_after_literal:
   186 00000173 BB0300              <1>         mov     bx,03H          ; set follows_literal(bx) to 3
   187                              <1> 
   188                              <1> .next_command:
   189                              <1> %if _COUNTER
   190                              <1> 	inc byte [bp + ?counter]
   191                              <1> 	test byte [bp + ?counter], _COUNTER - 1
   192                              <1> 	jnz @F
   193                              <1> 	push ax
   194                              <1> 	mov al, '.'
   195                              <1> 	call disp_al
   196                              <1> 	pop ax
   197                              <1> @@:
   198                              <1> %endif
   199 00000176 E84D01              <1>         call    .get_bit        ; read 'literal or match' bit
   200 00000179 73DA                <1>         jnc     .literal        ; if 0: literal
   201                              <1>                                 
   202                              <1>                                 ; 1x: match
   203                              <1> 
   204 0000017B E84801              <1>         call    .get_bit        ; read '8+n bits or other type' bit
   205 0000017E 7303E9CA00          <1>         jc      .other          ; 11x: other type of match
   206                              <1> 
   207                              <1>                                 ; 10: 8+n bits match
   208 00000183 E8BB00              <1>         call    .get_gamma2     ; read gamma2-coded high offset bits
   209 00000186 29D9                <1>         sub     cx,bx           ; high offset bits == 2 when follows_literal == 3 ?
   210                              <1>                                 ; (a gamma2 value is always >= 2, so substracting follows_literal when it
   211                              <1>                                 ; is == 2 will never result in a negative value)
   212 00000188 835EFC00            <1> 	sbb word [bp + ?gamma_high_word], 0
   213 0000018C 7305                <1>         jae     .not_repmatch   ; if not, not a rep-match
   214                              <1> 
   215                              <1> 
   216 0000018E E8B000              <1>         call    .get_gamma2     ; read match length
   217 00000191 EB3E                <1>         jmp     short .got_len  ; go copy
   218                              <1> 
   219                              <1> .not_repmatch:
   220 00000193 8B56FC              <1> 	mov dx, word [bp + ?gamma_high_word]
   221 00000196 84F6                <1> 	test dh, dh		; beyond 32-bit offset ?
   222 00000198 7403E90D01          <1> 	jnz .error		; if so, error -->
   223 0000019D 8856FB              <1> 	mov byte [bp + ?distance_high_word + 1], dl
   224 000001A0 886EFA              <1> 	mov byte [bp + ?distance_high_word], ch
   225                              <1> 				; get high word of distance
   226 000001A3 88CE                <1>         mov     dh,cl           ; transfer high offset bits to dh
   227 000001A5 92                  <1> 	xchg ax, dx
   228 000001A6 E80601              <1> 	call .lodsb
   229 000001A9 92                  <1> 	xchg ax, dx		; read low offset byte in dl
   230                              <1> 
   231 000001AA E89400              <1>         call    .get_gamma2     ; read match length
   232 000001AD 837EFA00            <1> 	cmp word [bp + ?distance_high_word], 0
   233                              <1> 				; high word nonzero ?
   234 000001B1 7510                <1> 	jne .increase_len_by2	; then always offset >= 32k
   235 000001B3 80FE7D              <1>         cmp     dh,07DH         ; offset >= 32000 ?
   236 000001B6 730B                <1>         jae     .increase_len_by2 ; if so, increase match len by 2
   237 000001B8 80FE05              <1>         cmp     dh,05H          ; offset >= 1280 ?
   238 000001BB 730D                <1>         jae     .increase_len_by1 ; if so, increase match len by 1
   239 000001BD 81FA8000            <1>         cmp     dx,0080H        ; offset < 128 ?
   240 000001C1 730E                <1>         jae     .got_len        ; if so, increase match len by 2, otherwise it would be a 7+1 copy
   241                              <1> .increase_len_by2:
   242 000001C3 83C101              <1> 	add cx, 1		; increase length
   243 000001C6 8356FC00            <1> 	adc word [bp + ?gamma_high_word], 0
   244                              <1> .increase_len_by1:
   245 000001CA 83C101              <1> 	add cx, 1		; increase length
   246 000001CD 8356FC00            <1> 	adc word [bp + ?gamma_high_word], 0
   247                              <1> 
   248                              <1>         ; copy ?gamma_high_word:cx bytes
   249                              <1> 	;  from match offset ?distance_high_word:dx
   250                              <1> 
   251                              <1> .got_len:
   252 000001D1 1E                  <1>         push    ds              ; save ds:si (current pointer to compressed data)
   253 000001D2 56                  <1>         push    si
   254                              <1> 
   255 000001D3 53                  <1> 	push bx
   256 000001D4 51                  <1> 	push cx
   257 000001D5 8B5EFA              <1> 	mov bx, word [bp + ?distance_high_word]
   258 000001D8 89D1                <1> 	mov cx, dx
   259                              <1> 
   260 000001DA E82600              <1> 	call .get_match_pointer
   261                              <1> 
   262 000001DD 59                  <1> 	pop cx
   263 000001DE 5B                  <1> 	pop bx
   264                              <1> 
   265                              <1> .match_loop:
   266 000001DF 83E9F0              <1> 	sub cx, 0FFF0h		; less than full transfer left ?
   267 000001E2 835EFC00            <1> 	sbb word [bp + ?gamma_high_word], 0
   268 000001E6 723E                <1> 	jb .match_last		; yes -->
   269 000001E8 51                  <1> 	push cx
   270 000001E9 B9F0FF              <1> 	mov cx, 0FFF0h		; do full transfer
   271 000001EC E80300              <1> 	call .match_copy
   272 000001EF 59                  <1> 	pop cx
   273 000001F0 EBED                <1> 	jmp .match_loop		; loop for more
   274                              <1> 
   275                              <1> .match_copy:
   276 000001F2 294EE6              <1> 	sub word [bp + ?length_of_destination], cx
   277 000001F5 835EE800            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   278 000001F9 7303E9AC00          <1> 	jb .error
   279 000001FE F3A4                <1> 	rep movsb		; copy matched bytes
   280 00000200 E9E300              <1> 	jmp normalise_both_pointers
   281                              <1> 
   282                              <1> .get_match_pointer:
   283 00000203 F7DB                <1> 	neg bx
   284 00000205 F7D9                <1> 	neg cx
   285 00000207 83DB00              <1> 	sbb bx, byte 0		; neg bx:cx
   286                              <1> 
   287 0000020A 06                  <1> 	 push es
   288 0000020B 57                  <1> 	 push di
   289 0000020C E80801              <1> 	call normalise_pointer_with_displacement_bxcx
   290                              <1> 				; -> match to copy
   291 0000020F 5E                  <1> 	 pop si
   292 00000210 5B                  <1> 	 pop bx
   293 00000211 7203E99400          <1> 	jnc .error		; if too high (underflow) -->
   294 00000216 3B5EF4              <1> 	cmp bx, word [bp + ?original_dst + 2]
   295 00000219 7503                <1> 	jne @F
   296 0000021B 3B76F2              <1> 	cmp si, word [bp + ?original_dst]
   297                              <1> @@:
   298 0000021E 7303E98700          <1> 	jb .error		; if too low -->
   299 00000223 8EDB                <1> 	mov ds, bx		; ds:si -> match to copy
   300 00000225 C3                  <1> 	retn
   301                              <1> 
   302                              <1> .match_last:
   303 00000226 83C1F0              <1> 	add cx, 0FFF0h		; restore counter (high word discarded)
   304 00000229 E8C6FF              <1> 	call .match_copy	; do last transfer (0 .. 0FFEFh bytes)
   305                              <1> 
   306 0000022C 5E                  <1>         pop     si              ; restore ds:si
   307 0000022D 1F                  <1>         pop     ds
   308                              <1> 
   309                              <1> %if _ALLOW_OVERLAPPING
   310 0000022E E80300              <1> 	call .checkoverlap
   311 00000231 E942FF              <1> 	jmp .next_command
   312                              <1> 
   313                              <1> .checkoverlap:
   314 00000234 52                  <1> 	push dx
   315 00000235 50                  <1> 	push ax
   316 00000236 E89900              <1> 	call check_pointers_not_overlapping
   317 00000239 58                  <1> 	pop ax
   318 0000023A 5A                  <1> 	pop dx
   319 0000023B 726D                <1> 	jc .error
   320                              <1> 
   321 0000023D BB0200              <1> 	mov bx, 2		; set follows_literal to 2 (bx is unmodified by match commands)
   322 00000240 C3                  <1> 	retn
   323                              <1> %else
   324                              <1>         mov     bl,02H          ; set follows_literal to 2 (bx is unmodified by match commands)
   325                              <1> 	jmp .next_command
   326                              <1> %endif
   327                              <1> 
   328                              <1>         ; read gamma2-coded value into cx
   329                              <1> 
   330                              <1> .get_gamma2:
   331 00000241 31C9                <1>         xor     cx,cx           ; initialize to 1 so that value will start at 2
   332 00000243 894EFC              <1> 	mov word [bp + ?gamma_high_word], cx
   333                              <1> 				; initialise high word to zero
   334 00000246 41                  <1>         inc     cx              ; when shifted left in the adc below
   335                              <1> 
   336                              <1> .gamma2_loop:
   337 00000247 E87200              <1>         call    .get_dibits     ; read data bit, shift into cx, read continuation bit
   338 0000024A 72FB                <1>         jc      .gamma2_loop    ; loop until a zero continuation bit is read
   339                              <1> 
   340 0000024C C3                  <1>         ret
   341                              <1> 
   342                              <1>         ; handle 7 bits offset + 1 bit len or 4 bits offset / 1 byte copy
   343                              <1> 
   344                              <1> .other:
   345 0000024D 31C9                <1>         xor     cx,cx
   346 0000024F E87400              <1>         call    .get_bit        ; read '7+1 match or short literal' bit
   347 00000252 7217                <1>         jc      .short_literal  ; 111: 4 bit offset for 1-byte copy
   348                              <1> 
   349                              <1>                                 ; 110: 7 bits offset + 1 bit length
   350 00000254 894EFC              <1> 	mov word [bp + ?gamma_high_word], cx
   351 00000257 894EFA              <1> 	mov word [bp + ?distance_high_word], cx
   352                              <1> 				; clear both high words
   353                              <1> 
   354 0000025A 92                  <1> 	xchg ax, dx
   355 0000025B E85100              <1> 	call .lodsb
   356 0000025E 92                  <1> 	xchg ax, dx		; read offset + length in dl
   357                              <1> 
   358 0000025F 41                  <1>         inc     cx              ; prepare cx for length below
   359 00000260 D0EA                <1>         shr     dl,1            ; shift len bit into carry, and offset in place
   360 00000262 743D                <1>         je      .done           ; if zero offset: EOD
   361 00000264 11C9                <1>         adc     cx,cx           ; len in cx: 1*2 + carry bit = 2 or 3
   362                              <1> 
   363 00000266 30F6                <1>         xor     dh,dh           ; clear high bits of offset
   364 00000268 E966FF              <1> 	jmp .got_len
   365                              <1> 
   366                              <1>         ; 4 bits offset / 1 byte copy
   367                              <1> 
   368                              <1> .short_literal:
   369 0000026B 894EFC              <1> 	mov word [bp + ?gamma_high_word], cx
   370 0000026E E84B00              <1>         call    .get_dibits     ; read 2 offset bits
   371 00000271 11C9                <1>         adc     cx,cx
   372 00000273 E84600              <1>         call    .get_dibits     ; read 2 offset bits
   373 00000276 11C9                <1>         adc     cx,cx
   374 00000278 91                  <1>         xchg    ax,cx           ; preserve bit queue in cx, put offset in ax
   375 00000279 740D                <1>         jz      .write_zero     ; if offset is 0, write a zero byte
   376                              <1> 
   377                              <1>                                 ; short offset 1-15
   378 0000027B 51                  <1> 	push cx
   379 0000027C 1E                  <1> 	push ds
   380 0000027D 56                  <1> 	push si
   381 0000027E 31DB                <1> 	xor bx, bx		; we trash bx, it will be reset to 3 when we loop
   382 00000280 91                  <1> 	xchg ax, cx		; bx:cx = offset to subtract
   383 00000281 E87FFF              <1> 	call .get_match_pointer
   384 00000284 AC                  <1> 	lodsb			; al = byte [ds:si]
   385                              <1> 				; read byte from short offset
   386 00000285 5E                  <1> 	pop si
   387 00000286 1F                  <1> 	pop ds
   388 00000287 59                  <1> 	pop cx
   389                              <1> .write_zero:
   390 00000288 836EE601            <1> 	sub word [bp + ?length_of_destination], 1
   391 0000028C 835EE800            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   392 00000290 7218                <1> 	jb .error
   393 00000292 AA                  <1>         stosb                   ; copy matched byte
   394 00000293 06                  <1> 	push es
   395 00000294 57                  <1> 	push di
   396 00000295 E85D00              <1> 	call normalise_pointer
   397 00000298 5F                  <1> 	pop di
   398 00000299 07                  <1> 	pop es
   399 0000029A 91                  <1>         xchg    ax,cx           ; restore bit queue in al
   400                              <1> %if _ALLOW_OVERLAPPING
   401 0000029B E896FF              <1> 	call .checkoverlap	; CHG: cx, bx
   402                              <1> %endif
   403 0000029E E9D2FE              <1>         jmp     .next_command_after_literal
   404                              <1> 
   405                              <1> .done:
   406 000002A1 8B4EEA              <1> 	mov cx, word [bp + ?length_of_source]
   407 000002A4 0B4EEC              <1> 	or cx, word [bp + ?length_of_source + 2]
   408 000002A7 7501                <1> 	jnz .error
   409                              <1> 
   410 000002A9 A8                  <1> 	db __TEST_IMM8		; (skip stc, NC)
   411                              <1> .error:
   412 000002AA F9                  <1> 	stc
   413                              <1> 
   414                              <1> %if _COUNTER
   415                              <1> 	lahf
   416                              <1> 	mov al, 13
   417                              <1> 	call disp_al
   418                              <1> 	mov al, 10
   419                              <1> 	call disp_al
   420                              <1> 	sahf
   421                              <1> %endif
   422                              <1> d0	mov bx, word [bp + ?errordata]
   423 000002AB 89EC5D              <1> 	lleave code
   424 000002AE C3                  <1> 	lret
   425                              <1> 
   426                              <1> 
   427                              <1> 		; INP:	ds:si -> source data
   428                              <1> 		;	?length_of_source
   429                              <1> 		; OUT:	CY if error (source buffer too small)
   430                              <1> 		;	NC if success,
   431                              <1> 		;	 al = value read
   432                              <1> 		;	 ds:si incremented (normalised)
   433                              <1> 		;	 ?length_of_source decremented
   434                              <1> .lodsb:
   435 000002AF 836EEA01            <1> 	sub word [bp + ?length_of_source], 1
   436 000002B3 835EEC00            <1> 	sbb word [bp + ?length_of_source + 2], 0
   437 000002B7 72F1                <1> 	jb .error
   438 000002B9 AC                  <1> 	lodsb
   439 000002BA EB31                <1> 	jmp normalise_dssi_pointer
   440                              <1> 
   441                              <1> 
   442                              <1> .get_dibits:
   443 000002BC E80700              <1>         call    .get_bit        ; read data bit
   444 000002BF 11C9                <1>         adc     cx,cx           ; shift into cx
   445 000002C1 D156FC              <1> 	rcl word [bp + ?gamma_high_word], 1
   446 000002C4 72E4                <1> 	jc .error
   447                              <1> 
   448                              <1> .get_bit:
   449 000002C6 00C0                <1>         add     al,al           ; shift bit queue, and high bit into carry
   450 000002C8 7507                <1>         jnz     .got_bit        ; queue not empty, bits remain
   451 000002CA 9C                  <1> 	pushf
   452 000002CB E8E1FF              <1> 	call .lodsb		; read 8 new bits
   453 000002CE 9D                  <1> 	popf
   454 000002CF 10C0                <1>         adc     al,al           ; shift bit queue, and high bit into carry
   455                              <1> .got_bit:
   456 000002D1 C3                  <1>         ret
  1052                                  %endif
  1053                                  
  1054                                  
  1055                                  %if _BZP
  1056                                  	%include "bzp.asm"
  1057                                  %endif
  1058                                  
  1059                                  
  1060                                  %if _ALLOW_OVERLAPPING
  1061                                  		; INP:	?src, ?dst
  1062                                  		; OUT:	CY if error (?src < ?dst)
  1063                                  		;	NC if success
  1064                                  		; CHG:	ax, bx, cx, dx
  1065                                  check_pointers_not_overlapping:
  1066                                  %if CHECK_POINTERS_VARIABLE_DST
  1067                                  	 push word [bp + ?dst + 2]
  1068                                  	 push word [bp + ?dst]
  1069                                  %else
  1070 000002D2 06                      	 push es
  1071 000002D3 57                      	 push di
  1072                                  %endif
  1073 000002D4 E86F00                  	call pointer_to_linear
  1074                                  
  1075 000002D7 91                      	xchg cx, ax
  1076 000002D8 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1077                                  
  1078                                  %if CHECK_POINTERS_VARIABLE_SRC
  1079                                  	 push word [bp + ?src + 2]
  1080                                  	 push word [bp + ?src]
  1081                                  %else
  1082 000002DA 1E                      	 push ds
  1083 000002DB 56                      	 push si
  1084                                  %endif
  1085 000002DC E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1086                                  
  1087 000002DF 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1088 000002E1 7502                    	jne @F
  1089 000002E3 39C8                    	cmp ax, cx
  1090                                  @@:
  1091                                  					; (CY) if error (src < dst)
  1092                                  					; (NC) if no error
  1093 000002E5 C3                      	retn
  1094                                  %endif
  1095                                  
  1096                                  	; This leaves the lframe context created within the
  1097                                  	;  specific depacker's file. The above function
  1098                                  	;  check_pointers_not_overlapping uses the frame.
  1099                                  	lleave ctx
  1100                                  
  1101                                  
  1102                                  		; INP:	ds:si = pointer
  1103                                  		;	es:di = pointer
  1104                                  		; OUT:	ds:si normalised
  1105                                  		;	es:di normalised
  1106                                  normalise_both_pointers:
  1107 000002E6 06                      	 push es
  1108 000002E7 57                      	 push di
  1109 000002E8 E80A00                  	call normalise_pointer
  1110 000002EB 5F                      	 pop di
  1111 000002EC 07                      	 pop es
  1112                                  
  1113                                  normalise_dssi_pointer:
  1114 000002ED 1E                      	 push ds
  1115 000002EE 56                      	 push si
  1116 000002EF E80300                  	call normalise_pointer
  1117 000002F2 5E                      	 pop si
  1118 000002F3 1F                      	 pop ds
  1119 000002F4 C3                      	retn
  1120                                  
  1121                                  
  1122                                  		; INP:	word [ss:sp + 2] = segment
  1123                                  		;	word [ss:sp] = offset
  1124                                  		;
  1125                                  		; Note:	Does not work correctly with pointers that point to
  1126                                  		;	 a HMA location. Do not use then!
  1127                                  normalise_pointer:
  1128                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1129                                  	lframe near
  1130                                  	lpar word,	segment
  1131                                  	lpar word,	offset
  1132                                  	lpar_return
  1133 000002F5 5589E5                  	lenter
  1134                                  
  1135 000002F8 837E040F                	cmp word [bp + ?offset], 15
  1136 000002FC 7617                    	jbe .ret
  1137                                  
  1138 000002FE 53                      	push bx
  1139 000002FF 51                      	push cx
  1140                                  
  1141 00000300 31DB                    	xor bx, bx
  1142 00000302 31C9                    	xor cx, cx
  1143 00000304 FF7606                  	 push word [bp + ?segment]
  1144 00000307 FF7604                  	 push word [bp + ?offset]
  1145 0000030A E80A00                  	call normalise_pointer_with_displacement_bxcx
  1146 0000030D 8F4604                  	 pop word [bp + ?offset]
  1147 00000310 8F4606                  	 pop word [bp + ?segment]
  1148                                  
  1149 00000313 59                      	pop cx
  1150 00000314 5B                      	pop bx
  1151                                  .ret:
  1152 00000315 5D                      	lleave
  1153 00000316 C3                      	lret
  1154                                  
  1155                                  
  1156                                  		; INP:	word [ss:sp + 2] = segment
  1157                                  		;	word [ss:sp] = offset
  1158                                  		;	bx:cx = add/sub displacement
  1159                                  		; OUT:	CY if the displacement carries
  1160                                  		;	NC if not
  1161                                  normalise_pointer_with_displacement_bxcx:
  1162                                  %endif
  1163                                  	lframe near
  1164                                  	lpar word,	segment
  1165                                  	lpar word,	offset
  1166                                  	lpar_return
  1167 00000317 5589E5                  	lenter
  1168                                  
  1169                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1170                                  	cmp word [bp + ?offset], 15
  1171                                  	jbe .ret
  1172                                  %endif
  1173                                  
  1174 0000031A 50                      	push ax
  1175 0000031B 51                      	push cx
  1176 0000031C 52                      	push dx
  1177                                  
  1178 0000031D FF7606                  	 push word [bp + ?segment]
  1179 00000320 FF7604                  	 push word [bp + ?offset]
  1180 00000323 E82000                  	call pointer_to_linear
  1181                                  
  1182                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1183                                  	; push bx
  1184                                  	; 				; sign-extend cx into bx:cx
  1185                                  	; cmp cx, 8000h			; CY if < 8000h (NC if negative)
  1186                                  	; cmc				; NC if positive
  1187                                  	; sbb bx, bx			; 0 if was NC, -1 if was CY
  1188                                  
  1189 00000326 01C1                    	add cx, ax
  1190 00000328 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1191                                  	; pop bx
  1192 0000032A 9F                      	lahf				; ah = flags
  1193                                  %else
  1194                                  	xchg ax, cx
  1195                                  %endif
  1196                                  
  1197                                  %if 0
  1198                                  		; Adds in HMA support for this function. Not currently used.
  1199                                  	cmp dx, 10h			; dx:ax >= 10_0000h ?
  1200                                  	jb @F				; no, linear-to-pointer normally -->
  1201                                  	; ja .error
  1202                                  
  1203                                  	add cx, 10h
  1204                                  	; jc .error
  1205                                  	mov word [bp + ?offset], cx
  1206                                  	or word [bp + ?segment], -1
  1207                                  	jmp .return
  1208                                  @@:
  1209                                  %endif
  1210                                  
  1211 0000032B 53                      	push bx
  1212 0000032C 89CB                    	mov bx, cx
  1213 0000032E 83E10F                  	and cx, 15
  1214 00000331 894E04                  	mov word [bp + ?offset], cx
  1215                                  
  1216 00000334 B104                    	mov cl, 4
  1217                                  @@:
  1218 00000336 D1EA                    	shr dx, 1
  1219 00000338 D1DB                    	rcr bx, 1
  1220 0000033A E2FA                    	loop @B
  1221                                  
  1222 0000033C 895E06                  	mov word [bp + ?segment], bx
  1223 0000033F 5B                      	pop bx
  1224                                  
  1225                                  	; test dx, dx
  1226                                  	; jnz .error
  1227                                  
  1228                                  .return:
  1229                                  
  1230                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1231 00000340 9E                      	sahf				; restore flags from ah
  1232                                  %endif
  1233 00000341 5A                      	pop dx
  1234 00000342 59                      	pop cx
  1235 00000343 58                      	pop ax
  1236                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1237                                  .ret:
  1238                                  %endif
  1239 00000344 5D                      	lleave
  1240 00000345 C3                      	lret
  1241                                  
  1242                                  
  1243                                  		; INP:	word [ss:sp + 2] = segment
  1244                                  		;	word [ss:sp] = offset
  1245                                  		; OUT:	dx:ax = linear address
  1246                                  pointer_to_linear:
  1247                                  	lframe near
  1248                                  	lpar word,	segment
  1249                                  	lpar word,	offset
  1250 00000346 5589E5                  	lenter
  1251                                  
  1252 00000349 8B4606                  	mov ax, word [bp + ?segment]
  1253 0000034C 31D2                    	xor dx, dx
  1254 0000034E 51                      	push cx
  1255 0000034F B90400                  	mov cx, 4
  1256                                  @@:
  1257 00000352 D1E0                    	shl ax, 1
  1258 00000354 D1D2                    	rcl dx, 1
  1259 00000356 E2FA                    	loop @B
  1260                                  
  1261 00000358 034604                  	add ax, word [bp + ?offset]
  1262 0000035B 11CA                    	adc dx, cx			; cx = 0 here
  1263 0000035D 59                      	pop cx
  1264                                  
  1265 0000035E 5D                      	lleave
  1266 0000035F C20400                  	lret
  1267                                  
  1268                                  
  1269 00000362 90<rep Eh>              	align 16
  1270                                  init1_end:
  1271                                  
  1272                                  
  1273                                  	section INIT0
  1274                                  %if _TEST_PROGRAM
  1275                                  init0_msg:
  1276 0000025F 4572726F723A204E6F-     .error_stderr:	db "Error: Not enough memory allocated.",13,10
  1276 00000268 7420656E6F75676820-
  1276 00000271 6D656D6F727920616C-
  1276 0000027A 6C6F63617465642E0D-
  1276 00000283 0A                 
  1277                                  .error_stderr.length: equ $ - .error_stderr
  1278 00000284 3132303634              .error_stdout:	_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  1283 00000289 0D0A                    		db 13,10
  1284                                  .error_stdout.length: equ $ - .error_stdout
  1285                                  
  1286 0000028B 90<rep 175h>            	align 1024
  1287                                  %if ($ - $$) != 1024
  1288                                   %error Wrong INIT0 size
  1289                                  %endif
  1290                                  %endif
  1291                                  
  1292                                  	align 16
  1293                                  init0_end:
  1294                                  
  1295                                  
  1296                                  %assign num (init1_end - init1_start) + (init0_end - init0_start)
  1297                                  %if _BRIEFLZ
  1298                                  %define which iniblz
  1299                                  %elif _LZ4
  1300                                  %define which inilz4
  1301                                  %elif _SNAPPY
  1302                                  %define which inisz
  1303                                  %elif _EXODECR
  1304                                  %define which iniexo
  1305                                  %elif _X
  1306                                  %define which inix
  1307                                  %elif _HEATSHRINK
  1308                                  %define which inihs
  1309                                  %elif _LZD
  1310                                  %define which inilz
  1311                                  %elif _LZO
  1312                                  %define which inilzo
  1313                                  %elif _LZSA2
  1314                                  %define which inilzsa2
  1315                                  %elif _APL
  1316                                  %define which iniapl
  1317                                  %elif _BZP
  1318                                  %define which inibzp
  1319                                  %endif
  1320                                  %warning which: num bytes used for depacker
  1320          ******************       warning: iniapl: 1904 bytes used for depacker [-w+user]
  1321                                  
  1322                                  
  1323                                  %if _TEST_PROGRAM
  1324                                  	section INIT2 align=16 follows=INIT1 vstart=0
  1325                                  init2_start:
  1326                                  		; si => after PSP
  1327                                  		; cs => INIT2
  1328                                  		; psp, free, payload, init1, init2, payload space, stack
  1329                                  		;
  1330                                  		; The correct allocation for the test program
  1331                                  		;  is image size (init0, payload, init1, init2)
  1332                                  		;  minus init0 plus compressed payload size
  1333                                  		;  plus decompressed size plus stack. For
  1334                                  		;  simplicity, init0 subtraction may be skipped.
  1335                                  
  1336                                  		; ss:sp -> word amount repetitions, word ax
  1337                                  		; bx = 1 if A test, 8001h if B test
  1338 00000000 53                      	push bx
  1339                                  
  1340                                  	lframe 0
  1341                                  	lpar word,	repetitions
  1342                                  	lpar word,	whichtest
  1343 00000001 5589E5                  	lenter
  1344                                  
  1345 00000004 8B5604                  	mov dx, word [bp + ?repetitions]
  1346 00000007 83FAFF                  	cmp dx, -1
  1347 0000000A 7509                    	jne @F
  1348                                  
  1349                                  .cmdline_error:
  1350                                  %if _DEBUG0
  1351                                  	mov bx, -1
  1352                                  %endif
  1353 0000000C BA[9F02]                	mov dx, init2_msg.cmdline_error
  1354 0000000F B92400                  	mov cx, init2_msg.cmdline_error.length
  1355 00000012 E95B01                  	jmp init2_error
  1356                                  
  1357                                  
  1358                                  @@:
  1359 00000015 F6460380                	testopt [bp + ?whichtest], 8000h
  1360 00000019 7406                    	jz .a
  1361                                  .b:
  1362 0000001B 85D2                    	test dx, dx
  1363 0000001D 74ED                    	jz .cmdline_error
  1364 0000001F EB04                    	jmp @F
  1365                                  
  1366                                  .a:
  1367 00000021 85D2                    	test dx, dx
  1368 00000023 75E7                    	jnz .cmdline_error
  1369                                  @@:
  1370                                  
  1371 00000025 8CCA                    	mov dx, cs
  1372 00000027 81C2231D                	add dx, (init2_end - init2_start) >> 4
  1373                                  				; => payload saving area
  1374 0000002B 8CC8                    	mov ax, cs
  1375 0000002D 2D3412                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  1378 00000030 B9FD11                  	mov cx, (payload_end - payload) >> 4
  1379 00000033 E89402                  	call init2_movp		; copy payload to payload saving area
  1380                                  		; We save away the payload here because a failure
  1381                                  		;  to decompress generally overwrites part of that
  1382                                  		;  payload which was used as source.
  1383                                  
  1384 00000036 89C2                    	mov dx, ax		; dx => payload source to use
  1385 00000038 8CC8                    	mov ax, cs
  1386 0000003A 83E837                  	sub ax, (init1_end - init1_start) >> 4
  1387                                  				; ax => INIT1
  1388 0000003D BB0100                  	mov bx, 1		; say we're in EXE mode
  1389 00000040 52                      	push dx
  1390 00000041 50                      	push ax
  1391 00000042 56                      	push si			; si => target
  1392 00000043 0E                      	 push cs
  1393 00000044 E8EA00                  	 call .transfer		; call decompression
  1394 00000047 5E                      	pop si
  1395 00000048 58                      	pop ax
  1396 00000049 5A                      	pop dx
  1397                                  		; Returns here after decompression.
  1398                                  		; CY if error.
  1399 0000004A 7309                    	jnc @F
  1400                                  
  1401 0000004C BA[F001]                	mov dx, init2_msg.initial_error
  1402 0000004F B93C00                  	mov cx, init2_msg.initial_error.length
  1403 00000052 E91B01                  	jmp init2_error
  1404                                  
  1405                                  @@:
  1406                                  	numdef INCLUDE_UNCOMPRESSED
  1407                                  	numdef WRITE_WRONG_FILE
  1408                                  %if _INCLUDE_UNCOMPRESSED
  1409                                  payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed
  1410                                  
  1411 00000055 E8DF00                  	call checkdecompressed
  1412 00000058 7409                    	je @F
  1413                                  
  1414                                  %if _WRITE_WRONG_FILE
  1415                                  	call writefiles
  1416                                  %endif
  1417                                  
  1418                                  %if _DEBUG0
  1419                                  	mov bx, -1
  1420                                  %endif
  1421 0000005A BA[2C02]                	mov dx, init2_msg.initial_error_2
  1422 0000005D B93C00                  	mov cx, init2_msg.initial_error_2.length
  1423 00000060 E90D01                  	jmp init2_error
  1424                                  
  1425                                  @@:
  1426                                  %endif
  1427                                  
  1428                                  	lvar word,	upperbound
  1429 00000063 52                      	 push dx
  1430                                  	lvar word,	lowerbound
  1431 00000064 56                      	 push si
  1432                                  	lvar word,	current_init1
  1433 00000065 50                      	 push ax
  1434                                  
  1435                                  %if _TEST_PROGRESS
  1436 00000066 BA[E501]                	mov dx, init2_msg.progress.1
  1437 00000069 B90700                  	mov cx, init2_msg.progress.1.length
  1438                                  .loop:
  1439 0000006C 0E                      	push cs
  1440 0000006D 1F                      	pop ds
  1441 0000006E BB0200                  	mov bx, 2
  1442 00000071 B440                    	mov ah, 40h
  1443 00000073 CD21                    	int 21h
  1444                                  %else
  1445                                  .loop:
  1446                                  %endif
  1447                                  
  1448 00000075 8B56FE                  	mov dx, [bp + ?upperbound]
  1449                                  
  1450 00000078 F6460380                	testopt [bp + ?whichtest], 8000h
  1451 0000007C 7419                    	jz @F
  1452                                  
  1453 0000007E FF4E04                  	dec word [bp + ?repetitions]
  1454 00000081 751E                    	jnz .test_b_skip_bound
  1455                                  
  1456                                  %if _TEST_PROGRESS
  1457 00000083 0E                      	push cs
  1458 00000084 1F                      	pop ds
  1459 00000085 BA[EE01]                	mov dx, init2_msg.progress.linebreak
  1460 00000088 B90200                  	mov cx, init2_msg.progress.linebreak.length
  1461 0000008B BB0200                  	mov bx, 2
  1462 0000008E B440                    	mov ah, 40h
  1463 00000090 CD21                    	int 21h
  1464                                  %endif
  1465 00000092 B8004C                  	mov ax, 4C00h
  1466 00000095 CD21                    	int 21h
  1467                                  
  1468                                  
  1469                                  @@:
  1470 00000097 2B56FC                  	sub dx, [bp + ?lowerbound]
  1471 0000009A 746C                    	jz .found
  1472 0000009C D1EA                    	shr dx, 1
  1473                                  		; Rounding down, so that we never retry upper bound.
  1474                                  		;  The upper bound is known to be working.
  1475 0000009E 0356FC                  	add dx, [bp + ?lowerbound]
  1476                                  
  1477                                  .test_b_skip_bound:
  1478 000000A1 52                      	push dx
  1479 000000A2 81C2FD11                	add dx, (payload_end - payload) >> 4
  1480 000000A6 8B46FA                  	mov ax, [bp + ?current_init1]
  1481 000000A9 B93700                  	mov cx, (init1_end - init1_start) >> 4
  1482 000000AC E81B02                  	call init2_movp
  1483 000000AF 8956FA                  	mov [bp + ?current_init1], dx
  1484 000000B2 5A                      	pop dx
  1485                                  
  1486 000000B3 8CC8                    	mov ax, cs
  1487 000000B5 05231D                  	add ax, (init2_end - init2_start) >> 4
  1488                                  				; => payload in saving area
  1489 000000B8 B9FD11                  	mov cx, (payload_end - payload) >> 4
  1490 000000BB E80C02                  	call init2_movp		; copy payload from payload saving area
  1491                                  
  1492                                  		; dx => source
  1493 000000BE 8B46FA                  	mov ax, [bp + ?current_init1]
  1494 000000C1 BB0100                  	mov bx, 1
  1495 000000C4 52                      	push dx
  1496 000000C5 56                      	push si
  1497 000000C6 0E                      	 push cs
  1498 000000C7 E86700                  	 call .transfer
  1499 000000CA 5E                      	pop si
  1500 000000CB 5A                      	pop dx
  1501                                  		; Returns here after decompression.
  1502                                  		; CY if error.
  1503 000000CC 7312                    	jnc @F
  1504                                  
  1505 000000CE F6460380                	testopt [bp + ?whichtest], 8000h
  1506 000000D2 7511                    	jnz .test_b_fail
  1507                                  
  1508                                  		; error: this attempt is one below the new lower bound
  1509 000000D4 42                      	inc dx
  1510 000000D5 8956FC                  	mov word [bp + ?lowerbound], dx
  1511                                  
  1512                                  %if _TEST_PROGRESS
  1513 000000D8 BA[EC01]                	mov dx, init2_msg.progress.fail
  1514 000000DB B90100                  	mov cx, init2_msg.progress.fail.length
  1515                                  %endif
  1516 000000DE EB8C                    	jmp .loop
  1517                                  
  1518                                  @@:
  1519                                  %if _INCLUDE_UNCOMPRESSED
  1520 000000E0 E85400                  	call checkdecompressed
  1521 000000E3 7417                    	je @F
  1522                                  
  1523                                  %if _WRITE_WRONG_FILE
  1524                                  	call writefiles
  1525                                  %endif
  1526                                  
  1527                                  .test_b_fail:
  1528                                  %if _TEST_PROGRESS
  1529 000000E5 0E                      	push cs
  1530 000000E6 1F                      	pop ds
  1531 000000E7 BA[EE01]                	mov dx, init2_msg.progress.linebreak
  1532 000000EA B90200                  	mov cx, init2_msg.progress.linebreak.length
  1533 000000ED BB0200                  	mov bx, 2
  1534 000000F0 B440                    	mov ah, 40h
  1535 000000F2 CD21                    	int 21h
  1536                                  %endif
  1537                                  %if _DEBUG0
  1538                                  	mov bx, -2
  1539                                  %endif
  1540 000000F4 BA[6802]                	mov dx, init2_msg.subsequent_error_2
  1541 000000F7 B93700                  	mov cx, init2_msg.subsequent_error_2.length
  1542 000000FA EB74                    	jmp init2_error
  1543                                  
  1544                                  @@:
  1545                                  %endif
  1546                                  		; success: this attempt is the new upper bound
  1547 000000FC 8956FE                  	mov word [bp + ?upperbound], dx
  1548                                  %if _TEST_PROGRESS
  1549 000000FF BA[ED01]                	mov dx, init2_msg.progress.success
  1550 00000102 B90100                  	mov cx, init2_msg.progress.success.length
  1551                                  %endif
  1552 00000105 E964FF                  	jmp .loop
  1553                                  
  1554                                  .found:
  1555                                  %if _TEST_PROGRESS
  1556 00000108 0E                      	push cs
  1557 00000109 1F                      	pop ds
  1558 0000010A BA[EE01]                	mov dx, init2_msg.progress.linebreak
  1559 0000010D B90200                  	mov cx, init2_msg.progress.linebreak.length
  1560 00000110 BB0200                  	mov bx, 2
  1561 00000113 B440                    	mov ah, 40h
  1562 00000115 CD21                    	int 21h
  1563                                  %endif
  1564 00000117 8B46FE                  	mov ax, word [bp + ?upperbound]
  1565 0000011A 29F0                    	sub ax, si		; = how many paragraphs in buffer before source
  1566 0000011C 053412                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  1568                                  				; = how many paragraphs needed for process
  1569 0000011F E87A00                  	call init2_disp_ax_dec
  1570 00000122 B00D                    	mov al, 13
  1571 00000124 E86A00                  	call init2_disp_al
  1572 00000127 B00A                    	mov al, 10
  1573 00000129 E86500                  	call init2_disp_al
  1574 0000012C B8004C                  	mov ax, 4C00h
  1575 0000012F CD21                    	int 21h
  1576                                  
  1577                                  
  1578                                  .transfer:
  1579 00000131 31FF                    	xor di, di
  1580 00000133 57                      	push di			; dummy ax value on stack
  1581 00000134 50                      	push ax			; INIT1 segment
  1582 00000135 57                      	push di			; zero = init1_start
  1583 00000136 CB                      	retf
  1584                                  
  1585                                  
  1586                                  
  1587                                  %if _INCLUDE_UNCOMPRESSED
  1588                                  
  1589                                  
  1590                                  %if _WRITE_WRONG_FILE
  1591                                  writefiles:
  1592                                  	push cs
  1593                                  	pop ds
  1594                                  	mov dx, init2_msg.wrong_file_name
  1595                                  	xor cx, cx
  1596                                  	mov ah, 3Ch
  1597                                  	int 21h
  1598                                  	jc .notfile
  1599                                  
  1600                                  	mov bx, ax
  1601                                  	mov cx, payload_uncompressed_size >> 4
  1602                                  	xor dx, dx
  1603                                  .loopfile:
  1604                                  	mov ds, si
  1605                                  	mov ah, 40h
  1606                                  	push cx
  1607                                  	mov cx, 16
  1608                                  	int 21h
  1609                                  	pop cx
  1610                                  	inc si
  1611                                  	loop .loopfile
  1612                                  
  1613                                  	mov ds, si
  1614                                  	mov cx, payload_uncompressed_size & 15
  1615                                  	mov ah, 40h
  1616                                  	int 21h
  1617                                  
  1618                                  	mov ah, 3Eh
  1619                                  	int 21h
  1620                                  
  1621                                  .notfile:
  1622                                  
  1623                                  	push cs
  1624                                  	pop ds
  1625                                  	mov dx, init2_msg.wrong_file_name2
  1626                                  	xor cx, cx
  1627                                  	mov ah, 3Ch
  1628                                  	int 21h
  1629                                  	jc .notfile2
  1630                                  
  1631                                  	mov bx, ax
  1632                                  	mov cx, payload_uncompressed_size >> 4
  1633                                  	mov si, cs
  1634                                  	add si, (payload_uncompressed - init2_start) >> 4
  1635                                  	xor dx, dx
  1636                                  .loopfile2:
  1637                                  	mov ds, si
  1638                                  	mov ah, 40h
  1639                                  	push cx
  1640                                  	mov cx, 16
  1641                                  	int 21h
  1642                                  	pop cx
  1643                                  	inc si
  1644                                  	loop .loopfile2
  1645                                  
  1646                                  	mov ds, si
  1647                                  	mov cx, payload_uncompressed_size & 15
  1648                                  	mov ah, 40h
  1649                                  	int 21h
  1650                                  
  1651                                  	mov ah, 3Eh
  1652                                  	int 21h
  1653                                  
  1654                                  .notfile2:
  1655                                  	retn
  1656                                  %endif
  1657                                  
  1658                                  		; INP:	si => decompressed image
  1659                                  		; OUT:	ZR if matching
  1660                                  		;	NZ if mismatching
  1661                                  		; CHG:	es, ds, di, bx, cx
  1662                                  		; STT:	UP
  1663                                  checkdecompressed:
  1664 00000137 50                      	push ax
  1665 00000138 52                      	push dx
  1666 00000139 56                      	push si
  1667                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  1668                                  	mov cx, _PAYLOAD_KERNEL_MAX_PARAS
  1669                                  	mov bx, 0
  1670                                  %else
  1671 0000013A B9EC1C                  	mov cx, payload_uncompressed_size >> 4
  1672 0000013D BB0000                  	mov bx, payload_uncompressed_size & 15
  1673                                  %endif
  1674 00000140 8CCF                    	mov di, cs
  1675 00000142 83C736                  	add di, (payload_uncompressed - init2_start) >> 4
  1676 00000145 E319                    	jcxz .end
  1677                                  .loop:
  1678 00000147 51                      	push cx
  1679 00000148 B90800                  	mov cx, 8
  1680 0000014B 8EDE                    	mov ds, si
  1681 0000014D 8EC7                    	mov es, di
  1682 0000014F 46                      	inc si
  1683 00000150 47                      	inc di
  1684 00000151 56                      	push si
  1685 00000152 57                      	push di
  1686 00000153 31F6                    	xor si, si
  1687 00000155 31FF                    	xor di, di
  1688 00000157 F3A7                    	repe cmpsw
  1689 00000159 5F                      	pop di
  1690 0000015A 5E                      	pop si
  1691 0000015B 59                      	pop cx
  1692 0000015C 750E                    	jne .ret
  1693 0000015E E2E7                    	loop .loop
  1694                                  .end:
  1695 00000160 8EDE                    	mov ds, si
  1696 00000162 8EC7                    	mov es, di
  1697 00000164 31F6                    	xor si, si
  1698 00000166 31FF                    	xor di, di		; (ZR)
  1699 00000168 89D9                    	mov cx, bx
  1700 0000016A F3A6                    	repe cmpsb
  1701                                  .ret:
  1702 0000016C 5E                      	pop si
  1703 0000016D 5A                      	pop dx
  1704 0000016E 58                      	pop ax
  1705 0000016F C3                      	retn
  1706                                  %endif
  1707                                  
  1708                                  
  1709                                  init2_error:
  1710                                  %if _DEBUG0
  1711                                  	push bx
  1712                                  %endif
  1713 00000170 0E                      	push cs
  1714 00000171 1F                      	pop ds
  1715 00000172 BB0200                  	mov bx, 2
  1716 00000175 B440                    	mov ah, 40h
  1717 00000177 CD21                    	int 21h
  1718                                  
  1719                                  %if _DEBUG0
  1720                                  	mov dx, init2_msg.rc
  1721                                  	mov cx, init2_msg.rc.length
  1722                                  	mov bx, 2
  1723                                  	mov ah, 40h
  1724                                  	int 21h
  1725                                  	pop ax
  1726                                  	call init2_error_disp_ax_hex
  1727                                  	mov dx, init2_msg.linebreak
  1728                                  	mov cx, init2_msg.linebreak.length
  1729                                  	mov bx, 2
  1730                                  	mov ah, 40h
  1731                                  	int 21h
  1732                                  %endif
  1733                                  
  1734 00000179 F6460380                	testopt [bp + ?whichtest], 8000h
  1735 0000017D 750D                    	jnz @F
  1736                                  
  1737 0000017F BA[C302]                	mov dx, init2_msg.error_stdout
  1738 00000182 B90700                  	mov cx, init2_msg.error_stdout.length
  1739 00000185 BB0100                  	mov bx, 1
  1740 00000188 B440                    	mov ah, 40h
  1741 0000018A CD21                    	int 21h
  1742                                  @@:
  1743 0000018C B8FF4C                  	mov ax, 4CFFh
  1744 0000018F CD21                    	int 21h
  1745                                  
  1746                                  	lleave ctx
  1747                                  
  1748                                  
  1749                                  %if _DEBUG0
  1750                                  init2_error_disp_ax_hex:	; ax
  1751                                  		xchg al,ah
  1752                                  		call init2_error_disp_al_hex	; display former ah
  1753                                  		xchg al,ah			;  and fall trough for al
  1754                                  init2_error_disp_al_hex:	; al
  1755                                  		push cx
  1756                                  		mov cl,4
  1757                                  		ror al,cl
  1758                                  		call init2_error_disp_al_lownibble_hex
  1759                                  						; display former high-nibble
  1760                                  		rol al,cl
  1761                                  		pop cx
  1762                                  						;  and fall trough for low-nibble
  1763                                  init2_error_disp_al_lownibble_hex:
  1764                                  		push ax			 ; save ax for call return
  1765                                  		and al,00001111b		; high nibble must be zero
  1766                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1767                                  		cmp al,'9'
  1768                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1769                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1770                                   .decimalnum:
  1771                                  		call init2_error_disp_al
  1772                                  		pop ax
  1773                                  		retn
  1774                                  
  1775                                  
  1776                                  init2_error_disp_al:
  1777                                  	push dx
  1778                                  	push cx
  1779                                  	push bx
  1780                                  	push ax
  1781                                  	mov dx, sp
  1782                                  	push ds
  1783                                  	 push ss
  1784                                  	 pop ds
  1785                                  	mov cx, 1
  1786                                  	mov bx, 2
  1787                                  	mov ah, 40h
  1788                                  	int 21h
  1789                                  	pop ds
  1790                                  	pop ax
  1791                                  	pop bx
  1792                                  	pop cx
  1793                                  	pop dx
  1794                                  	retn
  1795                                  %endif
  1796                                  
  1797                                  
  1798                                  init2_disp_al:
  1799 00000191 52                      	push dx
  1800 00000192 50                      	push ax
  1801 00000193 88C2                    	mov dl, al
  1802 00000195 B402                    	mov ah, 2
  1803 00000197 CD21                    	int 21h
  1804 00000199 58                      	pop ax
  1805 0000019A 5A                      	pop dx
  1806 0000019B C3                      	retn
  1807                                  
  1808                                  
  1809                                  		; Display number in ax decimal
  1810                                  		;
  1811                                  		; INP:	ax = number
  1812                                  		; OUT:	displayed using Int21.02
  1813                                  		; CHG:	none
  1814                                  init2_disp_ax_dec:			; ax (no leading zeros)
  1815 0000019C 53                      		push bx
  1816 0000019D 31DB                    		xor bx, bx
  1817                                  .pushax:
  1818 0000019F 52                      		push dx
  1819 000001A0 50                      		push ax
  1820 000001A1 08DB                    		or bl, bl
  1821 000001A3 7405                    		jz .nobl
  1822 000001A5 80EB05                  		sub bl, 5
  1823 000001A8 F6DB                    		neg bl
  1824                                  .nobl:
  1825 000001AA 51                      		push cx
  1826 000001AB B91027                  		mov cx, 10000
  1827 000001AE E81B00                  		call .divide_out
  1828 000001B1 B9E803                  		mov cx, 1000
  1829 000001B4 E81500                  		call .divide_out
  1830 000001B7 B96400                  		mov cx, 100
  1831 000001BA E80F00                  		call .divide_out
  1832 000001BD B10A                    		mov cl, 10
  1833 000001BF E80A00                  		call .divide_out
  1834                                  							; (Divisor 1 is useless)
  1835 000001C2 0430                    		add al, '0'
  1836 000001C4 E8CAFF                  		call init2_disp_al
  1837 000001C7 59                      		pop cx
  1838 000001C8 58                      		pop ax
  1839 000001C9 5A                      		pop dx
  1840 000001CA 5B                      		pop bx					; Caller's register
  1841 000001CB C3                      		retn
  1842                                  
  1843                                  
  1844                                  		; INP:	ax = number
  1845                                  		;	cx = divisor
  1846                                  		; OUT:	ax = remainder of operation
  1847                                  		;	result displayed
  1848                                  .divide_out:
  1849 000001CC 52                      		push dx
  1850 000001CD 31D2                    		xor dx, dx
  1851 000001CF F7F1                    		div cx				; 0:ax / cx
  1852 000001D1 52                      		push dx				; remainder
  1853 000001D2 FECB                    		dec bl
  1854 000001D4 7503                    		jnz .nobl2
  1855 000001D6 80CF01                  		or bh, 1
  1856                                  .nobl2:
  1857 000001D9 08C7                    		or bh, al
  1858 000001DB 7405                    		jz .leadingzero
  1859 000001DD 0430                    		add al, '0'
  1860 000001DF E8AFFF                  		call init2_disp_al		; display result
  1861                                   .leadingzero:
  1862 000001E2 58                      		pop ax				; remainder
  1863 000001E3 5A                      		pop dx
  1864 000001E4 C3                      		retn
  1865                                  
  1866                                  
  1867                                  init2_msg:
  1868                                  %if _TEST_PROGRESS
  1869 000001E5 496E666F3A2031          .progress.1:		db "Info: 1"
  1870                                  .progress.1.length: equ $ - .progress.1
  1871 000001EC 46                      .progress.fail:		db "F"
  1872                                  .progress.fail.length: equ $ - .progress.fail
  1873 000001ED 53                      .progress.success:	db "S"
  1874                                  .progress.success.length: equ $ - .progress.success
  1875 000001EE 0D0A                    .progress.linebreak:	db 13,10
  1876                                  .progress.linebreak.length: equ $ - .progress.linebreak
  1877                                  %endif
  1878                                  %if _WRITE_WRONG_FILE
  1879                                  .wrong_file_name:	asciz "WRONG.BIN"
  1880                                  .wrong_file_name2:	asciz "WRONG2.BIN"
  1881                                  %endif
  1882 000001F0 4572726F723A205465-     .initial_error:	db "Error: Test program failed to decompress with full buffer."
  1882 000001F9 73742070726F677261-
  1882 00000202 6D206661696C656420-
  1882 0000020B 746F206465636F6D70-
  1882 00000214 726573732077697468-
  1882 0000021D 2066756C6C20627566-
  1882 00000226 6665722E           
  1883 0000022A 0D0A                    .linebreak:	db 13,10
  1884                                  .initial_error.length: equ $ - .initial_error
  1885                                  .linebreak.length: equ $ - .linebreak
  1886                                  %if _DEBUG0
  1887                                  .rc:	db "Error: Failure code="
  1888                                  .rc.length: equ $ - .rc
  1889                                  %endif
  1890                                  %if _INCLUDE_UNCOMPRESSED
  1891 0000022C 4572726F723A205465-     .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  1891 00000235 73742070726F677261-
  1891 0000023E 6D206465636F6D7072-
  1891 00000247 65737365642077726F-
  1891 00000250 6E676C792077697468-
  1891 00000259 2066756C6C20627566-
  1891 00000262 6665722E0D0A       
  1892                                  .initial_error_2.length: equ $ - .initial_error_2
  1893 00000268 4572726F723A205465-     .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  1893 00000271 73742070726F677261-
  1893 0000027A 6D206465636F6D7072-
  1893 00000283 65737365642077726F-
  1893 0000028C 6E676C792064757269-
  1893 00000295 6E6720746573742E0D-
  1893 0000029E 0A                 
  1894                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  1895                                  %endif
  1896 0000029F 4572726F723A20496E-     .cmdline_error:	db "Error: Invalid command line input.",13,10
  1896 000002A8 76616C696420636F6D-
  1896 000002B1 6D616E64206C696E65-
  1896 000002BA 20696E7075742E0D0A 
  1897                                  .cmdline_error.length: equ $ - .cmdline_error
  1898 000002C3 3132303634              .error_stdout:	_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  1903 000002C8 0D0A                    		db 13,10
  1904                                  .error_stdout.length: equ $ - .error_stdout
  1905                                  
  1906                                  
  1907                                  		; Move paragraphs
  1908                                  		;
  1909                                  		; INP:	ax => source
  1910                                  		;	dx => destination
  1911                                  		;	cx = number of paragraphs
  1912                                  		; CHG:	-
  1913                                  		; OUT:	ax and dx unchanged
  1914                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  1915                                  		;	Do not provide a wrapped/HMA source or destination!
  1916                                  init2_movp:
  1917 000002CA 51                      	push cx
  1918 000002CB 1E                      	push ds
  1919 000002CC 56                      	push si
  1920 000002CD 06                      	push es
  1921 000002CE 57                      	push di
  1922                                  
  1923 000002CF 39D0                    	cmp ax, dx		; source above destination ?
  1924 000002D1 770A                    	ja .up			; yes, move up (forwards) -->
  1925 000002D3 747B                    	je .return		; same, no need to move -->
  1926 000002D5 50                      	push ax
  1927 000002D6 01C8                    	add ax, cx		; (expected not to carry)
  1928 000002D8 39D0                    	cmp ax, dx		; end of source is above destination ?
  1929 000002DA 58                      	pop ax
  1930 000002DB 7730                    	ja .down		; yes, move from top down -->
  1931                                  	; Here, the end of source is below-or-equal the destination,
  1932                                  	;  so they do not overlap. In this case we prefer moving up.
  1933                                  
  1934                                  .up:
  1935 000002DD 50                      	push ax
  1936 000002DE 52                      	push dx
  1937                                  .uploop:
  1938 000002DF 8ED8                    	mov ds, ax
  1939 000002E1 8EC2                    	mov es, dx
  1940 000002E3 31FF                    	xor di, di
  1941 000002E5 31F6                    	xor si, si		; -> start of segment
  1942 000002E7 81E90010                	sub cx, 1000h		; 64 KiB left ?
  1943 000002EB 7610                    	jbe .uplast		; no -->
  1944 000002ED 51                      	push cx
  1945 000002EE B90080                  	mov cx, 10000h /2
  1946 000002F1 F3A5                    	rep movsw		; move 64 KiB
  1947 000002F3 59                      	pop cx
  1948 000002F4 050010                  	add ax, 1000h
  1949 000002F7 81C20010                	add dx, 1000h		; -> next segment
  1950 000002FB EBE2                    	jmp short .uploop	; proceed for more -->
  1951                                  .uplast:
  1952 000002FD 81C10010                	add cx, 1000h		; restore counter
  1953 00000301 D1E1                    	shl cx, 1
  1954 00000303 D1E1                    	shl cx, 1
  1955 00000305 D1E1                    	shl cx, 1		; *8, paragraphs to words
  1956 00000307 F3A5                    	rep movsw		; move last part
  1957 00000309 5A                      	pop dx
  1958 0000030A 58                      	pop ax
  1959 0000030B EB43                    	jmp short .return
  1960                                  
  1961                                  .down:
  1962 0000030D FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
  1963                                  .dnloop:
  1964 0000030E 81E90010                	sub cx, 1000h		; 64 KiB left ?
  1965 00000312 761A                    	jbe .dnlast		; no -->
  1966 00000314 50                      	push ax
  1967 00000315 52                      	push dx
  1968 00000316 01C8                    	add ax, cx
  1969 00000318 01CA                    	add dx, cx
  1970 0000031A 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
  1971 0000031C 8EC2                    	mov es, dx
  1972 0000031E 5A                      	pop dx
  1973 0000031F 58                      	pop ax
  1974 00000320 BFFEFF                  	mov di, -2
  1975 00000323 89FE                    	mov si, di		; moved from last word down
  1976 00000325 51                      	push cx
  1977 00000326 B90080                  	mov cx, 10000h /2
  1978 00000329 F3A5                    	rep movsw		; move 64 KiB
  1979 0000032B 59                      	pop cx
  1980 0000032C EBE0                    	jmp short .dnloop	; proceed for more -->
  1981                                  .dnlast:
  1982 0000032E 81C10010                	add cx, 1000h		; restore counter
  1983 00000332 D1E1                    	shl cx, 1
  1984 00000334 D1E1                    	shl cx, 1
  1985 00000336 D1E1                    	shl cx, 1		; *8, paragraphs to words
  1986 00000338 89CF                    	mov di, cx
  1987 0000033A 4F                      	dec di
  1988 0000033B D1E7                    	shl di, 1		; words to offset, -> last word
  1989 0000033D 89FE                    	mov si, di
  1990 0000033F 8ED8                    	mov ds, ax
  1991 00000341 8EC2                    	mov es, dx		; first segment correct
  1992                                  
  1993                                  		; Refer to comment in init0_movp.
  1994                                  %if _AMD_ERRATUM_109_WORKAROUND
  1995 00000343 E308                    	jcxz @FF
  1996 00000345 83F914                  	cmp cx, 20
  1997 00000348 7703                    	ja @FF
  1998                                  @@:
  1999 0000034A A5                      	movsw
  2000 0000034B E2FD                    	loop @B
  2001                                  @@:
  2002                                  %endif
  2003 0000034D F3A5                    	rep movsw		; move first part
  2004 0000034F FC                      	cld
  2005                                  .return:
  2006 00000350 5F                      	pop di
  2007 00000351 07                      	pop es
  2008 00000352 5E                      	pop si
  2009 00000353 1F                      	pop ds
  2010 00000354 59                      	pop cx
  2011 00000355 C3                      	retn
  2012                                  
  2013                                  
  2014 00000356 90<rep Ah>              	align 16
  2015                                  
  2016                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  2017                                  %if _INCLUDE_UNCOMPRESSED
  2018                                  payload_uncompressed:
  2019 00000360 <bin 1CEC0h>            	incbin _UNCOMPRESSED_FILE
  2020                                  .end:
  2021 0001D220 26                      	db 38
  2022 0001D221 26<rep Fh>              	align 16, db 38
  2023                                  %endif
  2024                                  init2_end:
  2025                                  %endif
  2026                                  
