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