     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, "Db"
     3                              <1> %assign _DEVICE 1
     4                              <1> %assign _DEVICE_ZERO_ENTRYPOINT 1
     5                              <1> %assign _DEVICE_ATTRIBUTE 8800h
     6                              <1> %define _DEVICE_NAME "LDEBUG$$"
     7                              <1> %define _PROGRESSVARNAME "LDEBUGPROGRESS"
     8                              <1> %assign _LOADERSUPPORT 1
   170                                  %endif
   171                                  	strdef LCFG_CFG, ""
   172                                  
   173                                  %if _DEVICE
   174                                   %ifidn _DEVICE_NAME, ""
   175                                    %error Device name must be set
   176                                   %endif
   177                                  %endif
   178                                  
   179                                  	struc XMSM
   180 00000000 ????????                .size_:		resd 1
   181 00000004 ????                    .srchdl:	resw 1
   182 00000006 ????????                .srcadr:	resd 1
   183 0000000A ????                    .dsthdl:	resw 1
   184 0000000C ????????                .dstadr:	resd 1
   185                                  	endstruc
   186                                  
   187                                  
   188                                  	cpu 8086
   189                                  	addsection INIT0, start=0 vstart=0
   190                                  init0_start:
   191                                  %if _DEVICE
   192                                  		; The device header is of a fixed format.
   193                                  		;  For our purposes, the 4-byte code for
   194                                  		;  each the strategy entry and the
   195                                  		;  interrupt entry is part of this format.
   196                                  		; (DOS may read the attributes or entrypoint
   197                                  		;  offsets before calling either, so in the inicomp
   198                                  		;  stage we need to recreate in the entrypoints part
   199                                  		;  exactly what the application has here.)
   200                                  		; _PASSLCFG: The lCFG block is passed in the dword
   201                                  		;  behind the interrupt entry.
   202                                  device_header:
   203                                  .next:
   204                                   %if _DEVICE_ZERO_ENTRYPOINT
   205 00000000 EB3E                    	fill 2, -1, jmp strict short j_zero_entrypoint
   206 00000002 FFFF                    	dw -1
   207                                   %else
   208                                  	dd -1				; link to next device
   209                                   %endif
   210                                  .attributes:
   211 00000004 0088                    	dw _DEVICE_ATTRIBUTE		; attributes
   212                                  .strategy:
   213 00000006 [1200]                  	dw .strategy_entry		; -> strategy entry
   214                                  .interrupt:
   215 00000008 [1600]                  	dw .interrupt_entry		; -> interrupt entry
   216                                  .name:
   217 0000000A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME	; character device name,
   218                                  					;  or block device number of units
   219                                  					;  + optional name
   220                                  .strategy_entry:
   221 00000012 E96B0190                	fill 4, 90h, jmp device_entrypoint
   222                                  .interrupt_entry:
   223 00000016 CB90<rep 3h>            	fill 4, 90h, retf
   224                                  .pass_lcfg:
   225                                  %endif
   226                                  
   227                                  
   228                                  %if _IMAGE_EXE || _DEVICE
   229 0000001A 90                      	nop
   230 0000001B 90<rep 5h>              	align 32, nop
   231                                  init0_kernel_entry:
   232                                  		; cs:ip = load seg : 32 here
   233                                  %if ($ - $$) != 32
   234                                   %error Wrong kernel mode entrypoint
   235                                  %endif
   236                                  %if _TEST_PROGRAM
   237                                  @@:
   238 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 E9AF00                  	jmp init0_common
   254                                  %endif
   255                                  
   256                                   %if _IMAGE_EXE
   257 00000036 90<rep Ah>              	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 00000044 1E                      	push ds
   280 00000045 A12C00                  	mov ax, word [2Ch]	; => environment
   281 00000048 85C0                    	test ax, ax
   282 0000004A 7503                    	jnz @F
   283                                  .errorfile:
   284 0000004C E9E600                  	jmp init0_error_file
   285                                  @@:
   286 0000004F 8ED8                    	mov ds, ax
   287 00000051 B90080                  	mov cx, 8000h
   288 00000054 31F6                    	xor si, si		; -> environment
   289                                  @@:
   290 00000056 AC                      	lodsb
   291 00000057 84C0                    	test al, al
   292 00000059 E0FB                    	loopnz @B		; si -> past one NUL
   293 0000005B E3EF                    	jcxz .errorfile
   294 0000005D 803C00                  	cmp byte [si], 0	; -> another NUL ?
   295 00000060 E0F4                    	loopne @B		; no, skip next variable -->
   296 00000062 E3E8                    	jcxz .errorfile
   297 00000064 46                      	inc si			; skip double NUL
   298 00000065 AD                      	lodsw			; load amount strings after environment
   299 00000066 83F801                  	cmp ax, 1		; 1 ?
   300 00000069 75E1                    	jne .errorfile		; no -->
   301 0000006B 89F2                    	mov dx, si		; ds:dx -> executable pathname
   302 0000006D B8203D                  	mov ax, 3D00h + 0_010_0_000b	; deny write, read only
   303 00000070 CD21                    	int 21h			; open
   304 00000072 72D8                    	jc .errorfile
   305 00000074 1F                      	pop ds			; restore => PSP
   306 00000075 50                      	push ax			; push into ?handle
   307                                  %endif
   308                                  
   309 00000076 BE8100                  	mov si, 81h
   310 00000079 31D2                    	xor dx, dx
   311 0000007B 31C0                    	xor ax, ax
   312                                  cmdline:
   313                                  .:
   314 0000007D AC                      	lodsb
   315 0000007E 3C09                    	cmp al, 9
   316 00000080 74FB                    	je .
   317 00000082 3C20                    	cmp al, 32
   318 00000084 74F7                    	je .
   319 00000086 3C0D                    	cmp al, 13
   320 00000088 744E                    	je .end
   321 0000008A 3C30                    	cmp al, '0'
   322 0000008C 721E                    	jb .notdigit
   323 0000008E 3C39                    	cmp al, '9'
   324 00000090 771A                    	ja .notdigit
   325                                  .digit:
   326 00000092 2C30                    	sub al, '0'
   327 00000094 89D1                    	mov cx, dx		; times 1
   328 00000096 01D2                    	add dx, dx
   329 00000098 722A                    	jc .invalid
   330 0000009A 01D2                    	add dx, dx		; times 4
   331 0000009C 7226                    	jc .invalid
   332 0000009E 01CA                    	add dx, cx		; times 5
   333 000000A0 7222                    	jc .invalid
   334 000000A2 01D2                    	add dx, dx		; times 10
   335 000000A4 721E                    	jc .invalid
   336 000000A6 01C2                    	add dx, ax		; add in low digit
   337 000000A8 721A                    	jc .invalid
   338 000000AA EBD1                    	jmp .
   339                                  
   340                                  .notdigit:
   341 000000AC 3C41                    	cmp al, 'A'
   342 000000AE 7419                    	je .a
   343 000000B0 3C61                    	cmp al, 'a'
   344 000000B2 7415                    	je .a
   345 000000B4 3C42                    	cmp al, 'B'
   346 000000B6 7416                    	je .b
   347 000000B8 3C62                    	cmp al, 'b'
   348 000000BA 7412                    	je .b
   349 000000BC 3C43                    	cmp al, 'C'
   350 000000BE 7413                    	je .c
   351 000000C0 3C63                    	cmp al, 'c'
   352 000000C2 740F                    	je .c
   353                                  .invalid:
   354 000000C4 BAFFFF                  	mov dx, -1		; invalid
   355 000000C7 EB0F                    	jmp .end
   356                                  
   357                                  .a:
   358 000000C9 80E77F                  	and bh, ~ 80h		; A mode. determine min alloc size
   359 000000CC EBAF                    	jmp .
   360                                  
   361                                  .b:
   362 000000CE 80CF80                  	or bh, 80h		; B mode. repeat depack, counter in command line
   363 000000D1 EBAA                    	jmp .
   364                                  
   365                                  .c:
   366 000000D3 80CF40                  	or bh, 40h		; C mode. how often would the counter be called
   367 000000D6 EBA5                    	jmp .
   368                                  
   369                                  .end:
   370                                  				; bx for ?whichtest
   371 000000D8 52                      	push dx			; for ?repetitions
   372                                    %endif
   373 000000D9 8CD2                    	mov dx, ss		; => after end of available space
   374 000000DB 8CC8                    	mov ax, cs
   375 000000DD 83C050                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   376 000000E0 8CCE                    	mov si, cs
   377 000000E2 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 000000E5 FC                      	cld
   394                                  %if _TEST_PROGRAM
   395                                   %ifn _RELOAD_XMS || _RELOAD_FILE
   396                                  	sub dx, ( (payload_end - payload) ) >> 4
   397                                  	jc .error
   398                                   %endif
   399 000000E6 B9D414                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   405 000000E9 29CA                    	sub dx, cx
   406 000000EB 7213                    	jc .error
   407 000000ED 39C2                    	cmp dx, ax
   408 000000EF 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 000000F1 56                      	push si			; preserve destination
   420 000000F2 E86101                  	call init0_movp		; move up payload + INIT1
   421 000000F5 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 000000F6 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 000000F8 058514                  	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 000000FB 31C9                    	xor cx, cx
   466 000000FD 50                      	push ax
   467 000000FE 51                      	push cx
   468 000000FF 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 00000100 89DF                    	mov di, bx		; whichtest
   477                                  
   478 00000102 0E                      	push cs
   479 00000103 1F                      	pop ds
   480 00000104 BA[0404]                	mov dx, init0_msg.error_stderr + 256
   481 00000107 B92500                  	mov cx, init0_msg.error_stderr.length
   482 0000010A BB0200                  	mov bx, 2
   483 0000010D B440                    	mov ah, 40h
   484 0000010F CD21                    	int 21h
   485                                  
   486 00000111 F7C70040                	test di, 4000h		; whichtest
   487 00000115 7408                    	jz @F
   488 00000117 BA[2904]                	mov dx, init0_msg.error_c_stdout + 256
   489 0000011A B90300                  	mov cx, init0_msg.error_c_stdout.length
   490 0000011D EB0A                    	jmp @FF
   491                                  @@:
   492 0000011F 85FF                    	test di, di		; whichtest
   493 00000121 780D                    	js @FF
   494 00000123 BA[2904]                	mov dx, init0_msg.error_stdout + 256
   495 00000126 B90300                  	mov cx, init0_msg.error_stdout.length
   496                                  @@:
   497 00000129 BB0100                  	mov bx, 1
   498 0000012C B440                    	mov ah, 40h
   499 0000012E CD21                    	int 21h
   500                                  @@:
   501 00000130 B8FF4C                  	mov ax, 4CFFh
   502 00000133 CD21                    	int 21h
   503                                  
   504                                  %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE
   505                                  init0_error_file:
   506 00000135 BA[D803]                	mov dx, init0_msg.error_stderr_file + 256
   507 00000138 B92C00                  	mov cx, init0_msg.error_stderr_file.length
   508 0000013B 0E                      	push cs
   509 0000013C 1F                      	pop ds
   510 0000013D BB0200                  	mov bx, 2
   511 00000140 B440                    	mov ah, 40h
   512 00000142 CD21                    	int 21h
   513                                  
   514 00000144 BA[2904]                	mov dx, init0_msg.error_stdout + 256
   515 00000147 B90300                  	mov cx, init0_msg.error_stdout.length
   516 0000014A BB0100                  	mov bx, 1
   517 0000014D B440                    	mov ah, 40h
   518 0000014F CD21                    	int 21h
   519 00000151 B8FF4C                  	mov ax, 4CFFh
   520 00000154 CD21                    	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 00000156 90<rep Ah>              	align 16
   542                                  lcfg:
   543 00000160 EB1E                    .:		jmp strict short .end
   544 00000162 6C434647                lcfgoption 2,,	db "lCFG"
   545 00000166 3030                    lcfgoption 6,,	db "00"
   546 00000168 FCFF070000000000        lcfgoption 8,,	dq .inuse
   547                                   %if _PROGRESS && _PROGRESSMULTI
   548                                    %if _IMAGE_EXE
   549 00000170 00                      lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP
   550                                    %endif
   551                                    %if _DEVICE
   552 00000171 00                      lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE
   553                                    %endif
   554                                    %if _BOOTLDR
   555 00000172 01                      lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT
   556                                    %endif
   557                                   %endif
   558                                  
   559                                  %ifnidn _LCFG_CFG, ""
   560                                   %include _LCFG_CFG
   561                                  %endif
   562                                  
   563 00000173 00<rep Dh>              lcfgoption 32,,
   564                                  .end:
   565                                  .size: equ .end - .
   566                                  .inuse equ LCFGINUSE
   567                                  %endif
   568                                  
   569                                  
   570                                  %if _DEVICE
   571                                  device_entrypoint:
   572                                  %if _TEST_PROGRAM
   573                                  @@:
   574 00000180 CC                      	int3
   575 00000181 FB                      	sti
   576 00000182 F4                      	hlt
   577 00000183 EBFB                    	jmp @B
   578                                  %endif
   579 00000185 26807F0200              	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   580 0000018A 7407                    	je @F
   581                                  
   582 0000018C 26C747030381            	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   583 00000192 CB                      	retf
   584                                  
   585                                  @@:
   586 00000193 2E830E[0000]FF          	or word [cs:device_header.next], -1
   587 00000199 0E                      	push cs
   588 0000019A 2EFF36[0600]            	push word [cs:device_header.strategy]
   589                                  					; -> far return to payload's strategy
   590 0000019F 55                      	push bp
   591 000001A0 1E                      	push ds
   592 000001A1 56                      	push si
   593 000001A2 57                      	push di
   594 000001A3 52                      	push dx
   595 000001A4 51                      	push cx
   596 000001A5 50                      	push ax
   597 000001A6 53                      	push bx
   598 000001A7 06                      	push es
   599                                  
   600 000001A8 268B570E                	mov dx, word [es:bx + 14]
   601 000001AC B104                    	mov cl, 4
   602 000001AE D3EA                    	shr dx, cl		; = how many full paragraphs (rounded down)
   603 000001B0 26035710                	add dx, word [es:bx + 14 + 2]
   604                                  				; ax => behind end
   605                                  
   606 000001B4 8CCF                    	mov di, cs
   607                                  image_size: equ  ( 		+ (init0_end - init0_start) 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   613 000001B6 81C7C514                	add di, image_size >> 4		; di => end of image
   614                                  
   615 000001BA 39FA                    	cmp dx, di			; enough memory to hold all of us ?
   616 000001BC 720E                    	jb @F				; no -->
   617                                  				; yes
   618                                  .have_some_memory:
   619                                  				; dx => after end of memory
   620 000001BE BB0200                  	mov bx, 2		; device mode
   621 000001C1 50                      	push ax
   622 000001C2 8CC8                    	mov ax, cs
   623 000001C4 83C040                  	add ax, (init0_end - init0_start) >> 4
   624 000001C7 8CCE                    	mov si, cs		; => destination
   625 000001C9 E919FF                  	jmp init0_common
   626                                  
   627                                  
   628                                  @@:
   629 000001CC 0E                      	push cs
   630 000001CD 1F                      	pop ds
   631 000001CE BA[0D02]                	mov dx, .msg_no_memory
   632 000001D1 B409                    	mov ah, 09h
   633 000001D3 CD21                    	int 21h
   634                                  
   635 000001D5 B80030                  	mov ax, 3000h
   636 000001D8 CD21                    	int 21h
   637 000001DA 3C05                    	cmp al, 5
   638 000001DC 7307                    	jae @F
   639 000001DE BA[2C02]                	mov dx, .msg_dos_below_5
   640 000001E1 B409                    	mov ah, 09h
   641 000001E3 CD21                    	int 21h
   642                                  @@:
   643                                  
   644 000001E5 BA[5302]                	mov dx, .msg_linebreak
   645 000001E8 B409                    	mov ah, 09h
   646 000001EA CD21                    	int 21h
   647                                  
   648                                  		; tear down the stack frame and modify the request header
   649 000001EC 07                      	pop es
   650 000001ED 5B                      	pop bx
   651 000001EE 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   652 000001F4 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   653 000001F9 268C4F10                	mov word [es:bx + 14 + 2], cs
   654 000001FD 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   655 00000202 58                      	pop ax
   656 00000203 59                      	pop cx
   657 00000204 5A                      	pop dx
   658 00000205 5F                      	pop di
   659 00000206 5E                      	pop si
   660 00000207 1F                      	pop ds
   661 00000208 5D                      	pop bp
   662 00000209 83C404                  	add sp, 4		; discard far return to payload's strategy
   663 0000020C CB                      	retf			; return to DOS
   664                                  
   665                                  
   666 0000020D 4C6F6164206572726F-     .msg_no_memory:		ascic "Load error: Not enough memory."
   666 00000216 723A204E6F7420656E-
   666 0000021F 6F756768206D656D6F-
   666 00000228 72792E24           
   667 0000022C 204E6F74653A20444F-     .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   667 00000235 53206D757374206265-
   667 0000023E 206174206C65617374-
   667 00000247 2076657273696F6E20-
   667 00000250 352E24             
   668 00000253 0D0A24                  .msg_linebreak:		ascic 13,10
   669                                  %endif
   670                                  
   671                                  
   672                                  		; Move paragraphs
   673                                  		;
   674                                  		; INP:	ax => source
   675                                  		;	dx => destination
   676                                  		;	cx = number of paragraphs
   677                                  		; CHG:	cx, ds, si, es, di
   678                                  		; OUT:	ax and dx unchanged
   679                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   680                                  		;	Do not provide a wrapped/HMA source or destination!
   681                                  init0_movp:
   682 00000256 39D0                    	cmp ax, dx		; source above destination ?
   683 00000258 770A                    	ja .up			; yes, move up (forwards) -->
   684 0000025A 747B                    	je .return		; same, no need to move -->
   685 0000025C 50                      	push ax
   686 0000025D 01C8                    	add ax, cx		; (expected not to carry)
   687 0000025F 39D0                    	cmp ax, dx		; end of source is above destination ?
   688 00000261 58                      	pop ax
   689 00000262 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 00000264 50                      	push ax
   695 00000265 52                      	push dx
   696                                  .uploop:
   697 00000266 8ED8                    	mov ds, ax
   698 00000268 8EC2                    	mov es, dx
   699 0000026A 31FF                    	xor di, di
   700 0000026C 31F6                    	xor si, si		; -> start of segment
   701 0000026E 81E90010                	sub cx, 1000h		; 64 KiB left ?
   702 00000272 7610                    	jbe .uplast		; no -->
   703 00000274 51                      	push cx
   704 00000275 B90080                  	mov cx, 10000h /2
   705 00000278 F3A5                    	rep movsw		; move 64 KiB
   706 0000027A 59                      	pop cx
   707 0000027B 050010                  	add ax, 1000h
   708 0000027E 81C20010                	add dx, 1000h		; -> next segment
   709 00000282 EBE2                    	jmp short .uploop	; proceed for more -->
   710                                  .uplast:
   711 00000284 81C10010                	add cx, 1000h		; restore counter
   712 00000288 D1E1                    	shl cx, 1
   713 0000028A D1E1                    	shl cx, 1
   714 0000028C D1E1                    	shl cx, 1		; *8, paragraphs to words
   715 0000028E F3A5                    	rep movsw		; move last part
   716 00000290 5A                      	pop dx
   717 00000291 58                      	pop ax
   718 00000292 EB43                    	jmp short .return
   719                                  
   720                                  .down:
   721 00000294 FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   722                                  .dnloop:
   723 00000295 81E90010                	sub cx, 1000h		; 64 KiB left ?
   724 00000299 761A                    	jbe .dnlast		; no -->
   725 0000029B 50                      	push ax
   726 0000029C 52                      	push dx
   727 0000029D 01C8                    	add ax, cx
   728 0000029F 01CA                    	add dx, cx
   729 000002A1 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   730 000002A3 8EC2                    	mov es, dx
   731 000002A5 5A                      	pop dx
   732 000002A6 58                      	pop ax
   733 000002A7 BFFEFF                  	mov di, -2
   734 000002AA 89FE                    	mov si, di		; moved from last word down
   735 000002AC 51                      	push cx
   736 000002AD B90080                  	mov cx, 10000h /2
   737 000002B0 F3A5                    	rep movsw		; move 64 KiB
   738 000002B2 59                      	pop cx
   739 000002B3 EBE0                    	jmp short .dnloop	; proceed for more -->
   740                                  .dnlast:
   741 000002B5 81C10010                	add cx, 1000h		; restore counter
   742 000002B9 D1E1                    	shl cx, 1
   743 000002BB D1E1                    	shl cx, 1
   744 000002BD D1E1                    	shl cx, 1		; *8, paragraphs to words
   745 000002BF 89CF                    	mov di, cx
   746 000002C1 4F                      	dec di
   747 000002C2 D1E7                    	shl di, 1		; words to offset, -> last word
   748 000002C4 89FE                    	mov si, di
   749 000002C6 8ED8                    	mov ds, ax
   750 000002C8 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 000002CA E308                    	jcxz @FF
   791 000002CC 83F914                  	cmp cx, 20
   792 000002CF 7703                    	ja @FF
   793                                  @@:
   794 000002D1 A5                      	movsw
   795 000002D2 E2FD                    	loop @B
   796                                  @@:
   797                                  %endif
   798 000002D4 F3A5                    	rep movsw		; move first part
   799 000002D6 FC                      	cld
   800                                  .return:
   801 000002D7 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 05CE13                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   819                                  
   820                                  %if _LCFG && _PASSLCFG
   821                                   %if (_IMAGE_EXE || _DEVICE)
   822                                  	mov cx, si		; preserve si
   823                                   %endif
   824                                  	pop si
   825                                  	pop ds			; -> lCFG block
   826                                  	mov es, ax
   827                                  	mov di, transfer_lcfg_block
   828                                  				; -> destination
   829                                   %if (_IMAGE_EXE || _DEVICE)
   830                                  	push cx
   831                                   %endif
   832                                  	push di
   833                                  	mov cx, words(lcfg.size)
   834                                  	rep movsw		; cx = 0
   835                                  	pop di			; es:di -> relocated lCFG block, same difference
   836                                   %if (_IMAGE_EXE || _DEVICE)
   837                                  	pop si			; preserve si
   838                                   %endif
   839                                  %elif _LCFG
   840 00000003 5F                      	pop di
   841 00000004 07                      	pop es			; es:di -> (original) lCFG block
   842                                  %endif
   843                                  
   844 00000005 50                      	push ax
   845 00000006 51                      	push cx			; -> far return address to init1_start
   846                                  
   847                                  %if _PROGRESS && _PROGRESSMULTI
   848                                   %if (_IMAGE_EXE || _DEVICE)
   849 00000007 56                      	push si
   850 00000008 53                      	push bx
   851                                   %endif
   852                                   %if _BOOTLDR
   853                                    %if _LCFG
   854 00000009 31C0                    	xor ax, ax
   855 0000000B 268A4512                	mov al, byte [es:di + lcfg.progress_boot - lcfg]
   856 0000000F 97                      	xchg di, ax		; di = boot default progress
   857                                  				; es:ax -> lCFG block
   858                                    %else			; _LCFG
   859                                  	mov di, _PROGRESSDEFAULTBOOT
   860                                    %endif		; _LCFG
   861                                   %endif			; _BOOTLDR
   862                                   %if (_IMAGE_EXE || _DEVICE)
   863                                    %if _BOOTLDR
   864 00000010 85DB                    	test bx, bx
   865 00000012 7503E9AC00              	jz .default
   866                                    %endif		; _BOOTLDR
   867                                    %if _LCFG
   868 00000017 06                      	push es
   869                                     %if _BOOTLDR
   870 00000018 50                      	push ax			; -> lCFG block
   871                                     %else		; _BOOTLDR
   872                                  	push di
   873                                     %endif		; _BOOTLDR
   874                                    %endif		; _LCFG
   875                                    %if _PROGRESSVAR
   876 00000019 B451                    	mov ah, 51h
   877 0000001B CD21                    	int 21h
   878                                  @@:
   879 0000001D 8EDB                    	mov ds, bx
   880 0000001F A12C00                  	mov ax, word [2Ch]
   881 00000022 85C0                    	test ax, ax
   882 00000024 7510                    	jnz .gotenv
   883 00000026 A11600                  	mov ax, word [16h]
   884 00000029 40                      	inc ax
   885 0000002A 7469                    	jz .default_nonboot
   886 0000002C 48                      	dec ax
   887 0000002D 7466                    	jz .default_nonboot
   888 0000002F 39C3                    	cmp bx, ax
   889 00000031 7462                    	je .default_nonboot
   890 00000033 93                      	xchg bx, ax
   891 00000034 EBE7                    	jmp @B
   892                                  
   893                                  .gotenv:
   894 00000036 0E                      	push cs
   895 00000037 1F                      	pop ds				; => cs
   896 00000038 8EC0                    	mov es, ax			; => environment
   897                                   %ifnidni _PROGRESSVARNAME, ""
   898 0000003A BB[F000]                	mov bx, progressvarname1
   899 0000003D E80C00                  	call .findenv
   900 00000040 732E                    	jnc .foundenv			; match -->
   901 00000042 BB[0001]                	mov bx, progressvarname2
   902                                   %endif
   903 00000045 E80400                  	call .findenv
   904 00000048 7326                    	jnc .foundenv			; match -->
   905 0000004A EB49                    	jmp .default_nonboot
   906                                  
   907                                  .findenv:
   908 0000004C 31FF                    	xor di, di
   909                                  @@:
   910                                   %ifnidni _PROGRESSVARNAME, ""
   911 0000004E 89DE                    	mov si, bx			; -> variable name
   912                                   %else
   913                                  	mov si, progressvarname2	; -> variable name
   914                                   %endif
   915 00000050 31C0                    	xor ax, ax
   916 00000052 AC                      	lodsb				; get length
   917 00000053 91                      	xchg cx, ax			; cx = length
   918 00000054 57                      	push di
   919 00000055 F3A6                    	repe cmpsb			; match ?
   920 00000057 7415                    	je .findret_pop			; (NC) yes -->
   921 00000059 5F                      	pop di
   922 0000005A B90080                  	mov cx, 8000h			; maximum env size
   923 0000005D 29F9                    	sub cx, di			; any left ?
   924 0000005F 760B                    	jbe .findret_CY			; no -->
   925 00000061 B000                    	mov al, 0
   926 00000063 F2AE                    	repne scasb			; find next NUL
   927 00000065 7505                    	jne .findret_CY
   928 00000067 263805                  	cmp byte [es:di], al		; double NUL ?
   929 0000006A 75E2                    	jne @B				; no, loop -->
   930                                  .findret_CY:
   931 0000006C F9                      	stc				; not found
   932 0000006D C3                      	retn
   933                                  
   934                                  .findret_pop:
   935 0000006E 59                      	pop cx
   936 0000006F C3                      	retn
   937                                  
   938                                  .foundenv:
   939                                  %if _LCFG
   940 00000070 5E                      	pop si
   941 00000071 5E                      	pop si				; discard far pointer to lCFG
   942                                  %endif
   943 00000072 89FE                    	mov si, di			; es:si -> var content
   944 00000074 31FF                    	xor di, di			; = 0
   945 00000076 31C0                    	xor ax, ax			; ah = 0
   946                                  @@:
   947 00000078 26AC                    	es lodsb			; next candidate digit
   948 0000007A 2C30                    	sub al, '0'			; digit ?
   949 0000007C 7212                    	jb @F				; no -->
   950 0000007E 3C09                    	cmp al, 9
   951 00000080 770E                    	ja @F				; no -->
   952 00000082 01FF                    	add di, di			; times 2
   953 00000084 89FB                    	mov bx, di
   954 00000086 01FF                    	add di, di			; times 4
   955 00000088 01FF                    	add di, di			; times 8
   956 0000008A 01DF                    	add di, bx			; times 8 + times 2 = times 10
   957 0000008C 01C7                    	add di, ax			; add in next digit
   958 0000008E EBE8                    	jmp @B				; and loop
   959                                  
   960                                  @@:
   961 00000090 83E71F                  	and di, 31			; mask to low 5 bits
   962 00000093 EB10                    	jmp @F
   963                                    %endif	; _PROGRESSVAR
   964                                  
   965                                  .default_nonboot:
   966                                  %if _LCFG
   967 00000095 5F                      	pop di
   968 00000096 07                      	pop es			; -> lCFG block
   969 00000097 5B                      	pop bx			; = 1 if app, = 2 if device
   970 00000098 53                      	push bx
   971 00000099 268B4510                	mov ax, word [es:di + lcfg.progress_app - lcfg]
   972                                   %if _DEVICE
   973                                    %if lcfg.progress_app + 1 != lcfg.progress_dev
   974                                     %error Unexpected layout
   975                                    %endif
   976                                  				; al = app, ah = device
   977 0000009D 4B                      	dec bx
   978 0000009E 7402                    	jz .default_app
   979 000000A0 86C4                    	xchg al, ah		; al = device
   980                                  .default_app:
   981                                   %endif			; _DEVICE
   982 000000A2 B400                    	mov ah, 0		; ax = default
   983 000000A4 97                      	xchg di, ax		; di = default
   984                                  %else			; _LCFG
   985                                  	mov di, _PROGRESSDEFAULT
   986                                  %endif			; _LCFG
   987                                  @@:
   988 000000A5 F7C71000                	test di, 16
   989 000000A9 7405                    	jz @F
   990 000000AB 83E7EF                  	and di, ~16
   991 000000AE EB13                    	jmp .outputdevice	; if 16 set skip device check
   992                                  @@:
   993 000000B0 52                      	push dx
   994 000000B1 B80044                  	mov ax, 4400h		; IOCTL get device information
   995 000000B4 BB0100                  	mov bx, 1		; StdOut
   996 000000B7 B283                    	mov dl, 83h		; default if 21.4400 fails
   997 000000B9 CD21                    	int 21h
   998 000000BB F6C280                  	test dl, 80h
   999 000000BE 5A                      	pop dx
  1000 000000BF 7502                    	jnz .outputdevice
  1001 000000C1 31FF                    	xor di, di		; stdout is a file: force no progress marker
  1002                                  .outputdevice:
  1003                                   %endif			; (_IMAGE_EXE || _DEVICE)
  1004                                  
  1005                                  .default:
  1006                                   %if (_IMAGE_EXE || _DEVICE)
  1007 000000C3 5B                      	pop bx
  1008 000000C4 5E                      	pop si
  1009                                   %endif
  1010 000000C5 83FF05                  	cmp di, step_progress_table.amount
  1011                                  					; valid ?
  1012 000000C8 7202                    	jb @F				; yes -->
  1013 000000CA 31FF                    	xor di, di			; disable
  1014                                  @@:
  1015 000000CC D1E7                    	shl di, 1			; = word index
  1016 000000CE 59                      	pop cx				; = 0
  1017 000000CF 1F                      	pop ds				; ds => INIT1
  1018                                  
  1019 000000D0 2E8B85[E600]            	mov ax, word [cs:step_progress_table + di]
  1020                                  					; ax = rel16 for step progress handler
  1021 000000D5 1E                      	push ds
  1022 000000D6 51                      	push cx				; -> init1_start
  1023 000000D7 A3[BA00]                	mov word [step_progress.handler], ax
  1024                                  					; patch it
  1025                                  
  1026 000000DA 83FF04                  	cmp di, 2 * 2			; none or dots ?
  1027 000000DD 7305                    	jae @F				; no, skip -->
  1028 000000DF C606[0600]A9            	mov byte [..@empty_step_progress], __TEST_IMM16
  1029                                  					; for none and dots do not call here
  1030                                  @@:
  1031                                  %endif			;  _PROGRESS && _PROGRESSMULTI
  1032 000000E4 CB                      	retf
  1033                                  %endif
  1034                                  
  1035                                  %if _PROGRESS && _PROGRESSMULTI
  1036 000000E5 00                      		align 2, db 0
  1037                                  step_progress_table:
  1038                                  .:
  1039 000000E6 1600                    		dw step_progress.0_step - step_progress.base
  1040 000000E8 3B00                    		dw step_progress.1_step - step_progress.base
  1041 000000EA 0000                    		dw step_progress.2_step - step_progress.base
  1042 000000EC 4100                    		dw step_progress.3_step - step_progress.base
  1043 000000EE 8600                    		dw step_progress.4_step - step_progress.base
  1044                                  .amount equ ($ - .) / 2
  1045                                  
  1046                                   %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE)
  1047                                    %ifnidni _PROGRESSVARNAME, ""
  1048 000000F0 0F4C44454255475052-     progressvarname1:	counted _PROGRESSVARNAME, '='
  1048 000000F9 4F47524553533D     
  1049                                    %endif
  1050 00000100 0D4C444F5350524F47-     progressvarname2:	counted "LDOSPROGRESS="
  1050 00000109 524553533D         
  1051                                   %endif
  1052                                  %endif
  1053                                  
  1054 0000010E 90<rep 2h>              	align 16
  1055                                  init0b_end:
  1056                                  
  1057                                  
  1058                                  	addsection PAYLOAD, align=16 follows=INIT0B
  1059                                  payload:
  1060 00000000 <bin 13BC3h>            	incbin _PAYLOAD_FILE
  1061                                  .end:
  1062 00013BC3 26<rep Dh>              	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 B9C33B                  	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 E87C04                  	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 00000023 F6C302                  	test bl, 2
  1188 00000026 7411                    	jz .jmp_exe_or_kernel_mode
  1189                                  
  1190                                  .jmp_device_mode:
  1191 00000028 8EDE                    	mov ds, si
  1192 0000002A 830E[0000]FF            	or word [device_header.next], -1
  1193                                  %if _LCFG && _PASSLCFG
  1194                                  	mov word [device_header.pass_lcfg], transfer_lcfg_block
  1195                                  	mov word [device_header.pass_lcfg + 2], cs
  1196                                  %endif
  1197 0000002F 07                      	pop es
  1198 00000030 5B                      	pop bx
  1199 00000031 58                      	pop ax
  1200 00000032 59                      	pop cx
  1201 00000033 5A                      	pop dx
  1202 00000034 5F                      	pop di
  1203 00000035 5E                      	pop si
  1204 00000036 1F                      	pop ds
  1205 00000037 5D                      	pop bp
  1206 00000038 CB                      	retf			; transfer to payload strategy entrypoint
  1207                                  				; still on stack: far return address to DOS
  1208                                  
  1209                                  .jmp_exe_or_kernel_mode:
  1210                                  %endif
  1211                                  
  1212                                  %if _IMAGE_EXE
  1213 00000039 F6C301                  	test bl, 1
  1214 0000003C 7410                    	jz .jmp_kernel_mode
  1215                                  
  1216                                  .jmp_exe_mode:
  1217                                  %if ! _IMAGE_EXE_AUTO_STACK
  1218                                  	mov cx, cs
  1219                                  	lea dx, [si + _IMAGE_EXE_SS]
  1220                                  	push dx			; stack = relocated ss value
  1221                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
  1222                                  	cmp cx, dx		; INIT1 code is above intended stack ?
  1223                                  	jae @F			; yes -->
  1224                                  
  1225                                  	lframe
  1226                                  	lenter
  1227                                  	lvar	word, exemode
  1228                                  	 push bx
  1229                                   %if ?exemode != -2
  1230                                    %error exemode variable must be directly below bp
  1231                                   %endif
  1232                                  	mov bx, -1		; unimplemented, return error
  1233                                  	jmp error
  1234                                  	lleave ctx
  1235                                  @@:
  1236                                  	cli
  1237                                  	pop ss			; = relocated ss value
  1238                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
  1239                                  	sti
  1240                                  %endif
  1241                                  
  1242 0000003E 31C9                    	xor cx, cx
  1243 00000040 51                      	push cx			; put zero on top of stack
  1244                                  
  1245                                  %if _IMAGE_EXE_IP < 256
  1246                                  	mov cl, _IMAGE_EXE_IP
  1247                                  %elif (_IMAGE_EXE_IP & 255) == 0
  1248                                  	mov ch, _IMAGE_EXE_IP >> 8
  1249                                  %else
  1250 00000041 B94001                  	mov cx, _IMAGE_EXE_IP
  1251                                  %endif
  1252                                  
  1253                                  %if _IMAGE_EXE_CS == -16
  1254 00000044 83C6F0                  	add si, -16
  1255 00000047 8EDE                    	mov ds, si
  1256 00000049 8EC6                    	mov es, si
  1257                                  %else
  1258                                  	lea dx, [si - 10h]	; => PSP
  1259                                  	mov ds, dx
  1260                                  	mov es, dx		; ds = es => PSP
  1261                                   %if _IMAGE_EXE_CS
  1262                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
  1263                                   %endif
  1264                                  %endif
  1265 0000004B 56                      	push si
  1266 0000004C 51                      	push cx
  1267                                  %if _LCFG && _PASSLCFG
  1268                                  	mov di, transfer_lcfg_block
  1269                                  	mov cx, cs
  1270                                  %endif
  1271 0000004D CB                      	retf			; jump to EXE mode of image
  1272                                  
  1273                                  %endif
  1274                                  .jmp_kernel_mode:
  1275                                  %if _LCFG && _PASSLCFG
  1276                                  	mov di, transfer_lcfg_block
  1277                                  	mov cx, cs
  1278                                  %endif
  1279 0000004E EA20006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
  1280                                  
  1281                                  
  1282                                  %if _TEST_PROGRAM
  1283                                  disp_al_counter:
  1284 00000053 2EFF06[5900]            	inc word [cs:init1_c_mode_counter]	; 5 bytes
  1285 00000058 C3                      	retn					; 1 byte
  1286                                  
  1287 00000059 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 0000005B F646FE02                	test byte [bp - 2], 2
  1320 0000005F 7435                    	jz .exit_app_or_kernel
  1321                                  
  1322 00000061 5E                      	pop si				; => device segment
  1323 00000062 5B                      	pop bx				; mode word
  1324 00000063 5D                      	pop bp
  1325 00000064 58                      	pop ax
  1326 00000065 8EC6                    	mov es, si
  1327 00000067 31FF                    	xor di, di			; -> device header
  1328 00000069 0E                      	 push cs
  1329 0000006A 1F                      	 pop ds
  1330 0000006B BE[0002]                	mov si, device_header_copy	; -> to reset header
  1331 0000006E B91100                  	mov cx, words(device_header_copy.length)
  1332 00000071 F3A5                    	rep movsw		; overwrite device header with default
  1333                                  				;  (reset to a valid state after unsuccessful
  1334                                  				;  decompression, which may have partially
  1335                                  				;  written the header already)
  1336 00000073 06                      	 push es
  1337 00000074 1F                      	 pop ds				; -> device segment
  1338 00000075 07                      	pop es
  1339 00000076 5B                      	pop bx
  1340 00000077 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1341 0000007D 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
  1342 00000082 268C5F10                	mov word [es:bx + 14 + 2], ds
  1343 00000086 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
  1344 0000008B 58                      	pop ax
  1345 0000008C 59                      	pop cx
  1346 0000008D 5A                      	pop dx
  1347 0000008E 5F                      	pop di
  1348 0000008F 5E                      	pop si
  1349 00000090 1F                      	pop ds
  1350 00000091 5D                      	pop bp
  1351 00000092 83C404                  	add sp, 4		; discard far return to payload's strategy
  1352 00000095 CB                      	retf			; return to DOS
  1353                                  
  1354                                  
  1355                                  .exit_app_or_kernel:
  1356                                  %endif
  1357                                  
  1358                                  %if _IMAGE_EXE
  1359                                  %if _BOOTLDR
  1360 00000096 F646FE01                	test byte [bp - 2], 1
  1361 0000009A 7405                    	jz .exit_kernel_mode
  1362                                  %endif
  1363                                  
  1364 0000009C B87F4C                  	mov ax, 4C7Fh
  1365 0000009F CD21                    	int 21h
  1366                                  
  1367                                  .exit_kernel_mode:
  1368                                  %endif
  1369                                  %if _BOOTLDR
  1370 000000A1 31C0                    	xor ax, ax
  1371 000000A3 CD16                    	int 16h
  1372 000000A5 CD19                    	int 19h
  1373                                  %endif
  1374                                  
  1375                                  
  1376                                  %if _PROGRESS
  1377                                  step_progress:
  1378 000000A7 F9                      	stc
  1379                                  .CF:
  1380 000000A8 53                      	push bx
  1381 000000A9 51                      	push cx
  1382 000000AA 52                      	push dx
  1383 000000AB 1E                      	push ds
  1384 000000AC 56                      	push si
  1385 000000AD 57                      	push di
  1386 000000AE 50                      	push ax
  1387                                  
  1388 000000AF 0E                      	push cs
  1389 000000B0 1F                      	pop ds
  1390                                  
  1391 000000B1 8316[E201]00            	adc word [.counter], 0
  1392 000000B6 A1[E201]                	mov ax, word [.counter]
  1393                                  
  1394                                   %if _PROGRESSMULTI
  1395                                    %if _IMAGE_EXE || _DEVICE
  1396                                     %assign defaultprogresshandler _PROGRESSDEFAULT
  1397                                    %else
  1398                                     %assign defaultprogresshandler _PROGRESSDEFAULTBOOT
  1399                                    %endif
  1400 000000B9 E91600                  	jmp strict near . %+ defaultprogresshandler %+ _step
  1401                                  .handler: equ $ - 2		; SMC, patched to dispatch to handler
  1402                                  .base:
  1403                                   %endif
  1404                                  
  1405                                  .2_step:
  1406 000000BC BAE803                  	mov dx, 1000
  1407 000000BF F7E2                    	mul dx			; dx:ax = counter times 1000
  1408                                  %if _PROGRESSAMOUNT
  1409 000000C1 B90100                  	mov cx, _PROGRESSAMOUNT
  1410 000000C4 F7F1                    	div cx			; ax = 0..1000
  1411                                  %else
  1412                                   %warning Progress amount is zero
  1413                                  	mov ax, 1
  1414                                  %endif
  1415                                  
  1416                                  %if 0
  1417                                  	cmp word [.display], ax
  1418                                  	je .ret
  1419                                  	mov word [.display], ax
  1420                                  %endif
  1421 000000C6 BE[EB01]                	mov si, .message_number_end - 1
  1422 000000C9 E80E00                  	call .format_percentage
  1423                                  
  1424 000000CC BE[E401]                	mov si, .message
  1425 000000CF E85201                  	call disp_error
  1426                                  
  1427                                  .ret:
  1428 000000D2 58                      	pop ax
  1429                                  .ret_ax:
  1430 000000D3 5F                      	pop di
  1431 000000D4 5E                      	pop si
  1432 000000D5 1F                      	pop ds
  1433 000000D6 5A                      	pop dx
  1434 000000D7 59                      	pop cx
  1435 000000D8 5B                      	pop bx
  1436                                  .retn:
  1437 000000D9 C3                      	retn
  1438                                  
  1439                                  
  1440                                  .format_percentage:
  1441 000000DA BB0200                  	mov bx, 2		; skip dot
  1442                                  
  1443 000000DD B90A00                  	mov cx, 10		; base
  1444                                  @@:
  1445 000000E0 31D2                    	xor dx, dx		; dx:ax = current number
  1446 000000E2 F7F1                    	div cx			; dl = remainder, ax = next number
  1447 000000E4 80C230                  	add dl, '0'		; make decit
  1448 000000E7 8814                    	mov byte [si], dl	; store
  1449 000000E9 29DE                    	sub si, bx		; -> next digit slot
  1450 000000EB 80FB02                  	cmp bl, 2		; did we just store fractional ?
  1451 000000EE B301                    	mov bl, 1		; ! next iteration do not skip dot
  1452 000000F0 74EE                    	je @B			; yes, loop always -->
  1453 000000F2 85C0                    	test ax, ax		; nonzero left ?
  1454 000000F4 75EA                    	jnz @B			; yes, loop if so -->
  1455 000000F6 C3                      	retn
  1456                                  
  1457                                  
  1458                                   %if _PROGRESSMULTI
  1459                                  .0_step: equ .ret
  1460                                  
  1461                                  .1_step:
  1462 000000F7 58                      	pop ax
  1463 000000F8 E83701                  	call disp_al
  1464 000000FB EBD6                    	jmp .ret_ax
  1465                                  
  1466                                  .3_step:
  1467 000000FD BB4B00                  	mov bx, 80 - 1 - 4
  1468 00000100 F7E3                    	mul bx			; dx:ax = counter times 75
  1469                                  %if _PROGRESSAMOUNT
  1470 00000102 B90100                  	mov cx, _PROGRESSAMOUNT
  1471 00000105 F7F1                    	div cx			; ax = 0..75
  1472                                  %else
  1473                                   %warning Progress amount is zero
  1474                                  	mov ax, 1
  1475                                  %endif
  1476                                  
  1477 00000107 3906[E001]              	cmp word [.display], ax
  1478 0000010B 74C5                    	je .ret
  1479 0000010D A3[E001]                	mov word [.display], ax
  1480                                  
  1481 00000110 50                      	push ax
  1482 00000111 91                      	xchg cx, ax
  1483 00000112 B00D                    	mov al, 13
  1484 00000114 E81B01                  	call disp_al
  1485 00000117 B05B                    	mov al, '['
  1486 00000119 E81601                  	call disp_al
  1487 0000011C B020                    	mov al, 32
  1488 0000011E E81101                  	call disp_al
  1489                                  
  1490 00000121 B023                    	mov al, '#'
  1491 00000123 E305                    	jcxz @FF
  1492                                  @@:
  1493 00000125 E80A01                  	call disp_al
  1494 00000128 E2FB                    	loop @B
  1495                                  @@:
  1496                                  
  1497 0000012A B020                    	mov al, 32
  1498 0000012C 59                      	pop cx
  1499 0000012D 29CB                    	sub bx, cx
  1500 0000012F 7607                    	jbe @FF
  1501 00000131 89D9                    	mov cx, bx
  1502                                  @@:
  1503 00000133 E8FC00                  	call disp_al
  1504 00000136 E2FB                    	loop @B
  1505                                  @@:
  1506                                  
  1507                                  .m4done:
  1508 00000138 E8F700                  	call disp_al
  1509 0000013B B05D                    	mov al, ']'
  1510 0000013D E8F200                  	call disp_al
  1511 00000140 EB90                    	jmp .ret
  1512                                  
  1513                                  
  1514                                  .4_step:
  1515 00000142 50                      	push ax
  1516                                  
  1517 00000143 BAE803                  	mov dx, 1000
  1518 00000146 F7E2                    	mul dx			; dx:ax = counter times 1000
  1519                                  %if _PROGRESSAMOUNT
  1520 00000148 B90100                  	mov cx, _PROGRESSAMOUNT
  1521 0000014B F7F1                    	div cx			; ax = 0..1000
  1522                                  %else
  1523                                   %warning Progress amount is zero
  1524                                  	mov ax, 1
  1525                                  %endif
  1526                                  
  1527 0000014D BE[F501]                	mov si, .message_4_number_end - 1
  1528 00000150 E887FF                  	call .format_percentage
  1529                                  
  1530 00000153 58                      	pop ax
  1531 00000154 BB4B00                  	mov bx, 80 - 1 - 4
  1532 00000157 F7E3                    	mul bx			; dx:ax = counter times 75
  1533                                  %if _PROGRESSAMOUNT
  1534 00000159 B90100                  	mov cx, _PROGRESSAMOUNT
  1535 0000015C F7F1                    	div cx			; ax = 0..75
  1536                                  %else
  1537                                   %warning Progress amount is zero
  1538                                  	mov ax, 1
  1539                                  %endif
  1540                                  
  1541 0000015E 50                      	push ax
  1542 0000015F 91                      	xchg cx, ax
  1543 00000160 B00D                    	mov al, 13
  1544 00000162 E8CD00                  	call disp_al
  1545 00000165 B05B                    	mov al, '['
  1546 00000167 E8C800                  	call disp_al
  1547 0000016A B020                    	mov al, 32
  1548 0000016C E8C300                  	call disp_al
  1549                                  
  1550 0000016F 31FF                    	xor di, di
  1551 00000171 BA2200                  	mov dx, (80 - 1 - 4 - .message_4_length) / 2
  1552 00000174 803E[F101]20            	cmp byte [.message_4_number], 32
  1553 00000179 7401                    	je @F
  1554 0000017B 47                      	inc di
  1555                                  @@:
  1556 0000017C 29FA                    	sub dx, di
  1557                                  
  1558 0000017E B023                    	mov al, '#'
  1559 00000180 E306                    	jcxz @FF
  1560                                  @@:
  1561 00000182 E8AD00                  	call disp_al
  1562 00000185 4A                      	dec dx
  1563 00000186 E0FA                    	loopnz @B
  1564                                  @@:
  1565                                  
  1566 00000188 85D2                    	test dx, dx
  1567 0000018A 752E                    	jnz .notyetm4
  1568                                  
  1569 0000018C BE[F101]                	mov si, .message_4
  1570 0000018F 29FE                    	sub si, di
  1571 00000191 E89000                  	call disp_error
  1572                                  
  1573 00000194 29F9                    	sub cx, di
  1574 00000196 760E                    	jbe @FF
  1575 00000198 83E907                  	sub cx, .message_4_length
  1576 0000019B 7609                    	jbe @FF
  1577 0000019D 89CA                    	mov dx, cx
  1578 0000019F B023                    	mov al, '#'
  1579                                  @@:
  1580 000001A1 E88E00                  	call disp_al
  1581 000001A4 E2FB                    	loop @B
  1582                                  @@:
  1583 000001A6 59                      	pop cx
  1584 000001A7 B020                    	mov al, 32
  1585 000001A9 83EB29                  	sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length
  1586 000001AC 29D3                    	sub bx, dx
  1587 000001AE 7607                    	jbe @FF
  1588 000001B0 89D9                    	mov cx, bx
  1589                                  @@:
  1590 000001B2 E87D00                  	call disp_al
  1591 000001B5 E2FB                    	loop @B
  1592                                  @@:
  1593 000001B7 E97EFF                  	jmp .m4done
  1594                                  
  1595                                  .notyetm4:
  1596 000001BA B020                    	mov al, 32
  1597 000001BC 59                      	pop cx
  1598 000001BD 29CB                    	sub bx, cx
  1599 000001BF 7608                    	jbe @FF
  1600 000001C1 89D9                    	mov cx, bx
  1601                                  @@:
  1602 000001C3 E86C00                  	call disp_al
  1603 000001C6 4A                      	dec dx
  1604 000001C7 E0FA                    	loopnz @B
  1605                                  @@:
  1606                                  
  1607 000001C9 BE[F101]                	mov si, .message_4
  1608 000001CC 29FE                    	sub si, di
  1609 000001CE E85300                  	call disp_error
  1610                                  
  1611 000001D1 B020                    	mov al, 32
  1612 000001D3 29F9                    	sub cx, di
  1613 000001D5 83E907                  	sub cx, .message_4_length
  1614                                  	; jbe @FF
  1615                                  @@:
  1616 000001D8 E85700                  	call disp_al
  1617 000001DB E2FB                    	loop @B
  1618                                  @@:
  1619 000001DD E958FF                  	jmp .m4done
  1620                                  %endif
  1621                                  
  1622                                  	align 2, db 0
  1623                                   %if _PROGRESSMULTI
  1624 000001E0 FFFF                    .display:	dw -1
  1625                                   %endif
  1626 000001E2 0000                    .counter:	dw 0
  1627 000001E4 0D5B20                  .message:	db 13,"[ "
  1628 000001E7 2020312E30              .message_number:db "  1.0"	; enough digit slots for 100.0%,
  1629                                  				;  blanks are pre-init until written
  1630                                  .message_number_end:
  1631 000001EC 25205D00                		db "% ]",0
  1632                                   %if _PROGRESSMULTI
  1633 000001F0 20                      		db " "
  1634                                  .message_4:
  1635 000001F1 2020312E30              .message_4_number:db "  1.0"	; enough digit slots for 100.0%,
  1636                                  				;  blanks are pre-init until written
  1637                                  .message_4_number_end:
  1638 000001F6 252000                  		db "% ",0
  1639                                  .message_4_length: equ $ - 1 - .message_4
  1640                                   %endif
  1641                                  %endif
  1642                                  
  1643                                  
  1644                                  %if _DEVICE
  1645 000001F9 90<rep 7h>              	align 16
  1646                                  device_header_copy:
  1647                                  .:
  1648                                  .next:
  1649 00000200 FFFFFFFF                	dd -1				; already initialised
  1650                                  .attributes:
  1651 00000204 0088                    	dw _DEVICE_ATTRIBUTE
  1652                                  .strategy:
  1653 00000206 1200                    	dw .strategy_entry - .		; -> strategy entry
  1654                                  .interrupt:
  1655 00000208 1600                    	dw .interrupt_entry - .		; -> interrupt entry
  1656                                  .name:
  1657 0000020A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME
  1658                                  
  1659                                  .strategy_entry:
  1660 00000212 EB0690<rep 2h>          	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
  1661                                  .interrupt_entry:
  1662 00000216 CB90<rep 3h>            	fill 4, 90h, retf
  1663                                  
  1664                                  .set_error:
  1665 0000021A 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1666 00000220 CB                      	retf
  1667                                  .length: equ $ - .
  1668                                  %endif
  1669                                  
  1670                                  
  1671                                  disp_error.loop:
  1672 00000221 E80E00                  	call disp_al
  1673                                  disp_error:
  1674 00000224 AC                      	lodsb
  1675 00000225 84C0                    	test al, al
  1676 00000227 75F8                    	jnz .loop
  1677 00000229 C3                      	retn
  1678                                  
  1679                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
  1680                                  disp_ax_hex:			; ax
  1681                                  		xchg al,ah
  1682                                  		call disp_al_hex		; display former ah
  1683                                  		xchg al,ah			;  and fall trough for al
  1684                                  disp_al_hex:			; al
  1685                                  		push cx
  1686                                  		mov cl,4
  1687                                  		ror al,cl
  1688                                  		call disp_al_lownibble_hex	; display former high-nibble
  1689                                  		rol al,cl
  1690                                  		pop cx
  1691                                  						;  and fall trough for low-nibble
  1692                                  disp_al_lownibble_hex:
  1693                                  		push ax			 ; save ax for call return
  1694                                  		and al,00001111b		; high nibble must be zero
  1695                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1696                                  		cmp al,'9'
  1697                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1698                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1699                                   .decimalnum:
  1700                                  		call disp_al
  1701                                  		pop ax
  1702                                  		retn
  1703                                  %endif
  1704                                  
  1705                                  
  1706                                  disp_al_for_progress:
  1707                                  %if _PROGRESS && _PROGRESSMULTI
  1708 0000022A 2E833E[BA00]16          	cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base
  1709 00000230 741B                    	je disp_al.retn
  1710                                  %endif
  1711                                  disp_al:
  1712                                  %if _TEST_PROGRAM
  1713 00000232 C3                      	retn
  1714                                  %else
  1715                                  	push ax
  1716                                  %endif
  1717                                  %if _BOOTLDR
  1718 00000233 53                      	push bx
  1719 00000234 55                      	push bp
  1720 00000235 B40E                    	mov ah, 0Eh
  1721 00000237 BB0700                  	mov bx, 7
  1722                                  %endif
  1723                                  %if _IMAGE_EXE || _DEVICE
  1724 0000023A 52                      	push dx
  1725                                  
  1726                                  %if _BOOTLDR
  1727 0000023B F646FE03                	test byte [bp - 2], 1 | 2
  1728 0000023F 7406                    	jz .display_kernel_mode
  1729                                  %endif
  1730                                  
  1731 00000241 92                      	xchg dx, ax				; dl = input al
  1732 00000242 B402                    	mov ah, 02h
  1733 00000244 CD21                    	int 21h
  1734                                  %if _BOOTLDR
  1735 00000246 A9                      	db __TEST_IMM16				; (skip int)
  1736                                  %endif
  1737                                  
  1738                                  .display_kernel_mode:
  1739                                  %endif
  1740                                  %if _BOOTLDR
  1741 00000247 CD10                    	int 10h
  1742                                  %endif
  1743                                  %if _IMAGE_EXE
  1744 00000249 5A                      	pop dx
  1745                                  %endif
  1746                                  %if _BOOTLDR
  1747 0000024A 5D                      	pop bp
  1748 0000024B 5B                      	pop bx
  1749                                  %endif
  1750 0000024C 58                      	pop ax
  1751                                  .retn:
  1752                                  disp_error.ret:
  1753 0000024D C3                      	retn
  1754                                  
  1755                                  
  1756                                  msg:
  1757                                  %if _DEBUG0
  1758                                  .error_begin:	db "Load error: Decompression failure, code ",0
  1759                                  .error_end:	db "h.",13,10,0
  1760                                  %else
  1761 0000024E 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
  1761 00000257 723A204465636F6D70-
  1761 00000260 72657373696F6E2066-
  1761 00000269 61696C7572652E0D0A-
  1761 00000272 00                 
  1762                                  %endif
  1763                                  
  1764                                  
  1765                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
  1766                                  %assign NEED_NORMALISE_BOTH_POINTERS 1
  1767                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
  1768                                  %assign CHECK_POINTERS_VARIABLE_DST 1
  1769                                  
  1770                                  		; Specific depacker's file is included within label msg.
  1771                                  		; In the file, lframe is used and lleave ctx is not used.
  1772                                  
  1773                                  %if _BRIEFLZ
  1774                                  	%include "brieflz.asm"
  1775                                  %endif
  1776                                  
  1777                                  
  1778                                  %if _LZ4
  1779                                  	%include "lz4.asm"
  1780                                  %endif
  1781                                  
  1782                                  
  1783                                  %if _SNAPPY
  1784                                  	%include "snappy.asm"
  1785                                  %endif
  1786                                  
  1787                                  
  1788                                  %if _EXODECR
  1789                                  	%include "exodecr.asm"
  1790                                  %endif
  1791                                  
  1792                                  
  1793                                  %if _X
  1794                                  	%include "x.asm"
  1795                                  %endif
  1796                                  
  1797                                  
  1798                                  %if _HEATSHRINK
  1799                                  	%include "heatshr.asm"
  1800                                  %endif
  1801                                  
  1802                                  
  1803                                  %if _LZD
  1804                                  	%include "lzd.asm"
     1                              <1> 
     2                              <1> %if 0
     3                              <1> 
     4                              <1>     Lzd - Educational decompressor for the lzip format
     5                              <1>     Copyright (C) 2013-2019 Antonio Diaz Diaz.
     6                              <1> 
     7                              <1>     This program is free software. Redistribution and use in source and
     8                              <1>     binary forms, with or without modification, are permitted provided
     9                              <1>     that the following conditions are met:
    10                              <1> 
    11                              <1>     1. Redistributions of source code must retain the above copyright
    12                              <1>     notice, this list of conditions and the following disclaimer.
    13                              <1> 
    14                              <1>     2. Redistributions in binary form must reproduce the above copyright
    15                              <1>     notice, this list of conditions and the following disclaimer in the
    16                              <1>     documentation and/or other materials provided with the distribution.
    17                              <1> 
    18                              <1>     This program is distributed in the hope that it will be useful,
    19                              <1>     but WITHOUT ANY WARRANTY; without even the implied warranty of
    20                              <1>     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    21                              <1> 
    22                              <1> %endif
    23                              <1> 
    24                              <1> 
    25                              <1> 	numdef COUNTER,		0, 256
    26                              <1> %if (_COUNTER - 1) & _COUNTER
    27                              <1>  %error COUNTER must be a power of two
    28                              <1> %endif
    29                              <1> 
    30                              <1> 
    31                              <1> amount_states equ 12
    32                              <1> 
    33                              <1> 		numdef XLATBSEQ, 7
    34                              <1> 		numdef WARNXLATBSEQ, 0
    35                              <1> 
    36                              <1> 
    37                              <1> %if _XLATBSEQ != 7
    38                              <1> next_states.beforealign:
    39                              <1> 	align 2
    40                              <1> next_states:
    41                              <1> .:
    42                              <1> 	times 4 db 0
    43                              <1> 	db 1, 2, 3, 4, 5, 6, 4, 5
    44                              <1> .amount: equ $ - .
    45                              <1>  %if .amount != amount_states
    46                              <1>   %error Invalid next_states array content
    47                              <1>  %endif
    48                              <1>  %assign XLATBTABSIZE $ - .beforealign
    49                              <1> %else
    50                              <1>  %assign XLATBTABSIZE 0
    51                              <1> %endif
    52                              <1> 
    53                              <1> 
    54                              <1> State:
    55                              <1> 		; INP:	ds:bx -> localvariables
    56                              <1> 		;	byte [bx + state.st]
    57                              <1> 		; OUT:	CY if st < 7 (is_char() == true)
    58                              <1> 		;	NC if st >= 7 (is_char() == false)
    59                              <1> 		; CHG:	-
    60                              <1> .is_char:
    61 00000273 807F2807            <1> 	cmp byte [bx + state.st], 7
    62 00000277 C3                  <1> 	retn
    63                              <1> 
    64                              <1> 
    65                              <1> 		; INP:	ds:bx -> localvariables
    66                              <1> 		;	byte [bx + state.st]
    67                              <1> 		; OUT:	byte [bx + state.st] = al = next state
    68                              <1> 		; CHG:	al, ah (ah only if _XLATBSEQ == 6)
    69                              <1> .set_char:
    70                              <1> 
    71                              <1> .xlatbseq:
    72                              <1> %if 0 == _XLATBSEQ	; 10
    73                              <1> 	push bx
    74                              <1> 	mov al, byte [bx + state.st]
    75                              <1> 	mov bx, next_states
    76                              <1> 	cs xlatb
    77                              <1> 		; Problem: It is reported that prior to the 386
    78                              <1> 		;  a segment override on an xlatb instruction
    79                              <1> 		;  does not have any effect. So this choice is
    80                              <1> 		;  possibly wrong on those machines.
    81                              <1> 	pop bx
    82                              <1> %elif 1 == _XLATBSEQ	; 13
    83                              <1> 	push bx
    84                              <1> 	mov al, byte [bx + state.st]
    85                              <1> 	mov bx, next_states
    86                              <1> 	push ds
    87                              <1> 	 push cs
    88                              <1> 	 pop ds
    89                              <1> 	xlatb
    90                              <1> 	pop ds
    91                              <1> 	pop bx
    92                              <1> %elif 2 == _XLATBSEQ	; 16
    93                              <1> 	push bx
    94                              <1> 	mov al, byte [bx + state.st]
    95                              <1> 	mov bx, next_states
    96                              <1> 	add bl, al
    97                              <1> 	adc bh, 0
    98                              <1> 	mov al, byte [cs:bx]
    99                              <1> 	pop bx
   100                              <1> %elif 3 == _XLATBSEQ	; 14
   101                              <1> 	push bx
   102                              <1> 	mov al, byte [bx + state.st]
   103                              <1> 	xor bx, bx
   104                              <1> 	mov bl, al
   105                              <1> 	mov al, byte [cs:next_states + bx]
   106                              <1> 	pop bx
   107                              <1> %elif 4 == _XLATBSEQ	; 12
   108                              <1> 	push bx
   109                              <1> 	mov bl, byte [bx + state.st]
   110                              <1> 	mov bh, 0
   111                              <1> 	mov al, byte [cs:next_states + bx]
   112                              <1> 	pop bx
   113                              <1> %elif 5 == _XLATBSEQ	; 10
   114                              <1> 	push bx
   115                              <1> 	mov bl, byte [bx + state.st]
   116                              <1> 	; mov bh, 0
   117                              <1> 		; ! because the pointer stored in ?localvariables
   118                              <1> 		;    is normalised bh is already zero here.
   119                              <1> 	mov al, byte [cs:next_states + bx]
   120                              <1> 	pop bx
   121                              <1> %elif 6 == _XLATBSEQ	; 12
   122                              <1> 	xor ax, ax
   123                              <1> 	mov al, byte [bx + state.st]
   124                              <1> 	xchg ax, bx
   125                              <1> 	mov bl, byte [cs:next_states + bx]
   126                              <1> 	xchg ax, bx
   127                              <1> %elif 7 == _XLATBSEQ	; 16, but minus 13 for table
   128 00000278 8A4728              <1> 	mov al, byte [bx + state.st]
   129 0000027B 2C03                <1> 	sub al, 3		; below 4 ?
   130 0000027D 7607                <1> 	jbe .zero		; yes -->
   131 0000027F 3C07                <1> 	cmp al, 10 - 3		; 10 or 11 initially ?
   132 00000281 7202                <1> 	jb .have		; no -->
   133 00000283 2C03                <1> 	sub al, 3		; convert
   134                              <1> .have:
   135 00000285 A9                  <1> 	db __TEST_IMM16		; (skip mov)
   136                              <1> .zero:
   137 00000286 B000                <1> 	mov al, 0
   138                              <1> %else
   139                              <1>  %error Invalid xlatb sequence specified
   140                              <1> %endif
   141                              <1> %if _WARNXLATBSEQ
   142                              <1> %assign SIZE $ - .xlatbseq
   143                              <1> %warning xlatb sequence takes SIZE bytes plus XLATBTABSIZE table
   144                              <1> %endif
   145                              <1> .end:
   146 00000288 884728              <1> 	mov byte [bx + state.st], al
   147 0000028B C3                  <1> 	retn
   148                              <1> 
   149                              <1> 
   150                              <1> 		; INP:	ds:bx -> localvariables
   151                              <1> 		;	byte [bx + state.st]
   152                              <1> 		;	al = value to use if is_char() == true
   153                              <1> 		;	ah = value to use else
   154                              <1> 		; OUT:	byte [bx + state.st] = al = value to use
   155                              <1> 		; CHG:	al
   156                              <1> .select:
   157 0000028C E8E4FF              <1> 	call .is_char
   158 0000028F 72F7                <1> 	jc .end
   159 00000291 88E0                <1> 	mov al, ah
   160 00000293 EBF3                <1> 	jmp .end
   161                              <1> 
   162                              <1> 
   163                              <1>   min_dictionary_size:		equ 1 << 12
   164                              <1>   max_dictionary_size:		equ 1 << 29
   165                              <1>   literal_context_bits:		equ 3
   166                              <1>   literal_pos_state_bits:	equ 0		; not used
   167                              <1>   pos_state_bits:		equ 2
   168                              <1>   pos_states:			equ 1 << pos_state_bits
   169                              <1>   pos_state_mask:		equ pos_states - 1
   170                              <1> 
   171                              <1>   len_states:			equ 4
   172                              <1>   dis_slot_bits:		equ 6
   173                              <1>   start_dis_model:		equ 4
   174                              <1>   end_dis_model:		equ 14
   175                              <1>   modeled_distances:		equ 1 << ( end_dis_model / 2 )		; 128
   176                              <1>   dis_align_bits:		equ 4
   177                              <1>   dis_align_size:		equ 1 << dis_align_bits
   178                              <1> 
   179                              <1>   len_low_bits:			equ 3
   180                              <1>   len_mid_bits:			equ 3
   181                              <1>   len_high_bits:		equ 8
   182                              <1>   len_low_symbols:		equ 1 << len_low_bits
   183                              <1>   len_mid_symbols:		equ 1 << len_mid_bits
   184                              <1>   len_high_symbols:		equ 1 << len_high_bits
   185                              <1>   max_len_symbols:		equ len_low_symbols + len_mid_symbols + len_high_symbols
   186                              <1> 
   187                              <1>   min_match_len:		equ 2		; must be 2
   188                              <1> 
   189                              <1>   bit_model_move_bits:		equ 5
   190                              <1>   bit_model_total_bits:		equ 11
   191                              <1>   bit_model_total:		equ 1 << bit_model_total_bits
   192                              <1> 
   193                              <1> 
   194                              <1> 	struc bit_model
   195 00000000 ????                <1> .probability:	resw 1		; initialise to bit_model_total / 2
   196                              <1> 				; at most bit_model_total (800h)
   197                              <1> 	endstruc
   198                              <1> 
   199                              <1> 	struc len_model
   200 00000000 ????                <1> .choice1:	resb bit_model_size
   201 00000002 ????                <1> .choice2:	resb bit_model_size
   202 00000004 <res 40h>           <1> .bm_low:	resb bit_model_size * pos_states * len_low_symbols
   203 00000044 <res 40h>           <1> .bm_mid:	resb bit_model_size * pos_states * len_mid_symbols
   204 00000084 <res 200h>          <1> .bm_high:	resb bit_model_size * len_high_symbols
   205                              <1> 	endstruc
   206                              <1> 
   207                              <1> 	struc lzip_header
   208 00000000 ????????            <1> .magic:			resd 1
   209 00000004 ??                  <1> .version:		resb 1
   210 00000005 ??                  <1> .coded_dict_size:	resb 1
   211                              <1> 	endstruc
   212                              <1> 
   213                              <1> 	struc lzip_trailer
   214 00000000 ????????            <1> .uncompressed_checksum:	resd 1
   215 00000004 ????????????????    <1> .uncompressed_size:	resq 1
   216 0000000C ????????????????    <1> .member_size:		resq 1
   217                              <1> 	endstruc
   218                              <1> 
   219                              <1> 	struc range_decoder
   220 00000000 ????????            <1> .member_pos:		resd 1
   221 00000004 ????????            <1> .code:			resd 1
   222 00000008 ????????            <1> .range:			resd 1
   223                              <1> 	endstruc
   224                              <1> 
   225                              <1> 		; INP:	ds:bx -> range_decoder structure
   226                              <1> 		;	ss:bp -> depack stack frame
   227                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   228                              <1> 		; CHG:	es, di, ax, cx
   229                              <1> Range_decoder.init:
   230 00000295 1E                  <1> 	push ds
   231 00000296 07                  <1> 	pop es
   232 00000297 B80600              <1> 	mov ax, 6
   233 0000029A 89DF                <1> 	mov di, bx		; -> .member_pos
   234 0000029C AB                  <1> 	stosw			; low word of .member_pos
   235 0000029D 31C0                <1> 	xor ax, ax
   236 0000029F AB                  <1> 	stosw			; high word of .member_pos
   237 000002A0 AB                  <1> 	stosw
   238 000002A1 AB                  <1> 	stosw			; .code
   239 000002A2 48                  <1> 	dec ax
   240 000002A3 AB                  <1> 	stosw
   241 000002A4 AB                  <1> 	stosw			; .range
   242 000002A5 B90500              <1> 	mov cx, 5
   243                              <1> .loop:
   244 000002A8 E81900              <1> 	call getbyteshiftcode
   245 000002AB E2FB                <1> 	loop .loop
   246 000002AD C3                  <1> 	retn
   247                              <1> 
   248                              <1> 
   249                              <1> 		; INP:	ds:bx -> range_decoder structure
   250                              <1> 		;	ss:bp -> depack stack frame
   251                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   252                              <1> 		; CHG:	-
   253                              <1> normaliserange:
   254 000002AE 807F0B00            <1> 	cmp byte [bx + range_decoder.range + 3], 0
   255 000002B2 7521                <1> 	jnz @F			; (retn)
   256 000002B4 50                  <1> 	push ax
   257 000002B5 8B4709              <1> 	mov ax, word [bx + range_decoder.range + 1]
   258 000002B8 89470A              <1> 	mov word [bx + range_decoder.range + 2], ax
   259 000002BB 8A6708              <1> 	mov ah, byte [bx + range_decoder.range]
   260 000002BE B000                <1> 	mov al, 0
   261 000002C0 894708              <1> 	mov word [bx + range_decoder.range], ax
   262 000002C3 58                  <1> 	pop ax
   263                              <1> 		; fall through
   264                              <1> 
   265                              <1> 
   266                              <1> 		; INP:	ds:bx -> range_decoder structure
   267                              <1> 		;	ss:bp -> depack stack frame
   268                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   269                              <1> 		; CHG:	-
   270                              <1> getbyteshiftcode:
   271 000002C4 50                  <1> 	push ax
   272 000002C5 8B4705              <1> 	mov ax, word [bx + range_decoder.code + 1]
   273 000002C8 894706              <1> 	mov word [bx + range_decoder.code + 2], ax
   274 000002CB 8A6704              <1> 	mov ah, byte [bx + range_decoder.code]
   275 000002CE E8A306              <1> 	call Range_decoder.get_byte
   276 000002D1 894704              <1> 	mov word [bx + range_decoder.code], ax
   277 000002D4 58                  <1> 	pop ax
   278                              <1> @@:
   279 000002D5 C3                  <1> 	retn
   280                              <1> 
   281                              <1> 
   282                              <1> 		; INP:	ds:bx -> range_decoder structure
   283                              <1> 		;	cx = num_bits
   284                              <1> 		;	ss:bp -> depack stack frame
   285                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   286                              <1> 		;	If success,
   287                              <1> 		;	 dx:ax = symbol
   288                              <1> 		; CHG:	di, cx
   289                              <1> Range_decoder.decode:
   290 000002D6 31D2                <1> 	xor dx, dx
   291 000002D8 31C0                <1> 	xor ax, ax
   292 000002DA E32C                <1> 	jcxz .end
   293                              <1> .loop:
   294 000002DC D16F0A              <1> 	shr word [bx + range_decoder.range + 2], 1
   295 000002DF D15F08              <1> 	rcr word [bx + range_decoder.range], 1
   296 000002E2 D1E0                <1> 	shl ax, 1
   297 000002E4 D1D2                <1> 	rcl dx, 1
   298 000002E6 8B7F06              <1> 	mov di, word [bx + range_decoder.code + 2]
   299 000002E9 3B7F0A              <1> 	cmp di, word [bx + range_decoder.range + 2]
   300 000002EC 7506                <1> 	jne @F
   301 000002EE 8B7F04              <1> 	mov di, word [bx + range_decoder.code]
   302 000002F1 3B7F08              <1> 	cmp di, word [bx + range_decoder.range]
   303                              <1> @@:				; code >= range ?
   304 000002F4 720D                <1> 	jnae @F			; no, skip -->
   305 000002F6 8B7F08              <1> 	mov di, word [bx + range_decoder.range]
   306 000002F9 297F04              <1> 	sub word [bx + range_decoder.code], di
   307 000002FC 8B7F0A              <1> 	mov di, word [bx + range_decoder.range + 2]
   308 000002FF 197F06              <1> 	sbb word [bx + range_decoder.code + 2], di
   309 00000302 40                  <1> 	inc ax			; symbol |= 1 (lowest bit always was zero)
   310                              <1> @@:
   311 00000303 E8A8FF              <1> 	call normaliserange
   312 00000306 E2D4                <1> 	loop .loop
   313                              <1> .end:
   314 00000308 C3                  <1> 	retn
   315                              <1> 
   316                              <1> 
   317                              <1> 		; INP:	ds:bx -> range_decoder structure
   318                              <1> 		;	es:di -> bit_model structure
   319                              <1> 		;	ss:bp -> depack stack frame
   320                              <1> 		; OUT:	al = read bit
   321                              <1> 		;	NC if zero read
   322                              <1> 		;	CY if one read
   323                              <1> 		;	! If an error occurs, jumps to depack.error
   324                              <1> 		; CHG:	cx, dx, ax
   325                              <1> Range_decoder.decode_bit:
   326 00000309 8B570A              <1> 	mov dx, word [bx + range_decoder.range + 2]
   327 0000030C 8B4708              <1> 	mov ax, word [bx + range_decoder.range]
   328 0000030F B90B00              <1> 	mov cx, bit_model_total_bits
   329                              <1> @@:
   330 00000312 D1EA                <1> 	shr dx, 1
   331 00000314 D1D8                <1> 	rcr ax, 1
   332 00000316 E2FA                <1> 	loop @B
   333                              <1> 
   334 00000318 89D1                <1> 	mov cx, dx
   335 0000031A 26F725              <1> 	mul word [es:di + bit_model.probability]
   336                              <1> 				; dx:ax = low word + first high word
   337 0000031D 52                  <1> 	 push dx
   338 0000031E 50                  <1> 	 push ax		; on stack = low word + first high word
   339 0000031F 91                  <1> 	xchg ax, cx
   340 00000320 26F725              <1> 	mul word [es:di + bit_model.probability]
   341                              <1> 				; ax = second high word (dx overflow)
   342 00000323 91                  <1> 	xchg ax, cx		; cx
   343 00000324 58                  <1> 	 pop ax
   344 00000325 5A                  <1> 	 pop dx
   345 00000326 01CA                <1> 	add dx, cx		; = full uint32_t result
   346 00000328 B90500              <1> 	mov cx, bit_model_move_bits
   347                              <1> 
   348 0000032B 395706              <1> 	cmp word [bx + range_decoder.code + 2], dx
   349 0000032E 7503                <1> 	jne @F
   350 00000330 394704              <1> 	cmp word [bx + range_decoder.code], ax
   351                              <1> @@:
   352 00000333 7317                <1> 	jnb .not_code_below_bound
   353                              <1> 
   354                              <1> .code_below_bound:
   355 00000335 894708              <1> 	mov word [bx + range_decoder.range], ax
   356 00000338 89570A              <1> 	mov word [bx + range_decoder.range + 2], dx
   357 0000033B B80008              <1> 	mov ax, bit_model_total
   358 0000033E 262B05              <1> 	sub ax, word [es:di + bit_model.probability]
   359 00000341 7228                <1> 	jc .error
   360 00000343 D3E8                <1> 	shr ax, cl
   361 00000345 260105              <1> 	add word [es:di + bit_model.probability], ax
   362 00000348 B000                <1> 	mov al, 0
   363 0000034A EB18                <1> 	jmp .after_if
   364                              <1> 
   365                              <1> .not_code_below_bound:
   366 0000034C 294708              <1> 	sub word [bx + range_decoder.range], ax
   367 0000034F 19570A              <1> 	sbb word [bx + range_decoder.range + 2], dx
   368 00000352 294704              <1> 	sub word [bx + range_decoder.code], ax
   369 00000355 195706              <1> 	sbb word [bx + range_decoder.code + 2], dx
   370                              <1> 
   371 00000358 268B05              <1> 	mov ax, word [es:di + bit_model.probability]
   372 0000035B D3E8                <1> 	shr ax, cl
   373 0000035D 262905              <1> 	sub word [es:di + bit_model.probability], ax
   374 00000360 7209                <1> 	jc .error
   375 00000362 B001                <1> 	mov al, 1
   376                              <1> 
   377                              <1> .after_if:
   378 00000364 E847FF              <1> 	call normaliserange
   379 00000367 3C01                <1> 	cmp al, 1		; CY if 0, NC if 1
   380 00000369 F5                  <1> 	cmc			; NC if 0, CY if 1
   381 0000036A C3                  <1> 	retn
   382                              <1> 
   383                              <1> .error:
   384 0000036B E9F505              <1> 	jmp depack.error
   385                              <1> 
   386                              <1> 
   387                              <1> 		; INP:	ds:bx -> range_decoder structure
   388                              <1> 		;	es:di -> bit_model structure array
   389                              <1> 		;	cx = num_bits, <= 15
   390                              <1> 		;	ss:bp -> depack stack frame
   391                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   392                              <1> 		;	If success,
   393                              <1> 		;	 dx:ax = ax = symbol
   394                              <1> 		; CHG:	cx, si
   395                              <1> Range_decoder.decode_tree:
   396 0000036E BE0100              <1> 	mov si, 1		; symbol = 1
   397 00000371 83F90F              <1> 	cmp cx, 15
   398 00000374 7721                <1> 	ja .error
   399 00000376 51                  <1> 	push cx
   400 00000377 E312                <1> 	jcxz .end
   401                              <1> .loop:
   402 00000379 57                  <1> 	push di
   403                              <1> 		; Here si (symbol) is at most 1 << 14.
   404                              <1> %if bit_model_size != 2
   405                              <1>  %error Assuming word size for bit_model_size
   406                              <1> %endif
   407 0000037A D1E6                <1> 	shl si, 1		; Note that this shift is both used instead of
   408                              <1> 				;  multiplying symbol (si) by bit_model_size
   409                              <1> 				;  and to actually shift symbol (si) left!
   410 0000037C 01F7                <1> 	add di, si		; index into bit_model array
   411 0000037E 7217                <1> 	jc .error_pop_2
   412 00000380 51                  <1> 	push cx
   413 00000381 E885FF              <1> 	call Range_decoder.decode_bit
   414 00000384 59                  <1> 	pop cx
   415 00000385 83D600              <1> 	adc si, 0		; add in the decoded bit
   416 00000388 5F                  <1> 	pop di
   417 00000389 E2EE                <1> 	loop .loop
   418                              <1> .end:
   419 0000038B 59                  <1> 	pop cx
   420 0000038C B80100              <1> 	mov ax, 1
   421 0000038F D3E0                <1> 	shl ax, cl		; = 1 << num_bits
   422 00000391 29C6                <1> 	sub si, ax		; symbol - ( 1 << num_bits )
   423 00000393 96                  <1> 	xchg ax, si
   424 00000394 31D2                <1> 	xor dx, dx		; return symbol
   425 00000396 C3                  <1> 	retn
   426                              <1> 
   427                              <1> .error_pop_2:
   428                              <1> .error:
   429 00000397 E9C905              <1> 	jmp depack.error
   430                              <1> 
   431                              <1> 
   432                              <1> 		; INP:	ds:bx -> range_decoder structure
   433                              <1> 		;	es:di -> bit_model structure array
   434                              <1> 		;	cx = num_bits, <= 15
   435                              <1> 		;	ss:bp -> depack stack frame
   436                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   437                              <1> 		;	If success,
   438                              <1> 		;	 dx:ax = ax = reversed_symbol
   439                              <1> 		; CHG:	cx, si
   440                              <1> Range_decoder.decode_tree_reversed:
   441 0000039A 51                  <1> 	push cx
   442 0000039B E8D0FF              <1> 	call Range_decoder.decode_tree
   443 0000039E 59                  <1> 	pop cx
   444 0000039F 92                  <1> 	xchg dx, ax		; dx = symbol
   445 000003A0 31C0                <1> 	xor ax, ax		; = reversed_symbol
   446 000003A2 E306                <1> 	jcxz .end
   447                              <1> .loop:
   448 000003A4 D1EA                <1> 	shr dx, 1
   449 000003A6 D1D0                <1> 	rcl ax, 1
   450 000003A8 E2FA                <1> 	loop .loop
   451                              <1> .end:
   452 000003AA 31D2                <1> 	xor dx, dx
   453 000003AC C3                  <1> 	retn
   454                              <1> 
   455                              <1> 
   456                              <1> 		; INP:	ds:bx -> range_decoder structure
   457                              <1> 		;	es:di -> bit_model structure array
   458                              <1> 		;	al = match_byte
   459                              <1> 		;	ss:bp -> depack stack frame
   460                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   461                              <1> 		;	If success,
   462                              <1> 		;	 al = return value (symbol & 0FFh)
   463                              <1> 		; CHG:	cx, dx, ax
   464                              <1> Range_decoder.decode_matched:
   465 000003AD 88C6                <1> 	mov dh, al		; = match_byte
   466                              <1> 
   467 000003AF B80100              <1> 	mov ax, 1		; initialise symbol = 1
   468                              <1> 
   469 000003B2 B90800              <1> 	mov cx, 8
   470                              <1> .loop:
   471 000003B5 52                  <1> 	push dx			; preserve dh = match_byte
   472 000003B6 51                  <1> 	push cx			; preserve loop counter
   473 000003B7 49                  <1> 	dec cx
   474 000003B8 D2EE                <1> 	shr dh, cl		; match_byte >> i
   475 000003BA 81E20001            <1> 	and dx, 100h		; dh &= 1 = match_bit, dl = 0
   476 000003BE 52                  <1> 	push dx
   477 000003BF FEC6                <1> 	inc dh			; = (match_bit << 8) + 100h
   478 000003C1 01C2                <1> 	add dx, ax		; = symbol + (match_bit << 8) + 100h
   479                              <1> 		; As symbol is below 256, this is at most 255 + 100h + 100h,
   480                              <1> 		;  which is 2FFh. As such, the bm_literal array's
   481                              <1> 		;  entries are arrays of 300h bit_model each.
   482 000003C3 57                  <1> 	push di
   483 000003C4 50                  <1> 	push ax
   484                              <1> %if bit_model_size != 2
   485                              <1>  %error Assuming word size for bit_model_size
   486                              <1> %endif
   487 000003C5 01D2                <1> 	add dx, dx
   488                              <1> 		; As dx was < 300h before this addition, it cannot carry.
   489 000003C7 01D7                <1> 	add di, dx
   490                              <1> 		; We assume that this does not carry.
   491 000003C9 E83DFF              <1> 	call Range_decoder.decode_bit
   492 000003CC 91                  <1> 	xchg ax, cx		; cl = result (1 or 0)
   493 000003CD 58                  <1> 	pop ax			; = symbol
   494 000003CE 5F                  <1> 	pop di
   495 000003CF 5A                  <1> 	pop dx			; = match_bit << 8
   496 000003D0 D1D0                <1> 	rcl ax, 1		; shift symbol, OR in the bit
   497                              <1> 		; As the loop counter is initialised to 8,
   498                              <1> 		;  the symbol variable stays below 256.
   499 000003D2 38F1                <1> 	cmp cl, dh		; if( match_bit != bit ) ...-
   500 000003D4 59                  <1> 	pop cx			; = loop counter
   501 000003D5 5A                  <1> 	pop dx			; = dh = match_byte
   502 000003D6 7519                <1> 	jne .inner_next		; -... do the following -->
   503                              <1> .next:
   504 000003D8 E2DB                <1> 	loop .loop
   505                              <1> .end:
   506 000003DA 30E4                <1> 	xor ah, ah		; return ax = symbol & 0FFh
   507 000003DC C3                  <1> 	retn
   508                              <1> 
   509                              <1> .error_pop_2:
   510                              <1> .error:
   511 000003DD E98305              <1> 	jmp depack.error
   512                              <1> 
   513                              <1> 
   514                              <1> .inner_loop:
   515 000003E0 50                  <1> 	push ax
   516                              <1> %if bit_model_size != 2
   517                              <1>  %error Assuming word size for bit_model_size
   518                              <1> %endif
   519 000003E1 01C0                <1> 	add ax, ax
   520 000003E3 57                  <1> 	push di
   521 000003E4 01C7                <1> 	add di, ax
   522 000003E6 72F5                <1> 	jc .error_pop_2
   523 000003E8 E81EFF              <1> 	call Range_decoder.decode_bit
   524 000003EB 5F                  <1> 	pop di
   525 000003EC 58                  <1> 	pop ax
   526 000003ED D1D0                <1> 	rcl ax, 1
   527 000003EF 72EC                <1> 	jc .error
   528                              <1> 
   529                              <1> .inner_next:
   530 000003F1 3D0001              <1> 	cmp ax, 100h
   531 000003F4 72EA                <1> 	jb .inner_loop
   532 000003F6 EBE2                <1> 	jmp .end
   533                              <1> 
   534                              <1> 
   535                              <1> 		; INP:	ds:bx -> range_decoder structure
   536                              <1> 		;	es:di -> len_model structure
   537                              <1> 		;	ax = pos_state
   538                              <1> 		;	ss:bp -> depack stack frame
   539                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   540                              <1> 		;	If success,
   541                              <1> 		;	 dx:ax = return
   542                              <1> 		; CHG:	cx, si
   543                              <1> Range_decoder.decode_len:
   544 000003F8 89C6                <1> 	mov si, ax		; = pos_state
   545 000003FA 57                  <1> 	 push di		; = len_model_struc (on stack)
   546                              <1> 
   547 000003FB 8D3D                <1> 	lea di, [di + len_model.choice1]
   548 000003FD E809FF              <1> 	call Range_decoder.decode_bit
   549 00000400 5F                  <1> 	 pop di			; reset to ?len_model_struc
   550 00000401 57                  <1> 	 push di
   551 00000402 7218                <1> 	jc .not_decode_bit_choice1_equals_zero
   552                              <1> 
   553 00000404 8D7D04              <1> 	lea di, [di + len_model.bm_low]
   554 00000407 B81000              <1> 	mov ax, len_low_symbols * bit_model_size
   555 0000040A F7E6                <1> 	mul si
   556 0000040C 85D2                <1> 	test dx, dx
   557 0000040E 7546                <1> 	jnz .error
   558 00000410 01C7                <1> 	add di, ax
   559 00000412 7242                <1> 	jc .error
   560 00000414 B90300              <1> 	mov cx, len_low_bits
   561 00000417 E854FF              <1> 	call Range_decoder.decode_tree
   562 0000041A EB38                <1> 	jmp .ret
   563                              <1> 
   564                              <1> .not_decode_bit_choice1_equals_zero:
   565 0000041C 8D7D02              <1> 	lea di, [di + len_model.choice2]
   566 0000041F E8E7FE              <1> 	call Range_decoder.decode_bit
   567 00000422 5F                  <1> 	 pop di			; reset to ?len_model_struc
   568 00000423 57                  <1> 	 push di
   569 00000424 721E                <1> 	jc .not_decode_bit_choice2_equals_zero
   570                              <1> 
   571 00000426 8D7D44              <1> 	lea di, [di + len_model.bm_mid]
   572 00000429 B81000              <1> 	mov ax, len_mid_symbols * bit_model_size
   573 0000042C F7E6                <1> 	mul si
   574 0000042E 85D2                <1> 	test dx, dx
   575 00000430 7524                <1> 	jnz .error
   576 00000432 01C7                <1> 	add di, ax
   577 00000434 7220                <1> 	jc .error
   578 00000436 B90300              <1> 	mov cx, len_mid_bits
   579 00000439 E832FF              <1> 	call Range_decoder.decode_tree
   580 0000043C 83C008              <1> 	add ax, len_low_symbols & 0FFFFh
   581 0000043F 83D200              <1> 	adc dx, len_low_symbols >> 16
   582 00000442 EB10                <1> 	jmp .ret
   583                              <1> 
   584                              <1> .not_decode_bit_choice2_equals_zero:
   585 00000444 8DBD8400            <1> 	lea di, [di + len_model.bm_high]
   586 00000448 B90800              <1> 	mov cx, len_high_bits
   587 0000044B E820FF              <1> 	call Range_decoder.decode_tree
   588 0000044E 83C010              <1> 	add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh
   589 00000451 83D200              <1> 	adc dx, (len_low_symbols + len_mid_symbols) >> 16
   590                              <1> .ret:
   591 00000454 5F                  <1> 	 pop di
   592 00000455 C3                  <1> 	retn
   593                              <1> 
   594                              <1> .error:
   595 00000456 E90A05              <1> 	jmp depack.error
   596                              <1> 
   597                              <1> 
   598                              <1> 	struc lz_decoder
   599 00000000 <res Ch>            <1> .range_decoder:		resb range_decoder_size
   600 0000000C ????????            <1> 			alignb 8
   601 00000010 ????????            <1> .dictionary_size:	resd 1
   602 00000014 ????????            <1> .pos:			resd 1
   603                              <1> 	endstruc
   604                              <1> 
   605                              <1> 
   606                              <1> 		; INP:	ds:bx -> lz_decoder structure, localvariables structure
   607                              <1> 		;	dx:ax = distance
   608                              <1> 		; OUT:	al = ax = byte from buffer
   609                              <1> 		; CHG:	dx, cx, di, si, es
   610                              <1> LZ_decoder.peek:
   611 00000459 395716              <1> 	cmp word [bx + lz_decoder.pos + 2], dx
   612 0000045C 7503                <1> 	jne @F
   613 0000045E 394714              <1> 	cmp word [bx + lz_decoder.pos], ax
   614                              <1> @@:
   615 00000461 760A                <1> 	jna .not_pos_above_distance
   616                              <1> 
   617 00000463 E80A00              <1> 	call calculate_peek_pointer_disi
   618                              <1> 
   619 00000466 8EC7                <1> 	mov es, di			; es:si -> peek address
   620 00000468 31C0                <1> 	xor ax, ax
   621 0000046A 26AC                <1> 	es lodsb
   622 0000046C C3                  <1> 	retn
   623                              <1> 
   624                              <1> .not_pos_above_distance:
   625 0000046D 31C0                <1> 	xor ax, ax
   626 0000046F C3                  <1> 	retn
   627                              <1> 
   628                              <1> 
   629                              <1> 		; INP:	dx:ax = peek distance
   630                              <1> 		;	ds:bx -> local variables
   631                              <1> 		; OUT:	di:si -> peek address
   632                              <1> 		; CHG:	cx, dx, ax
   633                              <1> calculate_peek_pointer_disi:
   634 00000470 53                  <1> 	push bx
   635 00000471 FF772E              <1> 	 push word [bx + destinationbuffer_constant + 2]
   636 00000474 FF772C              <1> 	 push word [bx + destinationbuffer_constant]
   637                              <1> 
   638 00000477 F7DA                <1> 	neg dx
   639 00000479 F7D8                <1> 	neg ax
   640 0000047B 83DA00              <1> 	sbb dx, byte 0			; neg dx:ax = - distance
   641 0000047E 83E801              <1> 	sub ax, 1
   642 00000481 83DA00              <1> 	sbb dx, 0			; - 1
   643 00000484 034714              <1> 	add ax, word [bx + lz_decoder.pos]
   644 00000487 135716              <1> 	adc dx, word [bx + lz_decoder.pos + 2]
   645                              <1> 					; + pos
   646 0000048A 91                  <1> 	xchg cx, ax
   647 0000048B 87DA                <1> 	xchg bx, dx
   648                              <1> 
   649 0000048D E88B06              <1> 	call normalise_pointer_with_displacement_bxcx
   650 00000490 5E                  <1> 	 pop si
   651 00000491 5F                  <1> 	 pop di				; di:si -> source
   652 00000492 5B                  <1> 	pop bx
   653 00000493 C3                  <1> 	retn
   654                              <1> 
   655                              <1> 
   656                              <1> 		; INP:	ss:bp -> depack stack frame
   657                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   658                              <1> 		;	If success,
   659                              <1> 		;	 al = byte
   660                              <1> 		; CHG:	-
   661                              <1> LZ_decoder.get_byte: equ Range_decoder.get_byte
   662                              <1> 
   663                              <1> 
   664                              <1> 	struc localvariables
   665                              <1> lz_decoder_struc:
   666 00000000 <res 18h>           <1> 		resb lz_decoder_size
   667                              <1> 		alignb 4
   668                              <1> zeros_start:
   669 00000018 ????????            <1> rep0:		resd 1
   670 0000001C ????????            <1> rep1:		resd 1
   671 00000020 ????????            <1> rep2:		resd 1
   672 00000024 ????????            <1> rep3:		resd 1
   673 00000028 ????                <1> state.st:	resw 1		; initialise to zero
   674 0000002A ????                <1> 		alignb 4
   675                              <1> zeros_end:
   676 0000002C ????????            <1> destinationbuffer_constant:	resd 1		; stays constant
   677                              <1> 		alignb 16
   678                              <1> bit_models_start:
   679 00000030 <res 60h>           <1> bm_match:	resb bit_model_size * amount_states * pos_states
   680 00000090 <res 18h>           <1> bm_rep:		resb bit_model_size * amount_states
   681 000000A8 <res 18h>           <1> bm_rep0:	resb bit_model_size * amount_states
   682 000000C0 <res 18h>           <1> bm_rep1:	resb bit_model_size * amount_states
   683 000000D8 <res 18h>           <1> bm_rep2:	resb bit_model_size * amount_states
   684 000000F0 <res 3000h>         <1> bm_literal:	resb bit_model_size * (1 << literal_context_bits) * 300h
   685 000030F0 <res 60h>           <1> bm_len:		resb bit_model_size * amount_states * pos_states
   686 00003150 <res 200h>          <1> bm_dis_slot:	resb bit_model_size * len_states * (1 << dis_slot_bits)
   687 00003350 <res E6h>           <1> bm_dis:		resb bit_model_size * (modeled_distances - end_dis_model + 1)
   688 00003436 <res 20h>           <1> bm_align:	resb bit_model_size * dis_align_size
   689 00003456 <res 284h>          <1> match_len_model:resb len_model_size
   690 000036DA <res 284h>          <1> rep_len_model:	resb len_model_size
   691                              <1> bit_models_end:
   692 0000395E ????                <1> 		alignb 16
   693                              <1> 	endstruc
   694                              <1> %if lz_decoder_struc != 0
   695                              <1>  %error Expecting lz_decoder structure at start of localvariables structure
   696                              <1> %endif
   697                              <1> %assign STRUCSIZE localvariables_size
   698                              <1> %warning localvariables has STRUCSIZE bytes
   698          ******************  <1>  warning: localvariables has 14688 bytes [-w+user]
   699                              <1> 
   700                              <1> 
   701                              <1> 	align 4
   702                              <1> lzip_header_bytes:
   703                              <1> .:
   704 00000494 4C5A495001          <1> 	db "LZIP",1
   705                              <1> .length: equ $ - .
   706                              <1> 
   707                              <1> 
   708                              <1> 		; INP:	ds:si -> source
   709                              <1> 		;	dx:cx = length of source
   710                              <1> 		;	es:di -> destination (below source)
   711                              <1> 		;	if _IMAGE_EXE:
   712                              <1> 		;	 bx = EXE mode flag (bit 0)
   713                              <1> 		;	else:
   714                              <1> 		;	 bx = 0
   715                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
   716                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
   717                              <1> 		;	 (-1 if full source should be decompressed)
   718                              <1> 		;	else:
   719                              <1> 		;	 ax = -1
   720                              <1> 		; OUT:	NC if success
   721                              <1> 		;	CY if error,
   722                              <1> 		;	 bx = ?errordata (if _DEBUG0)
   723                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
   724                              <1> 		; STT:	UP
   725                              <1> 		;
   726                              <1> 		; Note:	The destination reaches up to below the source.
   727                              <1> 		; Note:	The input pointers need not be normalised yet.
   728                              <1> 		;	 Normalised means that the offset part is below 16.
   729                              <1> depack:
   730                              <1> 	lframe near
   731                              <1> %if _IMAGE_EXE || _COUNTER || _DEBUG0
   732 00000499 5589E5              <1> 	lenter early
   733                              <1>  %if _IMAGE_EXE
   734                              <1> 	lvar word,	exemode	; must be bp - 2!
   735 0000049C 53                  <1> 	 push bx
   736                              <1>   %if ?exemode != -2
   737                              <1>    %error exemode variable must be directly below bp
   738                              <1>   %endif
   739                              <1>  %endif
   740                              <1>  %if _COUNTER || _DEBUG0
   741 0000049D 31DB                <1> 	xor bx, bx
   742                              <1>  %endif
   743                              <1> %endif
   744                              <1> %if _COUNTER
   745                              <1> 	lvar word,	counter
   746 0000049F 53                  <1> 	 push bx		; initialise counter to zero
   747                              <1> %endif
   748                              <1> d0	lvar word,	errordata
   749                              <1> d0	 push bx
   750                              <1> 	lvar dword,	distance
   751                              <1> 	lvar dword,	len
   752                              <1> 	lvar dword,	dis_slot
   753                              <1> 	lvar word,	len_state
   754                              <1> 	lvar word,	pos_state
   755 000004A0 8D66EC              <1> 	lenter
   756                              <1> 
   757 000004A3 E84406              <1> 	call normalise_both_pointers
   758                              <1> 
   759                              <1> 		; ! di < 16, so dih == 0
   760                              <1> 	lvar dword,	src
   761 000004A6 1E                  <1> 	 push ds
   762 000004A7 56                  <1> 	 push si
   763                              <1> 	lvar dword,	final_dst
   764 000004A8 06                  <1> 	 push es
   765 000004A9 57                  <1> 	 push di
   766                              <1> 	lequ ?final_dst,	localvariables
   767                              <1> 		; ! offset of ?localvariables is always < 16
   768                              <1> 		;  required for State.set_char with _XLATBSEQ == 5
   769                              <1> 	lvar dword,	length_of_source
   770 000004AA 52                  <1> 	 push dx
   771 000004AB 51                  <1> 	 push cx
   772                              <1> 
   773                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
   774                              <1> 	cmp ax, -1		; no maximum specified ?
   775                              <1> 	je @FF			; retain -1 in ax -->
   776                              <1> 	test di, di		; do we need an additional paragraph ?
   777                              <1> 	jz @F			; no -->
   778                              <1> 	inc ax			; es + ax => paragraph after necessary part
   779                              <1> @@:
   780                              <1> 	mov dx, es
   781                              <1> 	add ax, dx		; => paragraph after necessary part
   782                              <1> 		; If the normalised destination pointer's segment grows
   783                              <1> 		;  to this segment then enough has been decompressed.
   784                              <1> d0	mov byte [bp + ?errordata], 40h
   785                              <1> 	jc .error_CY_a1		; should not carry
   786                              <1> @@:
   787                              <1> 	lvar word,	dst_max_segment
   788                              <1> 	 push ax
   789                              <1> %endif
   790                              <1> 
   791 000004AC 1E                  <1> 	 push ds
   792 000004AD 56                  <1> 	 push si
   793 000004AE E89906              <1> 	call pointer_to_linear
   794                              <1> 
   795 000004B1 87DA                <1> 	xchg bx, dx
   796 000004B3 91                  <1> 	xchg cx, ax		; bx:cx = source linear, clobber dx:ax
   797                              <1> 
   798 000004B4 06                  <1> 	 push es
   799 000004B5 57                  <1> 	 push di
   800 000004B6 E89106              <1> 	call pointer_to_linear
   801                              <1> 
   802                              <1> %if _ALLOW_OVERLAPPING
   803 000004B9 034EE0              <1> 	add cx, word [bp + ?length_of_source]
   804 000004BC 135EE2              <1> 	adc bx, word [bp + ?length_of_source + 2]
   805                              <1> 		; In case of allowing overlapping source and destination,
   806                              <1> 		;  the ?length_of_destination variable is set to
   807                              <1> 		;  ?src + ?length_of_source - ?dst, allowing to write to
   808                              <1> 		;  all of the source buffer (with the checks already in place
   809                              <1> 		;  from the default handling). Additional checks are done by
   810                              <1> 		;  calling check_pointers_not_overlapping. This is done after
   811                              <1> 		;  every change of ?dst to verify that the write pointer stays
   812                              <1> 		;  below-or-equal the read pointer.
   813                              <1> 		; This means the remaining source data may be corrupted by a
   814                              <1> 		;  write, but nothing after the source data is written to,
   815                              <1> 		;  so the error handling (in INIT1 after the data) still works.
   816                              <1> %endif
   817                              <1> 
   818 000004BF 29C1                <1> 	sub cx, ax
   819 000004C1 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   820                              <1> 
   821 000004C3 81E96039            <1> 	sub cx, localvariables_size & 0FFFFh
   822 000004C7 83DB00              <1> 	sbb bx, localvariables_size >> 16
   823 000004CA 7703E99404          <1> 	jbe .error		; make variables buffer available
   824                              <1> 
   825                              <1> 	lvar dword,	length_of_destination
   826 000004CF 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   827 000004D0 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   828                              <1> 
   829 000004D1 06                  <1> 	push es
   830 000004D2 57                  <1> 	push di
   831                              <1> %if localvariables_size >> 16
   832                              <1> 	mov bx, localvariables_size >> 16
   833                              <1> %else
   834 000004D3 31DB                <1> 	xor bx, bx
   835                              <1> %endif
   836 000004D5 B96039              <1> 	mov cx, localvariables_size & 0FFFFh
   837 000004D8 E84006              <1> 	call normalise_pointer_with_displacement_bxcx
   838 000004DB 5F                  <1> 	pop di
   839 000004DC 07                  <1> 	pop es
   840                              <1> 
   841                              <1> 	lvar dword,	original_dst
   842 000004DD 06                  <1> 	 push es
   843 000004DE 57                  <1> 	 push di
   844                              <1> 	lvar dword,	dst
   845 000004DF 06                  <1> 	 push es
   846 000004E0 57                  <1> 	 push di
   847                              <1> 
   848                              <1> %if _ALLOW_OVERLAPPING
   849 000004E1 E8EA05              <1> 	call check_pointers_not_overlapping
   850                              <1> 		; Note:	We initially check here that the write pointer is
   851                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   852                              <1> 		;	Unlike the other decompressors, this check is done
   853                              <1> 		;	 after any copied match or literal too, because
   854                              <1> 		;	 literals can presumably be encoded with less than
   855                              <1> 		;	 one byte of source data to the range decoder.
   856                              <1> d0	mov byte [bp + ?errordata], 1Bh
   857                              <1> .error_CY_a1:
   858 000004E4 7243                <1> 	jc short .error_CY_a
   859                              <1> %else
   860                              <1>  .error_CY_a1 equ .error_CY_a
   861                              <1> %endif
   862                              <1> 
   863                              <1> 
   864                              <1> member_min_size equ lzip_header_size + lzip_trailer_size
   865                              <1> 
   866                              <1> .loop_member:
   867 000004E6 837EE200            <1> 	cmp word [bp + ?length_of_source + 2], 0
   868 000004EA 7504                <1> 	jne @F
   869 000004EC 837EE01A            <1> 	cmp word [bp + ?length_of_source], member_min_size
   870                              <1> @@:
   871 000004F0 770F                <1> 	ja .got_member
   872                              <1> 
   873 000004F2 837EE200            <1> 	cmp word [bp + ?length_of_source + 2], 0
   874 000004F6 7504                <1> 	jne @F
   875 000004F8 837EE00F            <1> 	cmp word [bp + ?length_of_source], 15
   876                              <1> @@:
   877 000004FC 7710                <1> 	ja short .error_NZ_a		; (NZ if jumping)
   878 000004FE E92E04              <1> 	jmp .end
   879                              <1> 
   880                              <1> .got_member:
   881 00000501 C576E8              <1> 	lds si, [bp + ?src]		; ds:si -> lzip_header.magic, .version
   882 00000504 0E                  <1> 	push cs
   883 00000505 07                  <1> 	pop es
   884 00000506 BF[9404]            <1> 	mov di, lzip_header_bytes
   885 00000509 B90500              <1> 	mov cx, lzip_header_bytes.length
   886 0000050C F3A6                <1> 	repe cmpsb
   887                              <1> .error_NZ_a:
   888 0000050E 7403E95004          <1> 	jne .error
   889                              <1> %if _COUNTER && !_PROGRESS
   890                              <1> 	mov al, '#'
   891                              <1> 	call disp_al
   892                              <1> %endif
   893 00000513 31C0                <1> 	xor ax, ax
   894 00000515 AC                  <1> 	lodsb				; ax = lzip_header.coded_dict_size
   895                              <1> 
   896 00000516 1E                  <1> 	 push ds
   897 00000517 56                  <1> 	 push si
   898 00000518 E8DE05              <1> 	call normalise_pointer
   899 0000051B 8F46E8              <1> 	 pop word [bp + ?src]
   900 0000051E 8F46EA              <1> 	 pop word [bp + ?src + 2]
   901 00000521 836EE006            <1> 	sub word [bp + ?length_of_source], 6
   902 00000525 835EE200            <1> 	sbb word [bp + ?length_of_source + 2], 0
   903                              <1> .error_CY_a:
   904 00000529 7235                <1> 	jc short .error_CY_b
   905                              <1> 
   906 0000052B 50                  <1> 	push ax
   907 0000052C 241F                <1> 	and al, 1Fh
   908 0000052E 91                  <1> 	xchg cx, ax			; cx = coded dict size & 1Fh, clobber ax
   909 0000052F B80100              <1> 	mov ax, 1
   910 00000532 31D2                <1> 	xor dx, dx
   911                              <1> @@:
   912 00000534 D1E0                <1> 	shl ax, 1
   913 00000536 D1D2                <1> 	rcl dx, 1
   914 00000538 E2FA                <1> 	loop @B
   915                              <1> 
   916 0000053A 89D3                <1> 	mov bx, dx
   917 0000053C 89C7                <1> 	mov di, ax			; bx:di = dict_size
   918 0000053E B104                <1> 	mov cl, 4
   919                              <1> @@:
   920 00000540 D1EB                <1> 	shr bx, 1
   921 00000542 D1DF                <1> 	rcr di, 1
   922 00000544 E2FA                <1> 	loop @B				; bx:di = dict_size / 16
   923 00000546 59                  <1> 	pop cx
   924 00000547 88CD                <1> 	mov ch, cl
   925 00000549 B105                <1> 	mov cl, 5
   926 0000054B D2ED                <1> 	shr ch, cl
   927 0000054D 88E9                <1> 	mov cl, ch
   928 0000054F B500                <1> 	mov ch, 0
   929 00000551 E331                <1> 	jcxz @FF
   930                              <1> 
   931 00000553 52                  <1> 	push dx
   932 00000554 50                  <1> 	push ax
   933                              <1> 
   934 00000555 89F8                <1> 	mov ax, di			; ax = low word of input
   935 00000557 F7E1                <1> 	mul cx
   936 00000559 93                  <1> 	xchg ax, bx			; ax = high word of input
   937 0000055A 89D7                <1> 	mov di, dx			; di:bx = low word + first high word
   938 0000055C F7E1                <1> 	mul cx				; = high word
   939 0000055E 01C7                <1> 	add di, ax			; add into sum
   940                              <1> .error_CY_b:
   941 00000560 7217                <1> 	jc short .error_CY_c
   942 00000562 85D2                <1> 	test dx, dx			; overflows ?
   943 00000564 7403E9FA03          <1> 	jnz .error
   944                              <1> 					; bx:di = dict_size / 16 * fraction
   945 00000569 58                  <1> 	pop ax
   946 0000056A 5A                  <1> 	pop dx
   947 0000056B 29D8                <1> 	sub ax, bx
   948 0000056D 19FA                <1> 	sbb dx, di
   949 0000056F 7208                <1> 	jc short .error_CY_c
   950                              <1> 
   951 00000571 83FA00              <1> 	cmp dx, min_dictionary_size >> 16
   952 00000574 7503                <1> 	jne @F
   953 00000576 3D0010              <1> 	cmp ax, min_dictionary_size & 0FFFFh
   954                              <1> @@:
   955                              <1> .error_CY_c:
   956 00000579 7273                <1> 	jb short .error_CY_d
   957                              <1> 
   958 0000057B 81FA0020            <1> 	cmp dx, max_dictionary_size >> 16
   959 0000057F 7503                <1> 	jne @F
   960 00000581 83F800              <1> 	cmp ax, max_dictionary_size & 0FFFFh
   961                              <1> @@:
   962 00000584 7603E9DA03          <1> 	ja .error
   963                              <1> 
   964 00000589 C55EE4              <1> 	lds bx, [bp + ?final_dst]
   965 0000058C FF76D6              <1> 	push word [bp + ?dst + 2]
   966 0000058F FF76D4              <1> 	push word [bp + ?dst]
   967 00000592 8F472C              <1> 	pop word [bx + destinationbuffer_constant]
   968 00000595 8F472E              <1> 	pop word [bx + destinationbuffer_constant + 2]
   969                              <1> 
   970                              <1> 
   971                              <1> 		; decode_member start (inlined)
   972                              <1> 		; INP:	?localvariables = ds:bx -> localvariables structure,
   973                              <1> 		;	 destinationbuffer_constant pre-initialised
   974                              <1> 		;	dx:ax = dictionary size
   975                              <1> 		;	Following variables of depack frame initialised:
   976                              <1> 		;	 dword [ss:bp + ?src] -> source buffer
   977                              <1> 		;	 dword [ss:bp + ?length_of_source] = remaining length
   978                              <1> 		;	 dword [ss:bp + ?dst] -> destination buffer
   979                              <1> 		;	 dword [ss:bp + ?length_of_destination] = remaining
   980                              <1> 		; OUT:	NC if success
   981                              <1> 		;	CY if error
   982                              <1> 		; CHG:	all
   983                              <1> ; LZ_decoder.decode_member:
   984                              <1> 
   985 00000598 52                  <1> 	 push dx
   986 00000599 50                  <1> 	 push ax			; preserve dictionary size
   987 0000059A 1E                  <1> 	push ds
   988 0000059B 07                  <1> 	pop es
   989 0000059C 89DF                <1> 	mov di, bx
   990 0000059E B90C00              <1> 	mov cx, fromdwords(dwords(lz_decoder_size)) / 2
   991 000005A1 31C0                <1> 	xor ax, ax
   992 000005A3 F3AB                <1> 	rep stosw			; initialise lz_decoder structure
   993                              <1> 
   994 000005A5 E8EDFC              <1> 	call Range_decoder.init		; initialise embedded range_decoder
   995                              <1> 
   996 000005A8 8F4710              <1> 	 pop word [bx + lz_decoder.dictionary_size]
   997 000005AB 8F4712              <1> 	 pop word [bx + lz_decoder.dictionary_size + 2]
   998                              <1> 					; set dictionary size
   999                              <1> 
  1000 000005AE 8D7F30              <1> 	lea di, [bx + bit_models_start]
  1001 000005B1 B9971C              <1> 	mov cx, (bit_models_end - bit_models_start) / bit_model_size
  1002 000005B4 B80004              <1> 	mov ax, bit_model_total / 2	; initial value for bit_model
  1003                              <1> %if bit_model_size != 2
  1004                              <1>  %error Assuming word size for bit_model_size
  1005                              <1> %endif
  1006 000005B7 F3AB                <1> 	rep stosw			; initialise this bit_model
  1007                              <1> 					; loop for all bit_model and len_model
  1008                              <1> 
  1009 000005B9 8D7F18              <1> 	lea di, [bx + zeros_start]
  1010 000005BC 31C0                <1> 	xor ax, ax
  1011 000005BE B10A                <1> 	mov cl, (zeros_end - zeros_start) / 2
  1012 000005C0 F3AB                <1> 	rep stosw
  1013                              <1> 
  1014                              <1> .loop:
  1015                              <1> %if _COUNTER
  1016 000005C2 FE46FC              <1> 	inc byte [bp + ?counter]
  1017 000005C5 F646FCFF            <1> 	test byte [bp + ?counter], _COUNTER - 1
  1018 000005C9 7505                <1> 	jnz @F
  1019 000005CB B02E                <1> 	mov al, '.'
  1020 000005CD E883FA              <1> 	call disp_al_counter
  1021                              <1> @@:
  1022                              <1> %endif
  1023 000005D0 8B5EE4              <1> 	mov bx, word [bp + ?localvariables]
  1024 000005D3 8B4714              <1> 	mov ax, word [bx + lz_decoder.pos]
  1025 000005D6 83E003              <1> 	and ax, pos_state_mask
  1026 000005D9 91                  <1> 	xchg cx, ax			; cx = pos_state, ax clobbered
  1027 000005DA 894EEC              <1> 	mov word [bp + ?pos_state], cx
  1028                              <1> 
  1029 000005DD 1E                  <1> 	push ds
  1030 000005DE 07                  <1> 	pop es
  1031 000005DF 8D7F30              <1> 	lea di, [bx + bm_match]		; es:di -> bm_match 2D array
  1032 000005E2 B80800              <1> 	mov ax, bit_model_size * pos_states
  1033 000005E5 F76728              <1> 	mul word [bx + state.st]	; dx:ax = first index is state
  1034                              <1> 		; bit_model_size = 2
  1035                              <1> 		; pos_states = 4
  1036                              <1> 		; state.st < 12
  1037                              <1> 		; multiplication 2 * 4 * 11 = 88
  1038                              <1> %if bit_model_size != 2
  1039                              <1>  %error Assuming word size for bit_model_size
  1040                              <1> %endif
  1041 000005E8 01C9                <1> 	add cx, cx			; = second index (from pos_state)
  1042                              <1> 		; pos_state < 4
  1043                              <1> 		; cx < 8
  1044                              <1> 		; ax <= 88
  1045 000005EA 01C8                <1> 	add ax, cx			; = second index is pos_state
  1046 000005EC 01C7                <1> 	add di, ax			; es:di -> bm_match[state()][pos_state]
  1047                              <1> .error_CY_d:
  1048 000005EE 7222                <1> 	jc short .error_CY_1
  1049 000005F0 E816FD              <1> 	call Range_decoder.decode_bit
  1050 000005F3 7244                <1> 	jc .1st_bit_not_zero
  1051                              <1> 
  1052                              <1> .1st_bit_zero:			; literal byte
  1053 000005F5 31C0                <1> 	xor ax, ax
  1054 000005F7 31D2                <1> 	xor dx, dx
  1055 000005F9 E85DFE              <1> 	call LZ_decoder.peek		; al = prev_byte
  1056                              <1> 
  1057 000005FC B105                <1> 	mov cl, 8 - literal_context_bits
  1058 000005FE D2E8                <1> 	shr al, cl			; = literal_state
  1059 00000600 1E                  <1> 	push ds
  1060 00000601 07                  <1> 	pop es
  1061 00000602 8DBFF000            <1> 	lea di, [bx + bm_literal]	; -> 2D array bm_literal
  1062 00000606 B90006              <1> 	mov cx, bit_model_size * 300h
  1063 00000609 F7E1                <1> 	mul cx				; first index is literal_state
  1064 0000060B 85D2                <1> 	test dx, dx
  1065 0000060D F9                  <1> 	stc
  1066 0000060E 7502                <1> 	jnz short .error_CY_1
  1067 00000610 01C7                <1> 	add di, ax			; es:di -> bm_literal[literal_state]
  1068                              <1> .error_CY_1:
  1069 00000612 7232                <1> 	jc short .error_CY_2
  1070                              <1> 
  1071 00000614 E85CFC              <1> 	call State.is_char
  1072 00000617 7308                <1> 	jnc .not_is_char
  1073                              <1> .is_char:
  1074 00000619 B90800              <1> 	mov cx, 8
  1075 0000061C E84FFD              <1> 	call Range_decoder.decode_tree
  1076 0000061F EB10                <1> 	jmp @F
  1077                              <1> 
  1078                              <1> .not_is_char:
  1079 00000621 8B4718              <1> 	mov ax, word [bx + rep0]
  1080 00000624 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1081 00000627 06                  <1> 	push es
  1082 00000628 57                  <1> 	push di
  1083 00000629 E82DFE              <1> 	call LZ_decoder.peek
  1084 0000062C 5F                  <1> 	pop di
  1085 0000062D 07                  <1> 	pop es
  1086 0000062E E87CFD              <1> 	call Range_decoder.decode_matched
  1087                              <1> @@:
  1088 00000631 E86703              <1> 	call LZ_decoder.put_byte
  1089 00000634 E841FC              <1> 	call State.set_char
  1090 00000637 EB89                <1> 	jmp .loop
  1091                              <1> 
  1092                              <1> 
  1093                              <1> .1st_bit_not_zero:		; match or repeated match
  1094 00000639 1E                  <1> 	push ds
  1095 0000063A 07                  <1> 	pop es
  1096 0000063B 8DBF9000            <1> 	lea di, [bx + bm_rep]		; es:di -> bm_rep array
  1097                              <1> %if bit_model_size != 2
  1098                              <1>  %error Assuming word size for bit_model_size
  1099                              <1> %endif
  1100 0000063F 8B4728              <1> 	mov ax, word [bx + state.st]
  1101 00000642 01C0                <1> 	add ax, ax			; ax = index is state
  1102                              <1> 	; jc short .error_CY_2	; (state.st is always < 12)
  1103 00000644 01C7                <1> 	add di, ax			; es:di -> bm_rep[state()]
  1104                              <1> .error_CY_2:
  1105 00000646 7230                <1> 	jc short .error_CY_3
  1106 00000648 E8BEFC              <1> 	call Range_decoder.decode_bit
  1107 0000064B 7203E9EA00          <1> 	jnc .2nd_bit_zero
  1108                              <1> 
  1109                              <1> .2nd_bit_not_zero:
  1110 00000650 1E                  <1> 	push ds
  1111 00000651 07                  <1> 	pop es
  1112 00000652 8DBFA800            <1> 	lea di, [bx + bm_rep0]		; es:di -> bm_rep0 array
  1113                              <1> %if bit_model_size != 2
  1114                              <1>  %error Assuming word size for bit_model_size
  1115                              <1> %endif
  1116 00000656 8B4728              <1> 	mov ax, word [bx + state.st]
  1117 00000659 01C0                <1> 	add ax, ax			; ax = index is state
  1118                              <1> 	; jc short .error_CY_3	; (state.st is always < 12)
  1119 0000065B 01C7                <1> 	add di, ax			; es:di -> bm_rep0[state()]
  1120 0000065D 7219                <1> 	jc short .error_CY_3
  1121 0000065F E8A7FC              <1> 	call Range_decoder.decode_bit
  1122 00000662 7233                <1> 	jc .3rd_bit_not_zero
  1123                              <1> 
  1124                              <1> .3rd_bit_zero:
  1125 00000664 1E                  <1> 	push ds
  1126 00000665 07                  <1> 	pop es
  1127 00000666 8DBFF030            <1> 	lea di, [bx + bm_len]		; es:di -> bm_len 2D array
  1128 0000066A B80800              <1> 	mov ax, bit_model_size * pos_states
  1129                              <1> 				; (2 * 4 = 8)
  1130 0000066D F76728              <1> 	mul word [bx + state.st]; (< 12)
  1131                              <1> 					; dx:ax = first index is state
  1132                              <1> 	; test dx, dx
  1133                              <1> 	; stc
  1134                              <1> 	; jnz short .error_CY_3	; (dx:ax is always < 12 * 8)
  1135                              <1> %if bit_model_size != 2
  1136                              <1>  %error Assuming word size for bit_model_size
  1137                              <1> %endif
  1138                              <1> %rep bit_model_size
  1139                              <1> 	add ax, word [bp + ?pos_state]
  1140                              <1> 	; jc short .error_CY_3	; (pos_state is always < 4
  1141                              <1> 				;  and state_st is always < 12
  1142                              <1> 				;  and ax is < 12 * 8 prior to adding)
  1143                              <1> %endrep
  1139 00000670 0346EC              <2>  add ax, word [bp + ?pos_state]
  1140                              <2> 
  1141                              <2> 
  1142                              <2> 
  1139 00000673 0346EC              <2>  add ax, word [bp + ?pos_state]
  1140                              <2> 
  1141                              <2> 
  1142                              <2> 
  1144 00000676 01C7                <1> 	add di, ax			; es:di -> bm_len[state()]
  1145                              <1> .error_CY_3:
  1146 00000678 722A                <1> 	jc short .error_CY_4
  1147 0000067A E88CFC              <1> 	call Range_decoder.decode_bit
  1148 0000067D 7303E99500          <1> 	jc .4th_bit_not_zero
  1149                              <1> 
  1150                              <1> .4th_bit_zero:
  1151                              <1> ; State.set_short_rep
  1152 00000682 B8090B              <1> 	mov ax, 9 | (11 << 8)
  1153 00000685 E804FC              <1> 	call State.select
  1154                              <1> 
  1155 00000688 8B4718              <1> 	mov ax, word [bx + rep0]
  1156 0000068B 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1157 0000068E E8C8FD              <1> 	call LZ_decoder.peek
  1158 00000691 E80703              <1> 	call LZ_decoder.put_byte
  1159 00000694 E92BFF              <1> 	jmp .loop
  1160                              <1> 
  1161                              <1> .3rd_bit_not_zero:
  1162 00000697 1E                  <1> 	push ds
  1163 00000698 07                  <1> 	pop es
  1164 00000699 8DBFC000            <1> 	lea di, [bx + bm_rep1]		; es:di -> bm_rep1 array
  1165                              <1> %if bit_model_size != 2
  1166                              <1>  %error Assuming word size for bit_model_size
  1167                              <1> %endif
  1168 0000069D 8B4728              <1> 	mov ax, word [bx + state.st]
  1169 000006A0 01C0                <1> 	add ax, ax			; ax = index is state
  1170                              <1> 	; jc short .error_CY_4	; (state.st is always < 12)
  1171 000006A2 01C7                <1> 	add di, ax			; es:di -> bm_rep1[state()]
  1172                              <1> .error_CY_4:
  1173 000006A4 7220                <1> 	jc short .error_CY_4a
  1174 000006A6 E860FC              <1> 	call Range_decoder.decode_bit
  1175 000006A9 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero
  1176                              <1> 
  1177                              <1> .3rd_bit_not_zero.4th_bit_zero:
  1178 000006AB FF771E              <1> 	push word [bx + rep1 + 2]
  1179 000006AE FF771C              <1> 	push word [bx + rep1]
  1180 000006B1 8F46F8              <1> 	pop word [bp + ?distance]
  1181 000006B4 8F46FA              <1> 	pop word [bp + ?distance + 2]
  1182 000006B7 EB46                <1> 	jmp .3rd_bit_not_zero.common
  1183                              <1> 
  1184                              <1> .3rd_bit_not_zero.4th_bit_not_zero:
  1185 000006B9 1E                  <1> 	push ds
  1186 000006BA 07                  <1> 	pop es
  1187 000006BB 8DBFD800            <1> 	lea di, [bx + bm_rep2]		; es:di -> bm_rep2 array
  1188                              <1> %if bit_model_size != 2
  1189                              <1>  %error Assuming word size for bit_model_size
  1190                              <1> %endif
  1191 000006BF 8B4728              <1> 	mov ax, word [bx + state.st]
  1192 000006C2 01C0                <1> 	add ax, ax			; ax = index is state
  1193                              <1> 	; jc short .error_CY_5	; (state.st is always < 12)
  1194 000006C4 01C7                <1> 	add di, ax			; es:di -> bm_rep2[state()]
  1195                              <1> .error_CY_4a:
  1196 000006C6 7267                <1> 	jc short .error_CY_5
  1197 000006C8 E83EFC              <1> 	call Range_decoder.decode_bit
  1198 000006CB 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero
  1199                              <1> 
  1200                              <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_zero:
  1201 000006CD FF7722              <1> 	push word [bx + rep2 + 2]
  1202 000006D0 FF7720              <1> 	push word [bx + rep2]
  1203 000006D3 8F46F8              <1> 	pop word [bp + ?distance]
  1204 000006D6 8F46FA              <1> 	pop word [bp + ?distance + 2]
  1205 000006D9 EB18                <1> 	jmp .3rd_bit_not_zero.4th_bit_not_zero.common
  1206                              <1> 
  1207                              <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero:
  1208 000006DB FF7726              <1> 	push word [bx + rep3 + 2]
  1209 000006DE FF7724              <1> 	push word [bx + rep3]
  1210 000006E1 8F46F8              <1> 	pop word [bp + ?distance]
  1211 000006E4 8F46FA              <1> 	pop word [bp + ?distance + 2]	; distance = rep3
  1212 000006E7 FF7722              <1> 	push word [bx + rep2 + 2]
  1213 000006EA FF7720              <1> 	push word [bx + rep2]
  1214 000006ED 8F4724              <1> 	pop word [bx + rep3]
  1215 000006F0 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  1216                              <1> 
  1217                              <1> .3rd_bit_not_zero.4th_bit_not_zero.common:
  1218 000006F3 FF771E              <1> 	push word [bx + rep1 + 2]
  1219 000006F6 FF771C              <1> 	push word [bx + rep1]
  1220 000006F9 8F4720              <1> 	pop word [bx + rep2]
  1221 000006FC 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  1222                              <1> 
  1223                              <1> .3rd_bit_not_zero.common:
  1224 000006FF FF771A              <1> 	push word [bx + rep0 + 2]
  1225 00000702 FF7718              <1> 	push word [bx + rep0]
  1226 00000705 8F471C              <1> 	pop word [bx + rep1]
  1227 00000708 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  1228 0000070B FF76FA              <1> 	push word [bp + ?distance + 2]
  1229 0000070E FF76F8              <1> 	push word [bp + ?distance]
  1230 00000711 8F4718              <1> 	pop word [bx + rep0]
  1231 00000714 8F471A              <1> 	pop word [bx + rep0 + 2]	; rep0 = distance
  1232                              <1> 
  1233                              <1> .4th_bit_not_zero:
  1234                              <1> ; State.set_rep
  1235 00000717 B8080B              <1> 	mov ax, 8 | (11 << 8)
  1236 0000071A E86FFB              <1> 	call State.select
  1237                              <1> 
  1238 0000071D 8B46EC              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  1239 00000720 1E                  <1> 	push ds
  1240 00000721 07                  <1> 	pop es
  1241 00000722 8DBFDA36            <1> 	lea di, [bx + rep_len_model]	; -> len_model to use
  1242 00000726 E8CFFC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  1243 00000729 83C002              <1> 	add ax, min_match_len
  1244 0000072C 83D200              <1> 	adc dx, 0
  1245                              <1> .error_CY_5:
  1246 0000072F 7250                <1> 	jc short .error_CY_6
  1247 00000731 8946F4              <1> 	mov word [bp + ?len], ax
  1248 00000734 8956F6              <1> 	mov word [bp + ?len + 2], dx
  1249 00000737 E93001              <1> 	jmp .handle_match
  1250                              <1> 
  1251                              <1> .2nd_bit_zero:			; match
  1252 0000073A FF7722              <1> 	push word [bx + rep2 + 2]
  1253 0000073D FF7720              <1> 	push word [bx + rep2]
  1254 00000740 8F4724              <1> 	pop word [bx + rep3]
  1255 00000743 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  1256                              <1> 
  1257 00000746 FF771E              <1> 	push word [bx + rep1 + 2]
  1258 00000749 FF771C              <1> 	push word [bx + rep1]
  1259 0000074C 8F4720              <1> 	pop word [bx + rep2]
  1260 0000074F 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  1261                              <1> 
  1262 00000752 FF771A              <1> 	push word [bx + rep0 + 2]
  1263 00000755 FF7718              <1> 	push word [bx + rep0]
  1264 00000758 8F471C              <1> 	pop word [bx + rep1]
  1265 0000075B 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  1266                              <1> 
  1267 0000075E 8B46EC              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  1268 00000761 1E                  <1> 	push ds
  1269 00000762 07                  <1> 	pop es
  1270 00000763 8DBF5634            <1> 	lea di, [bx + match_len_model]	; -> len_model to use
  1271 00000767 E88EFC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  1272                              <1> 
  1273 0000076A 8946EE              <1> 	mov word [bp + ?len_state], ax
  1274 0000076D 85D2                <1> 	test dx, dx
  1275 0000076F 7505                <1> 	jnz @F
  1276 00000771 83F803              <1> 	cmp ax, len_states - 1
  1277 00000774 7205                <1> 	jb @FF
  1278                              <1> @@:
  1279 00000776 C746EE0300          <1> 	mov word [bp + ?len_state], len_states - 1
  1280                              <1> @@:
  1281                              <1> 
  1282 0000077B 83C002              <1> 	add ax, min_match_len
  1283 0000077E 83D200              <1> 	adc dx, 0
  1284                              <1> .error_CY_6:
  1285 00000781 723C                <1> 	jc short .error_CY_7
  1286                              <1> 
  1287 00000783 8946F4              <1> 	mov word [bp + ?len], ax
  1288 00000786 8956F6              <1> 	mov word [bp + ?len + 2], dx
  1289                              <1> 
  1290 00000789 1E                  <1> 	push ds
  1291 0000078A 07                  <1> 	pop es
  1292 0000078B 8DBF5031            <1> 	lea di, [bx + bm_dis_slot]	; -> 2D array bm_dis_slot
  1293                              <1> 
  1294 0000078F B88000              <1> 	mov ax, bit_model_size * (1 << dis_slot_bits)
  1295 00000792 F766EE              <1> 	mul word [bp + ?len_state]	; first index is len_state
  1296                              <1> 		; bit_model_size = 2
  1297                              <1> 		; 1 << dis_slot_bits = 1 << 6 = 64
  1298                              <1> 		; ?len_state < 4
  1299                              <1> 		; multiplication 2 * 64 * 3 = 384
  1300                              <1> 					; dx:ax = first index into array
  1301 00000795 01C7                <1> 	add di, ax			; -> 1D array at bm_dis_slot[len_state]
  1302 00000797 B90600              <1> 	mov cx, dis_slot_bits
  1303 0000079A E8D1FB              <1> 	call Range_decoder.decode_tree
  1304 0000079D 894718              <1> 	mov word [bx + rep0], ax
  1305 000007A0 89571A              <1> 	mov word [bx + rep0 + 2], dx
  1306                              <1> 
  1307 000007A3 85D2                <1> 	test dx, dx			; (same flags as cmp dx, 0)
  1308 000007A5 7503                <1> 	jne @F
  1309 000007A7 83F804              <1> 	cmp ax, start_dis_model
  1310                              <1> @@:
  1311 000007AA 7303E99B00          <1> 	jnae .not_rep0_ae_start_dis_model
  1312                              <1> 
  1313                              <1> .rep0_ae_start_dis_model:
  1314 000007AF 8946F0              <1> 	mov word [bp + ?dis_slot], ax
  1315 000007B2 8956F2              <1> 	mov word [bp + ?dis_slot + 2], dx
  1316                              <1> 
  1317 000007B5 D1EA                <1> 	shr dx, 1
  1318 000007B7 D1D8                <1> 	rcr ax, 1			; dis_slot >> 1
  1319 000007B9 83E801              <1> 	sub ax, 1
  1320 000007BC 83DA00              <1> 	sbb dx, 0			; - 1
  1321                              <1> .error_CY_7:
  1322                              <1> .error_CY_8:
  1323 000007BF 7230                <1> 	jc short .error_CY_9
  1324 000007C1 F9                  <1> 	stc
  1325 000007C2 752D                <1> 	jnz short .error_CY_9
  1326 000007C4 91                  <1> 	xchg cx, ax			; cx = direct_bits, clobber ax
  1327 000007C5 31D2                <1> 	xor dx, dx
  1328 000007C7 B80100              <1> 	mov ax, 1
  1329 000007CA 2246F0              <1> 	and al, byte [bp + ?dis_slot]
  1330 000007CD 0C02                <1> 	or al, 2
  1331 000007CF 51                  <1> 	push cx
  1332 000007D0 E306                <1> 	jcxz @FF
  1333                              <1> @@:
  1334 000007D2 D1E0                <1> 	shl ax, 1
  1335 000007D4 D1D2                <1> 	rcl dx, 1
  1336 000007D6 E2FA                <1> 	loop @B
  1337                              <1> @@:
  1338 000007D8 59                  <1> 	pop cx
  1339 000007D9 894718              <1> 	mov word [bx + rep0], ax
  1340 000007DC 89571A              <1> 	mov word [bx + rep0 + 2], dx
  1341                              <1> 
  1342 000007DF 837EF200            <1> 	cmp word [bp + ?dis_slot + 2], 0
  1343 000007E3 7504                <1> 	jne @F
  1344 000007E5 837EF00E            <1> 	cmp word [bp + ?dis_slot], end_dis_model
  1345                              <1> @@:
  1346 000007E9 7328                <1> 	jnb .not_dis_slot_below_end_dis_model
  1347                              <1> 
  1348                              <1> .dis_slot_below_end_dis_model:
  1349 000007EB 2B46F0              <1> 	sub ax, word [bp + ?dis_slot]
  1350 000007EE 1B56F2              <1> 	sbb dx, word [bp + ?dis_slot + 2]
  1351                              <1> 					; dx:ax = index into bm_dis array
  1352                              <1> 					;  = rep0 - dis_slot
  1353                              <1> .error_CY_9:
  1354 000007F1 722D                <1> 	jc short .error_CY_10
  1355                              <1> 
  1356                              <1> %if bit_model_size != 2
  1357                              <1>  %error Assuming word size for bit_model_size
  1358                              <1> %endif
  1359 000007F3 01C0                <1> 	add ax, ax
  1360 000007F5 11D2                <1> 	adc dx, dx			; dx:ax *= 2
  1361 000007F7 7227                <1> 	jc short .error_CY_10
  1362 000007F9 F9                  <1> 	stc
  1363 000007FA 7524                <1> 	jnz short .error_CY_10		; if dx != 0 -->
  1364 000007FC 1E                  <1> 	push ds
  1365 000007FD 07                  <1> 	pop es
  1366 000007FE 8DBF5033            <1> 	lea di, [bx + bm_dis]		; es:di -> bm_dis array
  1367 00000802 01C7                <1> 	add di, ax			; index into the array
  1368 00000804 721A                <1> 	jc short .error_CY_10
  1369 00000806 E891FB              <1> 	call Range_decoder.decode_tree_reversed
  1370 00000809 014718              <1> 	add word [bx + rep0], ax
  1371 0000080C 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1372 0000080F 720F                <1> 	jc short .error_CY_10
  1373 00000811 EB37                <1> 	jmp .after_dis_slot_below
  1374                              <1> 
  1375                              <1> .not_dis_slot_below_end_dis_model:
  1376 00000813 83E904              <1> 	sub cx, dis_align_bits
  1377 00000816 E8BDFA              <1> 	call Range_decoder.decode
  1378 00000819 B90400              <1> 	mov cx, dis_align_bits
  1379                              <1> @@:
  1380 0000081C D1E0                <1> 	shl ax, 1
  1381 0000081E D1D2                <1> 	rcl dx, 1
  1382                              <1> .error_CY_10:
  1383 00000820 721A                <1> 	jc short .error_CY_11
  1384 00000822 E2F8                <1> 	loop @B
  1385 00000824 014718              <1> 	add word [bx + rep0], ax
  1386 00000827 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1387                              <1> 
  1388 0000082A B90400              <1> 	mov cx, dis_align_bits
  1389 0000082D 1E                  <1> 	push ds
  1390 0000082E 07                  <1> 	pop es
  1391 0000082F 8DBF3634            <1> 	lea di, [bx + bm_align]
  1392 00000833 E864FB              <1> 	call Range_decoder.decode_tree_reversed
  1393 00000836 014718              <1> 	add word [bx + rep0], ax
  1394 00000839 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1395                              <1> .error_CY_11:
  1396 0000083C 727D                <1> 	jc .error_CY_12
  1397                              <1> 
  1398 0000083E 837F1AFF            <1> 	cmp word [bx + rep0 + 2], -1	; rep0 = 0FFFF_FFFFh ?
  1399 00000842 7504                <1> 	jne @F
  1400 00000844 837F18FF            <1> 	cmp word [bx + rep0], -1
  1401                              <1> @@:
  1402 00000848 7479                <1> 	je .end_member			; yes, end (marker found) -->
  1403                              <1> 
  1404                              <1> .after_dis_slot_below:
  1405                              <1> 
  1406                              <1> .not_rep0_ae_start_dis_model:
  1407                              <1> 
  1408                              <1> ; State.set_match
  1409 0000084A B8070A              <1> 	mov ax, 7 | (10 << 8)
  1410 0000084D E83CFA              <1> 	call State.select
  1411                              <1> 
  1412 00000850 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1413 00000853 8B4718              <1> 	mov ax, word [bx + rep0]
  1414                              <1> 
  1415 00000856 3B5712              <1> 	cmp dx, word [bx + lz_decoder.dictionary_size + 2]
  1416 00000859 7503                <1> 	jne @F
  1417 0000085B 3B4710              <1> 	cmp ax, word [bx + lz_decoder.dictionary_size]
  1418                              <1> @@:
  1419 0000085E 7308                <1> 	jae short .error_AE_1
  1420                              <1> 
  1421                              <1> 		; check for (rep0 >= pos && !pos_wrapped)
  1422                              <1> 		;  (pos_wrapped is always false for us)
  1423 00000860 3B5716              <1> 	cmp dx, word [bx + lz_decoder.pos + 2]
  1424 00000863 7503                <1> 	jne @F
  1425 00000865 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  1426                              <1> @@:
  1427                              <1> .error_AE_1:
  1428 00000868 7356                <1> 	jae short .error_1
  1429                              <1> 
  1430                              <1> .handle_match:
  1431 0000086A 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1432 0000086D 8B4718              <1> 	mov ax, word [bx + rep0]
  1433                              <1> 
  1434 00000870 E8FDFB              <1> 	call calculate_peek_pointer_disi
  1435                              <1> 
  1436 00000873 8B46F4              <1> 	mov ax, word [bp + ?len]
  1437 00000876 8B56F6              <1> 	mov dx, word [bp + ?len + 2]	; dx:ax = length
  1438                              <1> 
  1439                              <1> 
  1440                              <1> 		; INP:	dx:ax = length of match
  1441                              <1> 		;	di:si -> source (normalised)
  1442                              <1> 		;	ds:bx -> local variables structure
  1443                              <1> 		;	ss:bp -> depack stack frame,
  1444                              <1> 		;		with ?length_of_destination, ?dst
  1445                              <1> 		; OUT:	NC if success,
  1446                              <1> 		;	 ?length_of_destination and ?dst updated
  1447                              <1> 		;	CY if error
  1448                              <1> 		;	 (destination buffer too small or overlap error)
  1449                              <1> 		;	! may jump to depack.end if ?dst_max_segment reached
  1450                              <1> 		; CHG:	ax, cx, dx, di, si, es
  1451                              <1> ; handle_match:
  1452 00000879 014714              <1> 	add word [bx + lz_decoder.pos], ax
  1453 0000087C 115716              <1> 	adc word [bx + lz_decoder.pos + 2], dx
  1454 0000087F 723A                <1> 	jc short .error_CY_12		; (CY) -->
  1455                              <1> 
  1456 00000881 2946DC              <1> 	sub word [bp + ?length_of_destination], ax
  1457 00000884 1956DE              <1> 	sbb word [bp + ?length_of_destination + 2], dx
  1458                              <1> 					; enough space left ?
  1459 00000887 7232                <1> 	jb short .error_CY_12		; no --> (below == CY)
  1460                              <1> 
  1461 00000889 1E                  <1> 	push ds
  1462                              <1> 
  1463 0000088A 8EDF                <1> 	mov ds, di			; ds:si -> source
  1464 0000088C C47ED4              <1> 	les di, [bp + ?dst]		; es:di -> destination
  1465                              <1> .hm_loop:
  1466 0000088F B9F0FF              <1> 	mov cx, 64 * 1024 - 16		; block size
  1467                              <1> 		; If both pointers are normalised, moving 0FFF0h bytes is
  1468                              <1> 		;  valid and results in a maximum offset of 0FFFFh in either.
  1469                              <1> 
  1470 00000892 85D2                <1> 	test dx, dx			; >= 1_0000h ?
  1471 00000894 7508                <1> 	jnz @F				; yes, full block -->
  1472 00000896 85C0                <1> 	test ax, ax			; == 0 ?
  1473 00000898 7415                <1> 	jz .hm_end			; yes, done -->
  1474 0000089A 39C8                <1> 	cmp ax, cx			; can move in one (last) block ?
  1475 0000089C 7607                <1> 	jbe .hm_last			; yes -->
  1476                              <1> @@:
  1477                              <1> 					; no, move one block and continue
  1478 0000089E 29C8                <1> 	sub ax, cx
  1479 000008A0 83DA00              <1> 	sbb dx, 0			; left over remaining
  1480 000008A3 EB03                <1> 	jmp .hm_copy
  1481                              <1> 
  1482                              <1> .hm_last:
  1483 000008A5 91                  <1> 	xchg cx, ax			; cx = remaining length
  1484 000008A6 31C0                <1> 	xor ax, ax			; no more remaining
  1485                              <1> 
  1486                              <1> .hm_copy:
  1487 000008A8 F3A4                <1> 	rep movsb			; move one block (full or partial)
  1488                              <1> 
  1489 000008AA E83D02              <1> 	call normalise_both_pointers
  1490 000008AD EBE0                <1> 	jmp .hm_loop
  1491                              <1> 
  1492                              <1> .hm_end:
  1493 000008AF 897ED4              <1> 	mov word [bp + ?dst], di
  1494 000008B2 8C46D6              <1> 	mov word [bp + ?dst + 2], es
  1495                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
  1496                              <1> 	mov ax, es
  1497                              <1> 	cmp ax, word [bp + ?dst_max_segment]
  1498                              <1> 	jae depack.end
  1499                              <1> 		; note that we have the depack stack frame pointed to by
  1500                              <1> 		;  ss:bp here, which is needed for running depack.end
  1501                              <1> %endif
  1502 000008B5 1F                  <1> 	pop ds
  1503                              <1> %if _ALLOW_OVERLAPPING
  1504 000008B6 53                  <1> 	push bx
  1505 000008B7 E81402              <1> 	call check_pointers_not_overlapping
  1506 000008BA 5B                  <1> 	pop bx				; returns CF
  1507                              <1> .error_CY_12:
  1508 000008BB 7203                <1> 	jc short .error_1
  1509                              <1> %endif
  1510 000008BD E902FD              <1> 	jmp .loop
  1511                              <1> 
  1512                              <1> %if ! _ALLOW_OVERLAPPING
  1513                              <1> .error_CY_12:
  1514                              <1> %endif
  1515                              <1> .error_1:
  1516 000008C0 E9A000              <1> 	jmp .error
  1517                              <1> 
  1518                              <1> 
  1519                              <1> .end_member:			; End Of Stream marker
  1520 000008C3 837EF600            <1> 	cmp word [bp + ?len + 2], min_match_len >> 16
  1521 000008C7 7504                <1> 	jne @F
  1522 000008C9 837EF402            <1> 	cmp word [bp + ?len], min_match_len & 0FFFFh
  1523                              <1> @@:
  1524 000008CD 75F1                <1> 	jne short .error_1
  1525                              <1> 
  1526                              <1> 		; decode_member succeeded
  1527                              <1> 
  1528 000008CF C55EE4              <1> 	lds bx, [bp + ?final_dst]	; -> localvariables
  1529                              <1> 
  1530 000008D2 836EE014            <1> 	sub word [bp + ?length_of_source], lzip_trailer_size
  1531 000008D6 835EE200            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1532 000008DA 7303E98400          <1> 	jc .error
  1533                              <1> 
  1534 000008DF C476E8              <1> 	les si, [bp + ?src]	; es:si -> lzip_trailer.uncompressed_checksum
  1535 000008E2 83C604              <1> 	add si, 4			; skip CRC
  1536                              <1> 
  1537                              <1> 				; es:si -> lzip_trailer.uncompressed_size
  1538 000008E5 26AD                <1> 	es lodsw			; does the destination length match ?
  1539 000008E7 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  1540 000008EA 7577                <1> 	jne .error
  1541 000008EC 26AD                <1> 	es lodsw
  1542 000008EE 3B4716              <1> 	cmp ax, word [bx + lz_decoder.pos + 2]
  1543 000008F1 7570                <1> 	jne .error			; if no -->
  1544 000008F3 26AD                <1> 	es lodsw
  1545 000008F5 85C0                <1> 	test ax, ax
  1546 000008F7 756A                <1> 	jnz .error
  1547 000008F9 26AD                <1> 	es lodsw
  1548 000008FB 85C0                <1> 	test ax, ax
  1549 000008FD 7564                <1> 	jnz .error
  1550                              <1> 
  1551 000008FF 830714              <1> 	add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size
  1552 00000902 83570200            <1> 	adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0
  1553 00000906 725B                <1> 	jc .error
  1554                              <1> 
  1555                              <1> 				; es:si -> lzip_trailer.member_size
  1556 00000908 26AD                <1> 	es lodsw			; does the source length match ?
  1557 0000090A 3B07                <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos]
  1558 0000090C 7555                <1> 	jne .error
  1559 0000090E 26AD                <1> 	es lodsw
  1560 00000910 3B4702              <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2]
  1561 00000913 754E                <1> 	jne .error
  1562 00000915 26AD                <1> 	es lodsw
  1563 00000917 85C0                <1> 	test ax, ax
  1564 00000919 7548                <1> 	jnz .error
  1565 0000091B 26AD                <1> 	es lodsw
  1566 0000091D 85C0                <1> 	test ax, ax
  1567 0000091F 7542                <1> 	jnz .error
  1568                              <1> 
  1569                              <1> 				; es:si -> behind lzip_trailer
  1570 00000921 06                  <1> 	 push es
  1571 00000922 56                  <1> 	 push si
  1572 00000923 E8D301              <1> 	call normalise_pointer
  1573 00000926 8F46E8              <1> 	 pop word [bp + ?src]
  1574 00000929 8F46EA              <1> 	 pop word [bp + ?src + 2]
  1575                              <1> 
  1576 0000092C E9B7FB              <1> 	jmp .loop_member
  1577                              <1> 
  1578                              <1> .end:
  1579                              <1> 
  1580                              <1> .final:
  1581                              <1> %if _COUNTER && !_PROGRESS
  1582                              <1> 	mov al, '%'
  1583                              <1> 	call disp_al
  1584                              <1> %endif
  1585 0000092F C47EE4              <1> 	les di, [bp + ?final_dst]
  1586                              <1> 				; -> destination
  1587 00000932 C576D8              <1> 	lds si, [bp + ?original_dst]
  1588                              <1> 				; -> source
  1589 00000935 1E                  <1> 	 push ds
  1590 00000936 56                  <1> 	 push si
  1591 00000937 E81002              <1> 	call pointer_to_linear	; dx:ax = linear ?original_dst
  1592 0000093A 91                  <1> 	xchg cx, ax
  1593 0000093B 87DA                <1> 	xchg bx, dx		; bx:cx = linear ?original_dst, clobber dx:ax
  1594 0000093D FF76D6              <1> 	 push word [bp + ?dst + 2]
  1595 00000940 FF76D4              <1> 	 push word [bp + ?dst]
  1596 00000943 E80402              <1> 	call pointer_to_linear
  1597 00000946 29C8                <1> 	sub ax, cx
  1598 00000948 19DA                <1> 	sbb dx, bx		; = linear dst minus linear original_dst
  1599                              <1> 
  1600 0000094A B90400              <1> 	mov cx, 4
  1601 0000094D 83C00F              <1> 	add ax, 15
  1602 00000950 83D200              <1> 	adc dx, 0
  1603                              <1> @@:
  1604 00000953 D1EA                <1> 	shr dx, 1
  1605 00000955 D1D8                <1> 	rcr ax, 1
  1606 00000957 E2FA                <1> 	loop @B
  1607 00000959 89C1                <1> 	mov cx, ax
  1608 0000095B 85D2                <1> 	test dx, dx
  1609                              <1> d0	mov byte [bp + ?errordata], 84h
  1610 0000095D 7504                <1> 	jnz .error
  1611                              <1> 
  1612 0000095F E8D400              <1> 	call x_mov_p
  1613                              <1> 
  1614 00000962 A8                  <1> 	db __TEST_IMM8			; (NC)
  1615                              <1> .error:
  1616 00000963 F9                  <1> 	stc
  1617                              <1> 
  1618                              <1> %if _COUNTER
  1619 00000964 9F                  <1> 	lahf
  1620 00000965 B00D                <1> 	mov al, 13
  1621 00000967 E8C0F8              <1> 	call disp_al_for_progress
  1622 0000096A B00A                <1> 	mov al, 10
  1623 0000096C E8BBF8              <1> 	call disp_al_for_progress
  1624 0000096F 9E                  <1> 	sahf
  1625                              <1> %endif
  1626                              <1> d0	mov bx, word [bp + ?errordata]
  1627 00000970 89EC5D              <1> 	lleave code
  1628 00000973 C3                  <1> 	lret
  1629                              <1> 
  1630                              <1> 
  1631                              <1> 		; INP:	ds:bx -> range_decoder structure
  1632                              <1> 		;	ss:bp -> depack stack frame
  1633                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1634                              <1> 		;	If success,
  1635                              <1> 		;	 al = byte read
  1636                              <1> 		; CHG:	-
  1637                              <1> Range_decoder.get_byte:
  1638 00000974 830701              <1> 	add word [bx + range_decoder.member_pos], 1
  1639 00000977 83570200            <1> 	adc word [bx + range_decoder.member_pos + 2], 0
  1640 0000097B 72E6                <1> 	jc short .error
  1641                              <1> 
  1642                              <1> 		; INP:	ds:bx -> range_decoder structure
  1643                              <1> 		;	ss:bp -> depack stack frame
  1644                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1645                              <1> 		;	If success,
  1646                              <1> 		;	 al = value read
  1647                              <1> 		; CHG:	-
  1648                              <1> ; get_byte:
  1649 0000097D 1E                  <1> 	push ds
  1650 0000097E 56                  <1> 	push si
  1651                              <1> 
  1652 0000097F 836EE001            <1> 	sub word [bp + ?length_of_source], 1
  1653 00000983 835EE200            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1654 00000987 72DA                <1> 	jc short .error
  1655                              <1> 
  1656 00000989 C576E8              <1> 	lds si, [bp + ?src]
  1657 0000098C AC                  <1> 	lodsb
  1658 0000098D 1E                  <1> 	 push ds
  1659 0000098E 56                  <1> 	 push si
  1660 0000098F E86701              <1> 	call normalise_pointer
  1661 00000992 8F46E8              <1> 	 pop word [bp + ?src]
  1662 00000995 8F46EA              <1> 	 pop word [bp + ?src + 2]
  1663 00000998 5E                  <1> 	pop si
  1664 00000999 1F                  <1> 	pop ds
  1665 0000099A C3                  <1> 	retn
  1666                              <1> 
  1667                              <1> .error: equ depack.error
  1668                              <1> 
  1669                              <1> 
  1670                              <1> 		; INP:	ds:bx -> lz_decoder structure
  1671                              <1> 		;	al = byte to write to buffer
  1672                              <1> 		;	ss:bp -> depack stack frame
  1673                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1674                              <1> 		; CHG:	cx, dx, ax, di, es
  1675                              <1> LZ_decoder.put_byte:
  1676 0000099B C47ED4              <1> 	les di, [bp + ?dst]
  1677                              <1> 
  1678 0000099E 83471401            <1> 	add word [bx + lz_decoder.pos], 1
  1679 000009A2 83571600            <1> 	adc word [bx + lz_decoder.pos + 2], 0
  1680 000009A6 72BB                <1> 	jc short .error
  1681                              <1> 
  1682 000009A8 836EDC01            <1> 	sub word [bp + ?length_of_destination], 1
  1683 000009AC 835EDE00            <1> 	sbb word [bp + ?length_of_destination + 2], 0
  1684 000009B0 72B1                <1> 	jb short .error
  1685                              <1> 
  1686 000009B2 AA                  <1> 	stosb
  1687 000009B3 06                  <1> 	 push es
  1688 000009B4 57                  <1> 	 push di
  1689 000009B5 E84101              <1> 	call normalise_pointer
  1690 000009B8 8F46D4              <1> 	 pop word [bp + ?dst]
  1691 000009BB 8F46D6              <1> 	 pop word [bp + ?dst + 2]
  1692                              <1> 
  1693                              <1> %if _ALLOW_OVERLAPPING
  1694 000009BE 53                  <1> 	push bx
  1695 000009BF E80C01              <1> 	call check_pointers_not_overlapping
  1696 000009C2 5B                  <1> 	pop bx			; returns CF
  1697 000009C3 729E                <1> 	jc short .error
  1698                              <1> %endif
  1699 000009C5 C3                  <1> 	retn
  1700                              <1> 
  1701                              <1> .error: equ depack.error
  1702                              <1> 
  1703                              <1> 
  1704                              <1> 		; INP:	ds:si = pointer
  1705                              <1> 		;	es:di = pointer
  1706                              <1> 		; OUT:	ds:si anti normalised
  1707                              <1> 		;	es:di anti normalised
  1708                              <1> anti_normalise_both_pointers:
  1709 000009C6 1E                  <1> 	 push ds
  1710 000009C7 56                  <1> 	 push si
  1711 000009C8 E80A00              <1> 	call anti_normalise_pointer
  1712 000009CB 5E                  <1> 	 pop si
  1713 000009CC 1F                  <1> 	 pop ds
  1714                              <1> 
  1715 000009CD 06                  <1> 	 push es
  1716 000009CE 57                  <1> 	 push di
  1717 000009CF E80300              <1> 	call anti_normalise_pointer
  1718 000009D2 5F                  <1> 	 pop di
  1719 000009D3 07                  <1> 	 pop es
  1720 000009D4 C3                  <1> 	retn
  1721                              <1> 
  1722                              <1> 
  1723                              <1> 		; INP:	word [ss:sp + 2] = segment
  1724                              <1> 		;	word [ss:sp] = offset
  1725                              <1> 		;
  1726                              <1> 		; Note:	Does not work correctly with pointers that point to
  1727                              <1> 		;	 a HMA location. Do not use then!
  1728                              <1> anti_normalise_pointer:
  1729                              <1> 	lframe near, nested
  1730                              <1> 	lpar word,	segment
  1731                              <1> 	lpar word,	offset
  1732                              <1> 	lpar_return
  1733 000009D5 5589E5              <1> 	lenter
  1734 000009D8 53                  <1> 	push bx
  1735 000009D9 51                  <1> 	push cx
  1736                              <1> 
  1737 000009DA 31DB                <1> 	xor bx, bx
  1738 000009DC 31C9                <1> 	xor cx, cx
  1739 000009DE FF7606              <1> 	 push word [bp + ?segment]
  1740 000009E1 FF7604              <1> 	 push word [bp + ?offset]
  1741 000009E4 E80A00              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1742 000009E7 8F4604              <1> 	 pop word [bp + ?offset]
  1743 000009EA 8F4606              <1> 	 pop word [bp + ?segment]
  1744                              <1> 
  1745 000009ED 59                  <1> 	pop cx
  1746 000009EE 5B                  <1> 	pop bx
  1747 000009EF 5D                  <1> 	lleave
  1748 000009F0 C3                  <1> 	lret
  1749                              <1> 
  1750                              <1> 
  1751                              <1> 		; INP:	word [ss:sp + 2] = segment
  1752                              <1> 		;	word [ss:sp] = offset
  1753                              <1> 		;	bx:cx = add/sub displacement
  1754                              <1> 		; OUT:	dword [ss:sp] = anti-normalised address
  1755                              <1> 		;
  1756                              <1> 		; An anti-normalised pointer has an offset as high as possible,
  1757                              <1> 		;  which is in the range 0FFF0h to 0FFFFh unless the pointed-to
  1758                              <1> 		;  location is in the first 64 KiB of memory.
  1759                              <1> anti_normalise_pointer_with_displacement_bxcx:
  1760                              <1> 	lframe near, nested
  1761                              <1> 	lpar word,	segment
  1762                              <1> 	lpar word,	offset
  1763                              <1> 	lpar_return
  1764 000009F1 5589E5              <1> 	lenter
  1765 000009F4 50                  <1> 	push ax
  1766 000009F5 52                  <1> 	push dx
  1767                              <1> 
  1768 000009F6 FF7606              <1> 	 push word [bp + ?segment]
  1769 000009F9 FF7604              <1> 	 push word [bp + ?offset]
  1770 000009FC E84B01              <1> 	call pointer_to_linear
  1771                              <1> 
  1772 000009FF 01C8                <1> 	add ax, cx
  1773 00000A01 11DA                <1> 	adc dx, bx			; dx:ax += bx:cx
  1774                              <1> 
  1775 00000A03 83FA01              <1> 	cmp dx, 1
  1776 00000A06 7223                <1> 	jb @F
  1777                              <1> 
  1778 00000A08 50                  <1> 	push ax
  1779 00000A09 83C8F0              <1> 	or ax, 0FFF0h
  1780 00000A0C 894604              <1> 	mov word [bp + ?offset], ax
  1781 00000A0F 58                  <1> 	pop ax
  1782                              <1> 
  1783 00000A10 83E8F0              <1> 	sub ax, 0FFF0h
  1784 00000A13 83DA00              <1> 	sbb dx, 0
  1785                              <1> 
  1786                              <1> %rep 4
  1787                              <1> 	shr dx, 1
  1788                              <1> 	rcr ax, 1
  1789                              <1> %endrep
  1787 00000A16 D1EA                <2>  shr dx, 1
  1788 00000A18 D1D8                <2>  rcr ax, 1
  1787 00000A1A D1EA                <2>  shr dx, 1
  1788 00000A1C D1D8                <2>  rcr ax, 1
  1787 00000A1E D1EA                <2>  shr dx, 1
  1788 00000A20 D1D8                <2>  rcr ax, 1
  1787 00000A22 D1EA                <2>  shr dx, 1
  1788 00000A24 D1D8                <2>  rcr ax, 1
  1790 00000A26 894606              <1> 	mov word [bp + ?segment], ax
  1791                              <1> 
  1792 00000A29 EB07                <1> 	jmp .return
  1793                              <1> 
  1794                              <1> 		; dx:ax = 0000:offset
  1795                              <1> @@:
  1796 00000A2B 894604              <1> 	mov word [bp + ?offset], ax
  1797 00000A2E 83660600            <1> 	and word [bp + ?segment], 0
  1798                              <1> 
  1799                              <1> .return:
  1800 00000A32 5A                  <1> 	pop dx
  1801 00000A33 58                  <1> 	pop ax
  1802 00000A34 5D                  <1> 	lleave
  1803 00000A35 C3                  <1> 	lret
  1804                              <1> 
  1805                              <1> 
  1806                              <1> 		; Move paragraphs
  1807                              <1> 		;
  1808                              <1> 		; INP:	ds:si -> source
  1809                              <1> 		;	es:di -> destination
  1810                              <1> 		;	cx = number of paragraphs
  1811                              <1> 		; CHG:	ax, bx, cx, dx
  1812                              <1> 		; OUT:	ds:si -> after source (normalised)
  1813                              <1> 		;	es:di -> after destination (normalised)
  1814                              <1> 		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  1815                              <1> 		;	Do not provide a wrapped/HMA source or destination!
  1816                              <1> x_mov_p:
  1817 00000A36 E8B100              <1> 	call normalise_both_pointers
  1818 00000A39 8CD8                <1> 	mov ax, ds
  1819 00000A3B 8CC2                <1> 	mov dx, es
  1820                              <1> 
  1821 00000A3D 85C9                <1> 	test cx, cx
  1822 00000A3F 7503E98800          <1> 	jz .return
  1823                              <1> 
  1824 00000A44 39D0                <1> 	cmp ax, dx		; source above destination ?
  1825 00000A46 7716                <1> 	ja .up			; yes, move up (forwards) -->
  1826 00000A48 7206                <1> 	jb .check_down
  1827                              <1> 
  1828 00000A4A 39FE                <1> 	cmp si, di
  1829 00000A4C 7710                <1> 	ja .up
  1830 00000A4E 747C                <1> 	je .return		; pointers are the same, no need to move -->
  1831                              <1> .check_down:
  1832 00000A50 50                  <1> 	push ax
  1833 00000A51 01C8                <1> 	add ax, cx		; (expected not to carry)
  1834 00000A53 39D0                <1> 	cmp ax, dx		; end of source is above destination ?
  1835 00000A55 58                  <1> 	pop ax
  1836 00000A56 7726                <1> 	ja .down		; yes, move from top down -->
  1837 00000A58 7204                <1> 	jb .up
  1838 00000A5A 39FE                <1> 	cmp si, di
  1839 00000A5C 7720                <1> 	ja .down
  1840                              <1> 
  1841                              <1> 	; Here, the end of source is below-or-equal the destination,
  1842                              <1> 	;  so they do not overlap. In this case we prefer moving up.
  1843                              <1> .up:
  1844                              <1> .uploop:
  1845 00000A5E 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  1846 00000A62 760C                <1> 	jbe .uplast		; no -->
  1847 00000A64 51                  <1> 	push cx
  1848 00000A65 B9F87F              <1> 	mov cx, 0FFF0h /2
  1849 00000A68 F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  1850 00000A6A 59                  <1> 	pop cx
  1851 00000A6B E87C00              <1> 	call normalise_both_pointers
  1852 00000A6E EBEE                <1> 	jmp short .uploop	; proceed for more -->
  1853                              <1> .uplast:
  1854 00000A70 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  1855 00000A74 D1E1                <1> 	shl cx, 1
  1856 00000A76 D1E1                <1> 	shl cx, 1
  1857 00000A78 D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  1858 00000A7A F3A5                <1> 	rep movsw		; move last part
  1859 00000A7C EB4E                <1> 	jmp short .return
  1860                              <1> 
  1861                              <1> .down:
  1862 00000A7E FD                  <1> 	std			; _AMD_ERRATUM_109_WORKAROUND as below
  1863                              <1> 
  1864 00000A7F 89C8                <1> 	mov ax, cx
  1865 00000A81 31DB                <1> 	xor bx, bx
  1866 00000A83 51                  <1> 	push cx
  1867 00000A84 B90400              <1> 	mov cx, 4
  1868                              <1> @@:
  1869 00000A87 D1E0                <1> 	shl ax, 1
  1870 00000A89 D1D3                <1> 	rcl bx, 1
  1871 00000A8B E2FA                <1> 	loop @B
  1872 00000A8D 83E802              <1> 	sub ax, 2
  1873 00000A90 83DB00              <1> 	sbb bx, 0		; -> point at last word
  1874                              <1> 		; (Cannot borrow here because we checked that cx
  1875                              <1> 		;  was nonzero at the intro to this function, so
  1876                              <1> 		;  bx:ax is at least 16 prior to this subtraction.)
  1877 00000A93 91                  <1> 	xchg ax, cx		; bx:cx = displacement to point to last word
  1878 00000A94 1E                  <1> 	 push ds
  1879 00000A95 56                  <1> 	 push si
  1880 00000A96 E858FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1881 00000A99 5E                  <1> 	 pop si
  1882 00000A9A 1F                  <1> 	 pop ds			; -> last word of source
  1883 00000A9B 06                  <1> 	 push es
  1884 00000A9C 57                  <1> 	 push di
  1885 00000A9D E851FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1886 00000AA0 5F                  <1> 	 pop di
  1887 00000AA1 07                  <1> 	 pop es			; -> last word of destination
  1888 00000AA2 59                  <1> 	pop cx
  1889                              <1> 
  1890                              <1> .dnloop:
  1891 00000AA3 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  1892 00000AA7 760C                <1> 	jbe .dnlast		; no -->
  1893 00000AA9 51                  <1> 	push cx
  1894 00000AAA B9F87F              <1> 	mov cx, 0FFF0h /2
  1895 00000AAD F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  1896 00000AAF 59                  <1> 	pop cx
  1897 00000AB0 E813FF              <1> 	call anti_normalise_both_pointers
  1898 00000AB3 EBEE                <1> 	jmp short .dnloop	; proceed for more -->
  1899                              <1> .dnlast:
  1900 00000AB5 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  1901 00000AB9 D1E1                <1> 	shl cx, 1
  1902 00000ABB D1E1                <1> 	shl cx, 1
  1903 00000ABD D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  1904                              <1> 
  1905                              <1> 
  1906                              <1> 	numdef AMD_ERRATUM_109_WORKAROUND, 1
  1907                              <1> %if 0
  1908                              <1> 
  1909                              <1> Jack R. Ellis pointed out this erratum:
  1910                              <1> 
  1911                              <1> Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
  1912                              <1> 
  1913                              <1> 109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
  1914                              <1> 
  1915                              <1> Description
  1916                              <1> 
  1917                              <1> In certain situations a REP MOVS instruction may lead to
  1918                              <1> incorrect results. An incorrect address size, data size
  1919                              <1> or source operand segment may be used or a succeeding
  1920                              <1> instruction may be skipped. This may occur under the
  1921                              <1> following conditions:
  1922                              <1> 
  1923                              <1> * EFLAGS.DF=1 (the string is being moved in the reverse direction).
  1924                              <1> 
  1925                              <1> * The number of items being moved (RCX) is between 1 and 20.
  1926                              <1> 
  1927                              <1> * The REP MOVS instruction is preceded by some microcoded instruction
  1928                              <1>   that has not completely retired by the time the REP MOVS begins
  1929                              <1>   execution. The set of such instructions includes BOUND, CLI, LDS,
  1930                              <1>   LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
  1931                              <1> 
  1932                              <1> Potential Effect on System
  1933                              <1> 
  1934                              <1> Incorrect results may be produced or the system may hang.
  1935                              <1> 
  1936                              <1> Suggested Workaround
  1937                              <1> 
  1938                              <1> Contact your AMD representative for information on a BIOS update.
  1939                              <1> 
  1940                              <1> %endif
  1941                              <1> 
  1942                              <1> %if _AMD_ERRATUM_109_WORKAROUND
  1943 00000ABF E308                <1> 	jcxz @FF
  1944 00000AC1 83F914              <1> 	cmp cx, 20
  1945 00000AC4 7703                <1> 	ja @FF
  1946                              <1> @@:
  1947 00000AC6 A5                  <1> 	movsw
  1948 00000AC7 E2FD                <1> 	loop @B
  1949                              <1> @@:
  1950                              <1> %endif
  1951 00000AC9 F3A5                <1> 	rep movsw		; move first part
  1952 00000ACB FC                  <1> 	cld
  1953                              <1> .return:
  1954 00000ACC EB1C                <1> 	jmp normalise_both_pointers
  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 00000ACE FF76D6                  	 push word [bp + ?dst + 2]
  1851 00000AD1 FF76D4                  	 push word [bp + ?dst]
  1852                                  %else
  1853                                  	 push es
  1854                                  	 push di
  1855                                  %endif
  1856 00000AD4 E87300                  	call pointer_to_linear
  1857                                  
  1858 00000AD7 91                      	xchg cx, ax
  1859 00000AD8 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1860                                  
  1861                                  %if CHECK_POINTERS_VARIABLE_SRC
  1862 00000ADA FF76EA                  	 push word [bp + ?src + 2]
  1863 00000ADD FF76E8                  	 push word [bp + ?src]
  1864                                  %else
  1865                                  	 push ds
  1866                                  	 push si
  1867                                  %endif
  1868 00000AE0 E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1869                                  
  1870 00000AE3 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1871 00000AE5 7502                    	jne @F
  1872 00000AE7 39C8                    	cmp ax, cx
  1873                                  @@:
  1874                                  					; (CY) if error (src < dst)
  1875                                  					; (NC) if no error
  1876 00000AE9 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 00000AEA 06                      	 push es
  1892 00000AEB 57                      	 push di
  1893 00000AEC E80A00                  	call normalise_pointer
  1894 00000AEF 5F                      	 pop di
  1895 00000AF0 07                      	 pop es
  1896                                  %endif
  1897                                  
  1898                                  normalise_dssi_pointer:
  1899 00000AF1 1E                      	 push ds
  1900 00000AF2 56                      	 push si
  1901 00000AF3 E80300                  	call normalise_pointer
  1902 00000AF6 5E                      	 pop si
  1903 00000AF7 1F                      	 pop ds
  1904 00000AF8 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 00000AF9 5589E5                  	lenter
  1919                                  
  1920 00000AFC 837E040F                	cmp word [bp + ?offset], 15
  1921 00000B00 7617                    	jbe .ret
  1922                                  
  1923 00000B02 53                      	push bx
  1924 00000B03 51                      	push cx
  1925                                  
  1926 00000B04 31DB                    	xor bx, bx
  1927 00000B06 31C9                    	xor cx, cx
  1928 00000B08 FF7606                  	 push word [bp + ?segment]
  1929 00000B0B FF7604                  	 push word [bp + ?offset]
  1930 00000B0E E80A00                  	call normalise_pointer_with_displacement_bxcx
  1931 00000B11 8F4604                  	 pop word [bp + ?offset]
  1932 00000B14 8F4606                  	 pop word [bp + ?segment]
  1933                                  
  1934 00000B17 59                      	pop cx
  1935 00000B18 5B                      	pop bx
  1936                                  .ret:
  1937 00000B19 5D                      	lleave
  1938 00000B1A 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 00000B1B 5589E5                  	lenter
  1953                                  
  1954                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1955                                  	cmp word [bp + ?offset], 15
  1956                                  	jbe .ret
  1957                                  %endif
  1958                                  
  1959 00000B1E 50                      	push ax
  1960 00000B1F 51                      	push cx
  1961 00000B20 52                      	push dx
  1962                                  
  1963 00000B21 FF7606                  	 push word [bp + ?segment]
  1964 00000B24 FF7604                  	 push word [bp + ?offset]
  1965 00000B27 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 00000B2A 01C1                    	add cx, ax
  1975 00000B2C 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1976                                  	; pop bx
  1977 00000B2E 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 00000B2F 53                      	push bx
  1997 00000B30 89CB                    	mov bx, cx
  1998 00000B32 83E10F                  	and cx, 15
  1999 00000B35 894E04                  	mov word [bp + ?offset], cx
  2000                                  
  2001 00000B38 B104                    	mov cl, 4
  2002                                  @@:
  2003 00000B3A D1EA                    	shr dx, 1
  2004 00000B3C D1DB                    	rcr bx, 1
  2005 00000B3E E2FA                    	loop @B
  2006                                  
  2007 00000B40 895E06                  	mov word [bp + ?segment], bx
  2008 00000B43 5B                      	pop bx
  2009                                  
  2010                                  	; test dx, dx
  2011                                  	; jnz .error
  2012                                  
  2013                                  .return:
  2014                                  
  2015                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  2016 00000B44 9E                      	sahf				; restore flags from ah
  2017                                  %endif
  2018 00000B45 5A                      	pop dx
  2019 00000B46 59                      	pop cx
  2020 00000B47 58                      	pop ax
  2021                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  2022                                  .ret:
  2023                                  %endif
  2024 00000B48 5D                      	lleave
  2025 00000B49 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 00000B4A 5589E5                  	lenter
  2036                                  
  2037 00000B4D 8B4606                  	mov ax, word [bp + ?segment]
  2038 00000B50 31D2                    	xor dx, dx
  2039 00000B52 51                      	push cx
  2040 00000B53 B90400                  	mov cx, 4
  2041                                  @@:
  2042 00000B56 D1E0                    	shl ax, 1
  2043 00000B58 D1D2                    	rcl dx, 1
  2044 00000B5A E2FA                    	loop @B
  2045                                  
  2046 00000B5C 034604                  	add ax, word [bp + ?offset]
  2047 00000B5F 11CA                    	adc dx, cx			; cx = 0 here
  2048 00000B61 59                      	pop cx
  2049                                  
  2050 00000B62 5D                      	lleave
  2051 00000B63 C20400                  	lret
  2052                                  
  2053                                  
  2054                                  %if _PASSLCFG
  2055                                  	align 16
  2056                                  transfer_lcfg_block:
  2057                                  	times lcfg.size nop
  2058                                  %endif
  2059 00000B66 90<rep Ah>              	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 000002D8 4572726F723A20556E-     .error_stderr_file:	db "Error: Unable to open own executable file.",13,10
  2067 000002E1 61626C6520746F206F-
  2067 000002EA 70656E206F776E2065-
  2067 000002F3 786563757461626C65-
  2067 000002FC 2066696C652E0D0A   
  2068                                  .error_stderr_file.length equ $ - .error_stderr_file
  2069                                  %endif
  2070 00000304 4572726F723A204E6F-     .error_stderr:	db "Error: Not enough memory allocated.",13,10
  2070 0000030D 7420656E6F75676820-
  2070 00000316 6D656D6F727920616C-
  2070 0000031F 6C6F63617465642E0D-
  2070 00000328 0A                 
  2071                                  .error_stderr.length: equ $ - .error_stderr
  2072                                  .error_c_stdout:
  2073 00000329 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 0000032A 0D0A                    		db 13,10
  2082                                  .error_c_stdout.length: equ $ - .error_c_stdout
  2083                                  .error_stdout.length: equ $ - .error_stdout
  2084                                  
  2085 0000032C 90<rep D4h>             	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: inilz: 3952 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 5589E58DA67AFF          	lenter
  2162                                  
  2163                                  %if _RELOAD_FILE && _RELOAD_XMS
  2164 00000008 834EFAFF                	or word [bp + ?xmshandle], -1
  2165                                  %endif
  2166                                  
  2167 0000000C 8B5604                  	mov dx, word [bp + ?repetitions]
  2168 0000000F 83FAFF                  	cmp dx, -1
  2169 00000012 7509                    	jne @F
  2170                                  
  2171                                  .cmdline_error:
  2172                                  %if _DEBUG0
  2173                                  	mov bx, -1
  2174                                  %endif
  2175 00000014 BA[DE03]                	mov dx, init2_msg.cmdline_error
  2176 00000017 B92400                  	mov cx, init2_msg.cmdline_error.length
  2177 0000001A E98402                  	jmp init2_error
  2178                                  
  2179                                  
  2180                                  @@:
  2181 0000001D F6460340                	testopt [bp + ?whichtest], 4000h
  2182 00000021 750C                    	jnz .a_or_c
  2183 00000023 F6460380                	testopt [bp + ?whichtest], 8000h
  2184 00000027 7406                    	jz .a_or_c
  2185                                  .b:
  2186 00000029 85D2                    	test dx, dx
  2187 0000002B 74E7                    	jz .cmdline_error
  2188 0000002D EB04                    	jmp @F
  2189                                  
  2190                                  .a_or_c:
  2191 0000002F 85D2                    	test dx, dx
  2192 00000031 75E1                    	jnz .cmdline_error
  2193                                  @@:
  2194                                  
  2195                                  %if _RELOAD_XMS
  2196 00000033 56                      	push si
  2197 00000034 B80043                  	mov ax, 4300h
  2198 00000037 CD2F                    	int 2Fh
  2199 00000039 3C80                    	cmp al, 80h
  2200                                  %if _RELOAD_FILE
  2201 0000003B 7538                    	jne .noxms
  2202                                  %else
  2203                                  	jne init2_error_xms
  2204                                  %endif
  2205 0000003D B81043                  	mov ax, 4310h
  2206 00000040 CD2F                    	int 2Fh
  2207 00000042 895EFC                  	mov word [bp + ?xmsentry], bx
  2208 00000045 8C46FE                  	mov word [bp + ?xmsentry + 2], es
  2209 00000048 B409                    	mov ah, 09h
  2210 0000004A BA4F00                  	mov dx, KiB(payload_end - payload)
  2211 0000004D FF5EFC                  	call far [bp + ?xmsentry]
  2212 00000050 83F801                  	cmp ax, 1
  2213                                  %if _RELOAD_FILE
  2214 00000053 7520                    	jne .noxms
  2215                                  %else
  2216                                  	jne init2_error_xms
  2217                                  %endif
  2218 00000055 8956FA                  	mov word [bp + ?xmshandle], dx
  2219 00000058 8CC8                    	mov ax, cs
  2220 0000005A 2D7414                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2223 0000005D 0E                      	 push cs
  2224 0000005E 1F                      	 pop ds
  2225 0000005F BE[D404]                	mov si, init2_xmsm_to_save
  2226 00000062 89540A                  	mov word [si + XMSM.dsthdl], dx
  2227 00000065 894408                  	mov word [si + XMSM.srcadr + 2], ax
  2228                                  %ifn _RELOAD_FILE
  2229                                  	push ax
  2230                                  %endif
  2231 00000068 B40B                    	mov ah, 0Bh
  2232 0000006A FF5EFC                  	call far [bp + ?xmsentry]
  2233 0000006D 83F801                  	cmp ax, 1
  2234 00000070 7403E91802              	jne init2_error_xms_free
  2235                                  %ifn _RELOAD_FILE
  2236                                  	pop ax			; => payload
  2237                                  %else
  2238                                  .noxms:
  2239 00000075 8CC8                    	mov ax, cs
  2240 00000077 2D7414                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2243                                  @@:
  2244                                  %endif
  2245 0000007A 5E                      	pop si
  2246                                  %elif _RELOAD_FILE
  2247                                  	mov ax, cs
  2248                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2251                                  %else
  2252                                  	mov dx, cs
  2253                                  	add dx, (init2_end - init2_start) >> 4
  2254                                  				; => payload saving area
  2255                                  	mov ax, cs
  2256                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2259                                  	mov cx, (payload_end - payload) >> 4
  2260                                  	call init2_movp		; copy payload to payload saving area
  2261                                  %endif
  2262                                  		; We save away the payload here because a failure
  2263                                  		;  to decompress generally overwrites part of that
  2264                                  		;  payload which was used as source.
  2265                                  
  2266 0000007B 89C2                    	mov dx, ax		; dx => payload source to use
  2267 0000007D 8CC8                    	mov ax, cs
  2268 0000007F 2DB700                  	sub ax, (init1_end - init1_start) >> 4
  2269                                  				; ax => INIT1
  2270 00000082 BB0100                  	mov bx, 1		; say we're in EXE mode
  2271 00000085 52                      	push dx
  2272 00000086 50                      	push ax
  2273 00000087 56                      	push si			; si => target
  2274 00000088 0E                      	 push cs
  2275 00000089 E89001                  	 call .transfer		; call decompression
  2276 0000008C 5E                      	pop si
  2277 0000008D 58                      	pop ax
  2278 0000008E 5A                      	pop dx
  2279                                  		; Returns here after decompression.
  2280                                  		; CY if error.
  2281 0000008F 7309                    	jnc @F
  2282                                  
  2283 00000091 BA[2F03]                	mov dx, init2_msg.initial_error
  2284 00000094 B93C00                  	mov cx, init2_msg.initial_error.length
  2285 00000097 E90402                  	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 0000009A E88501                  	call checkdecompressed
  2295 0000009D 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 0000009F BA[6B03]                	mov dx, init2_msg.initial_error_2
  2305 000000A2 B93C00                  	mov cx, init2_msg.initial_error_2.length
  2306 000000A5 E9F601                  	jmp init2_error_free
  2307                                  
  2308                                  @@:
  2309                                  %endif
  2310                                  
  2311 000000A8 F6460340                	testopt [bp + ?whichtest], 4000h
  2312 000000AC 7420                    	jz @F
  2313 000000AE 8CC8                    	mov ax, cs
  2314 000000B0 2DB700                  	sub ax, (init1_end - init1_start) >> 4
  2315                                  				; ax => INIT1
  2316 000000B3 8EC0                    	mov es, ax
  2317 000000B5 26A1[5900]              	mov ax, word [es:init1_c_mode_counter]
  2318 000000B9 E81F02                  	call init2_disp_ax_dec
  2319 000000BC B00D                    	mov al, 13
  2320 000000BE E80F02                  	call init2_disp_al
  2321 000000C1 B00A                    	mov al, 10
  2322 000000C3 E80A02                  	call init2_disp_al
  2323                                  %if _RELOAD_XMS
  2324 000000C6 E8AD01                  	call freexms
  2325                                  %endif
  2326 000000C9 B8004C                  	mov ax, 4C00h
  2327 000000CC CD21                    	int 21h
  2328                                  
  2329                                  @@:
  2330                                  	lvar word,	upperbound
  2331 000000CE 52                      	 push dx
  2332                                  	lvar word,	lowerbound
  2333 000000CF 56                      	 push si
  2334                                  	lvar word,	current_init1
  2335 000000D0 50                      	 push ax
  2336                                  
  2337                                  %if _TEST_PROGRESS
  2338 000000D1 BA[2403]                	mov dx, init2_msg.progress.1
  2339 000000D4 B90700                  	mov cx, init2_msg.progress.1.length
  2340                                  .loop:
  2341 000000D7 0E                      	push cs
  2342 000000D8 1F                      	pop ds
  2343 000000D9 BB0200                  	mov bx, 2
  2344 000000DC B440                    	mov ah, 40h
  2345 000000DE CD21                    	int 21h
  2346                                  %else
  2347                                  .loop:
  2348                                  %endif
  2349                                  
  2350 000000E0 8B9678FF                	mov dx, [bp + ?upperbound]
  2351                                  
  2352 000000E4 F6460380                	testopt [bp + ?whichtest], 8000h
  2353 000000E8 741C                    	jz @F
  2354                                  
  2355 000000EA FF4E04                  	dec word [bp + ?repetitions]
  2356 000000ED 7526                    	jnz .test_b_skip_bound
  2357                                  
  2358                                  %if _TEST_PROGRESS
  2359 000000EF 0E                      	push cs
  2360 000000F0 1F                      	pop ds
  2361 000000F1 BA[2D03]                	mov dx, init2_msg.progress.linebreak
  2362 000000F4 B90200                  	mov cx, init2_msg.progress.linebreak.length
  2363 000000F7 BB0200                  	mov bx, 2
  2364 000000FA B440                    	mov ah, 40h
  2365 000000FC CD21                    	int 21h
  2366                                  %endif
  2367                                  %if _RELOAD_XMS
  2368 000000FE E87501                  	call freexms
  2369                                  %endif
  2370 00000101 B8004C                  	mov ax, 4C00h
  2371 00000104 CD21                    	int 21h
  2372                                  
  2373                                  
  2374                                  @@:
  2375 00000106 2B9676FF                	sub dx, [bp + ?lowerbound]
  2376 0000010A 7503E9E000              	jz .found
  2377 0000010F D1EA                    	shr dx, 1
  2378                                  		; Rounding down, so that we never retry upper bound.
  2379                                  		;  The upper bound is known to be working.
  2380 00000111 039676FF                	add dx, [bp + ?lowerbound]
  2381                                  
  2382                                  .test_b_skip_bound:
  2383 00000115 52                      	push dx
  2384 00000116 81C2BD13                	add dx, (payload_end - payload) >> 4
  2385 0000011A 8B8674FF                	mov ax, [bp + ?current_init1]
  2386 0000011E B9B700                  	mov cx, (init1_end - init1_start) >> 4
  2387 00000121 E81103                  	call init2_movp
  2388 00000124 899674FF                	mov [bp + ?current_init1], dx
  2389 00000128 5A                      	pop dx
  2390                                  
  2391                                  %if _RELOAD_XMS
  2392 00000129 8B46FA                  	mov ax, [bp + ?xmshandle]
  2393                                   %if _RELOAD_FILE
  2394 0000012C 83F8FF                  	cmp ax, -1
  2395 0000012F 741C                    	je .restore_no_xms
  2396                                   %endif
  2397 00000131 56                      	push si
  2398 00000132 0E                      	 push cs
  2399 00000133 1F                      	 pop ds
  2400 00000134 BE[C404]                	mov si, init2_xmsm_from_save
  2401 00000137 894404                  	mov word [si + XMSM.srchdl], ax
  2402 0000013A 89540E                  	mov word [si + XMSM.dstadr + 2], dx
  2403 0000013D B40B                    	mov ah, 0Bh
  2404 0000013F FF5EFC                  	call far [bp + ?xmsentry]
  2405 00000142 83F801                  	cmp ax, 1
  2406 00000145 7403E94301              	jne init2_error_xms_free
  2407 0000014A 5E                      	pop si
  2408                                   %if _RELOAD_FILE
  2409 0000014B EB53                    	jmp .restore_done
  2410                                   %endif
  2411                                  %endif
  2412                                  %if _RELOAD_FILE
  2413                                  .restore_no_xms:
  2414                                  size_compressed equ (payload.end - payload)
  2415 0000014D 52                      	push dx
  2416 0000014E 8EDA                    	mov ds, dx
  2417 00000150 B9FEFF                  	mov cx, ((- size_compressed) >> 16) & 0FFFFh
  2418 00000153 BA3DC4                  	mov dx, (- size_compressed) & 0FFFFh
  2419 00000156 B80242                  	mov ax, 4202h
  2420 00000159 8B5E06                  	mov bx, [bp + ?handle]
  2421 0000015C CD21                    	int 21h
  2422 0000015E 7303E93501              	jc init2_error_file
  2423 00000163 BA0100                  	mov dx, size_compressed >> 16
  2424 00000166 B8C33B                  	mov ax, size_compressed & 0FFFFh
  2425                                  @@:
  2426 00000169 B900FF                  	mov cx, 0FF00h
  2427 0000016C 85D2                    	test dx, dx
  2428 0000016E 7506                    	jnz @F
  2429 00000170 39C8                    	cmp ax, cx
  2430 00000172 7302                    	jae @F
  2431 00000174 89C1                    	mov cx, ax
  2432                                  @@:
  2433 00000176 29C8                    	sub ax, cx
  2434 00000178 83DA00                  	sbb dx, 0
  2435 0000017B 52                      	push dx
  2436 0000017C 50                      	push ax
  2437 0000017D 31D2                    	xor dx, dx
  2438 0000017F B43F                    	mov ah, 3Fh
  2439 00000181 CD21                    	int 21h
  2440 00000183 7303E91001              	jc init2_error_file
  2441 00000188 39C8                    	cmp ax, cx
  2442 0000018A 7403E90901              	jne init2_error_file
  2443 0000018F 8CDA                    	mov dx, ds
  2444 00000191 81C2F00F                	add dx, 0FF0h
  2445 00000195 8EDA                    	mov ds, dx
  2446 00000197 58                      	pop ax
  2447 00000198 5A                      	pop dx
  2448 00000199 89C1                    	mov cx, ax
  2449 0000019B 09D1                    	or cx, dx
  2450 0000019D 75CA                    	jnz @BB
  2451 0000019F 5A                      	pop dx
  2452                                  .restore_done:
  2453                                  %endif
  2454                                  %ifn _RELOAD_XMS || _RELOAD_FILE
  2455                                  	mov ax, cs
  2456                                  	add ax, (init2_end - init2_start) >> 4
  2457                                  				; => payload in saving area
  2458                                  	mov cx, (payload_end - payload) >> 4
  2459                                  	call init2_movp		; copy payload from payload saving area
  2460                                  %endif
  2461                                  		; dx => source
  2462 000001A0 8B8674FF                	mov ax, [bp + ?current_init1]
  2463 000001A4 BB0100                  	mov bx, 1
  2464 000001A7 52                      	push dx
  2465 000001A8 56                      	push si
  2466 000001A9 0E                      	 push cs
  2467 000001AA E86F00                  	 call .transfer
  2468 000001AD 5E                      	pop si
  2469 000001AE 5A                      	pop dx
  2470                                  		; Returns here after decompression.
  2471                                  		; CY if error.
  2472 000001AF 7314                    	jnc @F
  2473                                  
  2474 000001B1 F6460380                	testopt [bp + ?whichtest], 8000h
  2475 000001B5 7513                    	jnz .test_b_fail
  2476                                  
  2477                                  		; error: this attempt is one below the new lower bound
  2478 000001B7 42                      	inc dx
  2479 000001B8 899676FF                	mov word [bp + ?lowerbound], dx
  2480                                  
  2481                                  %if _TEST_PROGRESS
  2482 000001BC BA[2B03]                	mov dx, init2_msg.progress.fail
  2483 000001BF B90100                  	mov cx, init2_msg.progress.fail.length
  2484                                  %endif
  2485 000001C2 E912FF                  	jmp .loop
  2486                                  
  2487                                  @@:
  2488                                  %if _INCLUDE_UNCOMPRESSED
  2489 000001C5 E85A00                  	call checkdecompressed
  2490 000001C8 7418                    	je @F
  2491                                  
  2492                                  %if _WRITE_WRONG_FILE
  2493                                  	call writefiles
  2494                                  %endif
  2495                                  
  2496                                  .test_b_fail:
  2497                                  %if _TEST_PROGRESS
  2498 000001CA 0E                      	push cs
  2499 000001CB 1F                      	pop ds
  2500 000001CC BA[2D03]                	mov dx, init2_msg.progress.linebreak
  2501 000001CF B90200                  	mov cx, init2_msg.progress.linebreak.length
  2502 000001D2 BB0200                  	mov bx, 2
  2503 000001D5 B440                    	mov ah, 40h
  2504 000001D7 CD21                    	int 21h
  2505                                  %endif
  2506                                  %if _DEBUG0
  2507                                  	mov bx, -2
  2508                                  %endif
  2509 000001D9 BA[A703]                	mov dx, init2_msg.subsequent_error_2
  2510 000001DC B93700                  	mov cx, init2_msg.subsequent_error_2.length
  2511 000001DF E9BC00                  	jmp init2_error_free
  2512                                  
  2513                                  @@:
  2514                                  %endif
  2515                                  		; success: this attempt is the new upper bound
  2516 000001E2 899678FF                	mov word [bp + ?upperbound], dx
  2517                                  %if _TEST_PROGRESS
  2518 000001E6 BA[2C03]                	mov dx, init2_msg.progress.success
  2519 000001E9 B90100                  	mov cx, init2_msg.progress.success.length
  2520                                  %endif
  2521 000001EC E9E8FE                  	jmp .loop
  2522                                  
  2523                                  .found:
  2524                                  %if _TEST_PROGRESS
  2525 000001EF 0E                      	push cs
  2526 000001F0 1F                      	pop ds
  2527 000001F1 BA[2D03]                	mov dx, init2_msg.progress.linebreak
  2528 000001F4 B90200                  	mov cx, init2_msg.progress.linebreak.length
  2529 000001F7 BB0200                  	mov bx, 2
  2530 000001FA B440                    	mov ah, 40h
  2531 000001FC CD21                    	int 21h
  2532                                  %endif
  2533 000001FE 8B8678FF                	mov ax, word [bp + ?upperbound]
  2534 00000202 29F0                    	sub ax, si		; = how many paragraphs in buffer before source
  2535 00000204 057414                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  2537                                  				; = how many paragraphs needed for process
  2538 00000207 E8D100                  	call init2_disp_ax_dec
  2539 0000020A B00D                    	mov al, 13
  2540 0000020C E8C100                  	call init2_disp_al
  2541 0000020F B00A                    	mov al, 10
  2542 00000211 E8BC00                  	call init2_disp_al
  2543                                  %if _RELOAD_XMS
  2544 00000214 E85F00                  	call freexms
  2545                                  %endif
  2546 00000217 B8004C                  	mov ax, 4C00h
  2547 0000021A CD21                    	int 21h
  2548                                  
  2549                                  
  2550                                  .transfer:
  2551 0000021C 31FF                    	xor di, di
  2552 0000021E 57                      	push di			; placeholder ax value on stack
  2553 0000021F 50                      	push ax			; INIT1 segment
  2554 00000220 57                      	push di			; zero = init1_start
  2555 00000221 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 00000222 50                      	push ax
  2726 00000223 52                      	push dx
  2727 00000224 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                                  	mov cx, payload_uncompressed_size >> 4
  2734                                  	mov bx, payload_uncompressed_size & 15
  2735                                  %endif
  2736                                  	mov di, cs
  2737                                  	add di, (payload_uncompressed - init2_start) >> 4
  2738                                  	jcxz .end
  2739                                  .loop:
  2740                                  	push cx
  2741                                  	mov cx, 8
  2742                                  	mov ds, si
  2743                                  	mov es, di
  2744                                  	inc si
  2745                                  	inc di
  2746                                  	push si
  2747                                  	push di
  2748                                  	xor si, si
  2749                                  	xor di, di
  2750                                  	repe cmpsw
  2751                                  	pop di
  2752                                  	pop si
  2753                                  	pop cx
  2754                                  	jne .ret
  2755                                  	loop .loop
  2756                                  .end:
  2757                                  	mov ds, si
  2758                                  	mov es, di
  2759                                  	xor si, si
  2760                                  	xor di, di		; (ZR)
  2761                                  	mov cx, bx
  2762                                  	repe cmpsb
  2763                                  %else
  2764                                  %if _RELOAD_FILE
  2765                                  size_compressed_plus_uncompressed equ  payload_uncompressed_size + (payload.end - payload)
  2767 00000225 B9FCFF                  	mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh
  2768 00000228 BAEDD7                  	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 0000022B B80242                  	mov ax, 4202h
  2774 0000022E 8B5E06                  	mov bx, [bp + ?handle]
  2775 00000231 CD21                    	int 21h
  2776 00000233 7219                    	jc .error
  2777                                  %if payload_uncompressed_size == 0
  2778                                   %error Empty payload not allowed
  2779                                  %endif
  2780                                  %if (payload_uncompressed_size / ?buffersize) != 0
  2781 00000235 B9D803                  	mov cx, payload_uncompressed_size / ?buffersize
  2782                                  %if ?buffersize == 0 || (?buffersize & 15) != 0
  2783                                   %error Unexpected layout
  2784                                  %endif
  2785                                  .loop:
  2786 00000238 51                      	push cx
  2787 00000239 B98000                  	mov cx, ?buffersize
  2788 0000023C E81300                  	call comparechunk
  2789 0000023F 59                      	pop cx
  2790 00000240 7508                    	jne .ret
  2791 00000242 E2F4                    	loop .loop
  2792                                  %endif
  2793                                  %if (payload_uncompressed_size % ?buffersize) != 0
  2794 00000244 B95000                  	mov cx, payload_uncompressed_size % ?buffersize
  2795 00000247 E80800                  	call comparechunk
  2796                                  %endif
  2797                                  %endif
  2798                                  .ret:
  2799 0000024A 5E                      	pop si
  2800 0000024B 5A                      	pop dx
  2801 0000024C 58                      	pop ax
  2802 0000024D C3                      	retn
  2803                                  
  2804                                  %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE
  2805                                  .error:
  2806 0000024E 0C01                    	or al, 1			; NZ
  2807 00000250 EBF8                    	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 00000252 16                      	push ss
  2825 00000253 1F                      	pop ds
  2826 00000254 8D967AFF                	lea dx, [bp + ?buffer]
  2827 00000258 8B5E06                  	mov bx, [bp + ?handle]
  2828 0000025B B43F                    	mov ah, 3Fh
  2829 0000025D CD21                    	int 21h
  2830 0000025F 7212                    	jc .error
  2831 00000261 39C8                    	cmp ax, cx
  2832 00000263 750E                    	jne .error
  2833 00000265 8EC6                    	mov es, si
  2834 00000267 83C608                  	add si, ?buffersize / 16
  2835 0000026A 56                      	push si
  2836 0000026B 31FF                    	xor di, di
  2837 0000026D 89D6                    	mov si, dx
  2838 0000026F F3A6                    	repe cmpsb
  2839 00000271 5E                      	pop si
  2840                                  .ret:
  2841 00000272 C3                      	retn
  2842                                  
  2843                                  .error:
  2844 00000273 0C01                    	or al, 1			; NZ
  2845 00000275 C3                      	retn
  2846                                  %endif
  2847                                  
  2848                                  %if _RELOAD_XMS
  2849                                  freexms:
  2850 00000276 50                      	push ax
  2851 00000277 53                      	push bx
  2852 00000278 52                      	push dx
  2853 00000279 BAFFFF                  	mov dx, -1
  2854 0000027C 8756FA                  	xchg dx, [bp + ?xmshandle]
  2855                                  %if _RELOAD_FILE
  2856 0000027F 83FAFF                  	cmp dx, -1
  2857 00000282 7405                    	je @F
  2858                                  %endif
  2859 00000284 B40A                    	mov ah, 0Ah
  2860 00000286 FF5EFC                  	call far [bp + ?xmsentry]
  2861                                  @@:
  2862 00000289 5A                      	pop dx
  2863 0000028A 5B                      	pop bx
  2864 0000028B 58                      	pop ax
  2865 0000028C C3                      	retn
  2866                                  
  2867                                  init2_error_xms_free:
  2868 0000028D E8E6FF                  	call freexms
  2869                                  init2_error_xms:
  2870 00000290 BA[0204]                	mov dx, init2_msg.xms_error
  2871 00000293 B91500                  	mov cx, init2_msg.xms_error.length
  2872 00000296 EB09                    	jmp init2_error
  2873                                  %endif
  2874                                  
  2875                                  %if _RELOAD_FILE
  2876                                  init2_error_file:
  2877 00000298 BA[1704]                	mov dx, init2_msg.file_error
  2878 0000029B B91B00                  	mov cx, init2_msg.file_error.length
  2879                                  %endif
  2880                                  
  2881                                  init2_error_free:
  2882                                  %if _RELOAD_XMS
  2883 0000029E E8D5FF                  	call freexms
  2884                                  %endif
  2885                                  init2_error:
  2886                                  %if _DEBUG0
  2887                                  	push bx
  2888                                  %endif
  2889 000002A1 0E                      	push cs
  2890 000002A2 1F                      	pop ds
  2891 000002A3 BB0200                  	mov bx, 2
  2892 000002A6 B440                    	mov ah, 40h
  2893 000002A8 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 000002AA F6460340                	testopt [bp + ?whichtest], 4000h
  2911 000002AE 7408                    	jz @F
  2912 000002B0 BA[3204]                	mov dx, init2_msg.error_c_stdout
  2913 000002B3 B90300                  	mov cx, init2_msg.error_c_stdout.length
  2914 000002B6 EB0C                    	jmp @FF
  2915                                  @@:
  2916 000002B8 F6460380                	testopt [bp + ?whichtest], 8000h
  2917 000002BC 750D                    	jnz @FF
  2918 000002BE BA[3204]                	mov dx, init2_msg.error_stdout
  2919 000002C1 B90300                  	mov cx, init2_msg.error_stdout.length
  2920                                  @@:
  2921 000002C4 BB0100                  	mov bx, 1
  2922 000002C7 B440                    	mov ah, 40h
  2923 000002C9 CD21                    	int 21h
  2924                                  @@:
  2925 000002CB B8FF4C                  	mov ax, 4CFFh
  2926 000002CE 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 000002D0 52                      	push dx
  2982 000002D1 50                      	push ax
  2983 000002D2 88C2                    	mov dl, al
  2984 000002D4 B402                    	mov ah, 2
  2985 000002D6 CD21                    	int 21h
  2986 000002D8 58                      	pop ax
  2987 000002D9 5A                      	pop dx
  2988 000002DA 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 000002DB 53                      		push bx
  2998 000002DC 31DB                    		xor bx, bx
  2999                                  .pushax:
  3000 000002DE 52                      		push dx
  3001 000002DF 50                      		push ax
  3002 000002E0 08DB                    		or bl, bl
  3003 000002E2 7405                    		jz .nobl
  3004 000002E4 80EB05                  		sub bl, 5
  3005 000002E7 F6DB                    		neg bl
  3006                                  .nobl:
  3007 000002E9 51                      		push cx
  3008 000002EA B91027                  		mov cx, 10000
  3009 000002ED E81B00                  		call .divide_out
  3010 000002F0 B9E803                  		mov cx, 1000
  3011 000002F3 E81500                  		call .divide_out
  3012 000002F6 B96400                  		mov cx, 100
  3013 000002F9 E80F00                  		call .divide_out
  3014 000002FC B10A                    		mov cl, 10
  3015 000002FE E80A00                  		call .divide_out
  3016                                  							; (Divisor 1 is useless)
  3017 00000301 0430                    		add al, '0'
  3018 00000303 E8CAFF                  		call init2_disp_al
  3019 00000306 59                      		pop cx
  3020 00000307 58                      		pop ax
  3021 00000308 5A                      		pop dx
  3022 00000309 5B                      		pop bx					; Caller's register
  3023 0000030A C3                      		retn
  3024                                  
  3025                                  
  3026                                  		; INP:	ax = number
  3027                                  		;	cx = divisor
  3028                                  		; OUT:	ax = remainder of operation
  3029                                  		;	result displayed
  3030                                  .divide_out:
  3031 0000030B 52                      		push dx
  3032 0000030C 31D2                    		xor dx, dx
  3033 0000030E F7F1                    		div cx				; 0:ax / cx
  3034 00000310 52                      		push dx				; remainder
  3035 00000311 FECB                    		dec bl
  3036 00000313 7503                    		jnz .nobl2
  3037 00000315 80CF01                  		or bh, 1
  3038                                  .nobl2:
  3039 00000318 08C7                    		or bh, al
  3040 0000031A 7405                    		jz .leadingzero
  3041 0000031C 0430                    		add al, '0'
  3042 0000031E E8AFFF                  		call init2_disp_al		; display result
  3043                                   .leadingzero:
  3044 00000321 58                      		pop ax				; remainder
  3045 00000322 5A                      		pop dx
  3046 00000323 C3                      		retn
  3047                                  
  3048                                  
  3049                                  init2_msg:
  3050                                  %if _TEST_PROGRESS
  3051 00000324 496E666F3A2031          .progress.1:		db "Info: 1"
  3052                                  .progress.1.length: equ $ - .progress.1
  3053 0000032B 46                      .progress.fail:		db "F"
  3054                                  .progress.fail.length: equ $ - .progress.fail
  3055 0000032C 53                      .progress.success:	db "S"
  3056                                  .progress.success.length: equ $ - .progress.success
  3057 0000032D 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 0000032F 4572726F723A205465-     .initial_error:	db "Error: Test program failed to decompress with full buffer."
  3064 00000338 73742070726F677261-
  3064 00000341 6D206661696C656420-
  3064 0000034A 746F206465636F6D70-
  3064 00000353 726573732077697468-
  3064 0000035C 2066756C6C20627566-
  3064 00000365 6665722E           
  3065 00000369 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 0000036B 4572726F723A205465-     .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  3073 00000374 73742070726F677261-
  3073 0000037D 6D206465636F6D7072-
  3073 00000386 65737365642077726F-
  3073 0000038F 6E676C792077697468-
  3073 00000398 2066756C6C20627566-
  3073 000003A1 6665722E0D0A       
  3074                                  .initial_error_2.length: equ $ - .initial_error_2
  3075 000003A7 4572726F723A205465-     .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  3075 000003B0 73742070726F677261-
  3075 000003B9 6D206465636F6D7072-
  3075 000003C2 65737365642077726F-
  3075 000003CB 6E676C792064757269-
  3075 000003D4 6E6720746573742E0D-
  3075 000003DD 0A                 
  3076                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  3077                                  %endif
  3078 000003DE 4572726F723A20496E-     .cmdline_error:	db "Error: Invalid command line input.",13,10
  3078 000003E7 76616C696420636F6D-
  3078 000003F0 6D616E64206C696E65-
  3078 000003F9 20696E7075742E0D0A 
  3079                                  .cmdline_error.length: equ $ - .cmdline_error
  3080                                  %if _RELOAD_XMS
  3081 00000402 4572726F723A20584D-     .xms_error:	db "Error: XMS failure.",13,10
  3081 0000040B 53206661696C757265-
  3081 00000414 2E0D0A             
  3082                                  .xms_error.length: equ $ - .xms_error
  3083                                  %endif
  3084                                  %if _RELOAD_FILE
  3085 00000417 4572726F723A204669-     .file_error:	db "Error: File read failure.",13,10
  3085 00000420 6C6520726561642066-
  3085 00000429 61696C7572652E0D0A 
  3086                                  .file_error.length: equ $ - .file_error
  3087                                  %endif
  3088                                  
  3089                                  .error_c_stdout:
  3090 00000432 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 00000433 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 00000435 51                      	push cx
  3114 00000436 1E                      	push ds
  3115 00000437 56                      	push si
  3116 00000438 06                      	push es
  3117 00000439 57                      	push di
  3118                                  
  3119 0000043A 39D0                    	cmp ax, dx		; source above destination ?
  3120 0000043C 770A                    	ja .up			; yes, move up (forwards) -->
  3121 0000043E 747B                    	je .return		; same, no need to move -->
  3122 00000440 50                      	push ax
  3123 00000441 01C8                    	add ax, cx		; (expected not to carry)
  3124 00000443 39D0                    	cmp ax, dx		; end of source is above destination ?
  3125 00000445 58                      	pop ax
  3126 00000446 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 00000448 50                      	push ax
  3132 00000449 52                      	push dx
  3133                                  .uploop:
  3134 0000044A 8ED8                    	mov ds, ax
  3135 0000044C 8EC2                    	mov es, dx
  3136 0000044E 31FF                    	xor di, di
  3137 00000450 31F6                    	xor si, si		; -> start of segment
  3138 00000452 81E90010                	sub cx, 1000h		; 64 KiB left ?
  3139 00000456 7610                    	jbe .uplast		; no -->
  3140 00000458 51                      	push cx
  3141 00000459 B90080                  	mov cx, 10000h /2
  3142 0000045C F3A5                    	rep movsw		; move 64 KiB
  3143 0000045E 59                      	pop cx
  3144 0000045F 050010                  	add ax, 1000h
  3145 00000462 81C20010                	add dx, 1000h		; -> next segment
  3146 00000466 EBE2                    	jmp short .uploop	; proceed for more -->
  3147                                  .uplast:
  3148 00000468 81C10010                	add cx, 1000h		; restore counter
  3149 0000046C D1E1                    	shl cx, 1
  3150 0000046E D1E1                    	shl cx, 1
  3151 00000470 D1E1                    	shl cx, 1		; *8, paragraphs to words
  3152 00000472 F3A5                    	rep movsw		; move last part
  3153 00000474 5A                      	pop dx
  3154 00000475 58                      	pop ax
  3155 00000476 EB43                    	jmp short .return
  3156                                  
  3157                                  .down:
  3158 00000478 FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
  3159                                  .dnloop:
  3160 00000479 81E90010                	sub cx, 1000h		; 64 KiB left ?
  3161 0000047D 761A                    	jbe .dnlast		; no -->
  3162 0000047F 50                      	push ax
  3163 00000480 52                      	push dx
  3164 00000481 01C8                    	add ax, cx
  3165 00000483 01CA                    	add dx, cx
  3166 00000485 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
  3167 00000487 8EC2                    	mov es, dx
  3168 00000489 5A                      	pop dx
  3169 0000048A 58                      	pop ax
  3170 0000048B BFFEFF                  	mov di, -2
  3171 0000048E 89FE                    	mov si, di		; moved from last word down
  3172 00000490 51                      	push cx
  3173 00000491 B90080                  	mov cx, 10000h /2
  3174 00000494 F3A5                    	rep movsw		; move 64 KiB
  3175 00000496 59                      	pop cx
  3176 00000497 EBE0                    	jmp short .dnloop	; proceed for more -->
  3177                                  .dnlast:
  3178 00000499 81C10010                	add cx, 1000h		; restore counter
  3179 0000049D D1E1                    	shl cx, 1
  3180 0000049F D1E1                    	shl cx, 1
  3181 000004A1 D1E1                    	shl cx, 1		; *8, paragraphs to words
  3182 000004A3 89CF                    	mov di, cx
  3183 000004A5 4F                      	dec di
  3184 000004A6 D1E7                    	shl di, 1		; words to offset, -> last word
  3185 000004A8 89FE                    	mov si, di
  3186 000004AA 8ED8                    	mov ds, ax
  3187 000004AC 8EC2                    	mov es, dx		; first segment correct
  3188                                  
  3189                                  		; Refer to comment in init0_movp.
  3190                                  %if _AMD_ERRATUM_109_WORKAROUND
  3191 000004AE E308                    	jcxz @FF
  3192 000004B0 83F914                  	cmp cx, 20
  3193 000004B3 7703                    	ja @FF
  3194                                  @@:
  3195 000004B5 A5                      	movsw
  3196 000004B6 E2FD                    	loop @B
  3197                                  @@:
  3198                                  %endif
  3199 000004B8 F3A5                    	rep movsw		; move first part
  3200 000004BA FC                      	cld
  3201                                  .return:
  3202 000004BB 5F                      	pop di
  3203 000004BC 07                      	pop es
  3204 000004BD 5E                      	pop si
  3205 000004BE 1F                      	pop ds
  3206 000004BF 59                      	pop cx
  3207 000004C0 C3                      	retn
  3208                                  
  3209                                  
  3210 000004C1 90<rep 3h>              	align 4
  3211                                  %if _RELOAD_XMS
  3212                                  init2_xmsm_from_save:
  3213                                  	istruc XMSM
  3214 000004C4 D03B0100                at XMSM.size_,	dd payload_end - payload
  3215 000004C8 00<rep Ch>              	iend
  3216                                  init2_xmsm_to_save:
  3217                                  	istruc XMSM
  3218 000004D4 D03B0100                at XMSM.size_,	dd payload_end - payload
  3219 000004D8 00<rep Ch>              	iend
  3220                                  %endif
  3221                                  
  3222 000004E4 90<rep Ch>              	align 16
  3223                                  
  3224                                  %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE
  3225                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  3226                                  payload_uncompressed:
  3227                                  	incbin _UNCOMPRESSED_FILE
  3228                                  .end:
  3229                                  	db 38
  3230                                  	align 16, db 38
  3231                                  %endif
  3232                                  init2_end:
  3233                                  %endif
  3234                                  
