     1                                  
     2                                  %if 0
     3                                  
     4                                  lDOS iniload packed payload
     5                                   by C. Masloch, 2018-2020
     6                                  
     7                                  Usage of the works is permitted provided that this
     8                                  instrument is retained with the works, so that any entity
     9                                  that uses the works is notified of this instrument.
    10                                  
    11                                  DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                                  
    13                                  
    14                                  Includes one of several depackers, some of which are under
    15                                  separate usage conditions. Refer to the individual depacker
    16                                  source files for the applicable usage conditions.
    17                                  
    18                                  %endif
    19                                  
    20                                  %include "lmacros2.mac"
    21                              <1> [list -]
    34                              <1> [list -]
    21                                  
    22                                  	struc LOADSTACKVARS, -10h
    23 FFFFFFF0 ????????                lsvFirstCluster:	resd 1
    24 FFFFFFF4 ????????                lsvFATSector:		resd 1
    25 FFFFFFF8 ????                    lsvFATSeg:		resw 1
    26 FFFFFFFA ????                    lsvLoadSeg:		resw 1
    27 FFFFFFFC ????????                lsvDataStart:		resd 1
    28                                  	endstruc
    29                                  
    30                                  	struc LOADDATA, LOADSTACKVARS - 10h
    31 FFFFFFE0 ????                    ldMemoryTop:	resw 1
    32 FFFFFFE2 ????                    ldLoadTop:	resw 1
    33 FFFFFFE4 ????                    ldSectorSeg:	resw 1
    34 FFFFFFE6 ??                      ldFATType:	resb 1
    35 FFFFFFE7 ??                      ldHasLBA:	resb 1
    36 FFFFFFE8 ????                    ldClusterSize:	resw 1
    37 FFFFFFEA ????                    ldParaPerSector:resw 1
    38 FFFFFFEC ????                    ldLoadingSeg:	resw 1
    39 FFFFFFEE ????                    ldLoadUntilSeg:	resw 1
    40                                  	endstruc
    41                                  
    42                                  
    43                                  %ifndef _MAP
    44                                  %elifempty _MAP
    45                                  %else	; defined non-empty, str or non-str
    46                                  	[map all _MAP]
    47                                  %endif
    48                                  
    49                                  	defaulting
    50                                  
    51                                  	numdef DEBUG0		; use errordata to generate an error code
    52                                  	numdef DEBUG1		; dump_stack_frame after an error occurred
    53                                  	numdef DEBUG2		; dump_stack_frame before blz_depack_safe call
    54                                  	numdef DEBUG3		; dump_stack_frame at start of blz_depack_safe
    55                                  
    56                                  	numdef ALLOW_OVERLAPPING,	1	; allow overlapping src and dst
    57                                  	numdef TEST_PROGRAM,		0
    58                                  	numdef TEST_PROGRAM_DECOMPRESSED_SIZE,		0,0
    59                                  %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE
    60                                   %error Test program has to learn of decompressed size.
    61                                  %endif
    62                                  	numdef TEST_PROGRESS,	0
    63                                  
    64                                  	numdef EXEC_OFFSET,	0
    65                                  	numdef EXEC_SEGMENT,	0
    66                                  	numdef IMAGE_EXE,	0
    67                                  %if ! _IMAGE_EXE && _TEST_PROGRAM
    68                                   %error Test program can only be used as EXE.
    69                                  %endif
    70                                  	numdef IMAGE_EXE_CS,	-16	; relative-segment for CS
    71                                  	numdef IMAGE_EXE_IP,	256 +64	; value for IP
    72                                  		; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0.
    73                                  	numdef IMAGE_EXE_SS,	-16	; relative-segment for SS
    74                                  	numdef IMAGE_EXE_SP,	0FFFEh	; value for SP (0 underflows)
    75                                  	numdef IMAGE_EXE_AUTO_STACK,	0, 2048	; use stack behind image
    76                                  		; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of
    77                                  		;  the same name. This one is only used as a flag; if non-zero,
    78                                  		;  keep the stack given to us by iniload; if zero, set up the
    79                                  		;  stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP.
    80                                  	numdef DEVICE,			0
    81                                  	gendef DEVICE_NAME,		""
    82                                  	numdef DEVICE_ATTRIBUTE,	8000h
    83                                  	numdef DEVICE_ZERO_ENTRYPOINT,	0
    84                                  %if _DEVICE
    85                                   %ifidn _DEVICE_NAME, ""
    86                                    %error Device name must be set
    87                                   %endif
    88                                  %endif
    89                                  
    90                                  	numdef BRIEFLZ,		0
    91                                  	numdef LZ4,		0
    92                                  	numdef SNAPPY,		0
    93                                  	numdef EXODECR,		0
    94                                  	numdef X,		0
    95                                  	numdef HEATSHRINK,	0
    96                                  	numdef LZD,		0
    97                                  	numdef LZO,		0
    98                                  	numdef LZSA2,		0
    99                                  	numdef APL,		0
   100                                  	numdef BZP,		0
   101                                  %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK 	+ !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP) != 1
   103                                   %fatal Exactly one compression method must be selected.
   104                                  %endif
   105                                  %assign ADDITIONAL_MEMORY 0
   106                                  %if _BRIEFLZ
   107                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BLZ"
   108                                  %elif _LZ4
   109                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ4"
   110                                  %elif _SNAPPY
   111                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SZ"
   112                                  %elif _EXODECR
   113                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.EXO"
   114                                  %elif _X
   115                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.X"
   116                                  %elif _HEATSHRINK
   117                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.HS"
   118                                  %elif _LZD
   119                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ"
   120                                  %elif _LZO
   121                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZO"
   122                                  %elif _LZSA2
   123                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SA2"
   124                                  %elif _APL
   125                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.APL"
   126                                  %elif _BZP
   127                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BZP"
   128                                  %endif
   129                                  	numdef PAYLOAD_KERNEL_MAX_PARAS,	0, 0
   130                                  %if _PAYLOAD_KERNEL_MAX_PARAS && ! _IMAGE_EXE
   131                                   %error Kernel mode max paras requires building dual-mode executable
   132                                  %endif
   133                                  	numdef COUNTER,		0, 32
   134                                  %if (_COUNTER - 1) & _COUNTER
   135                                   %error COUNTER must be a power of two
   136                                  %endif
   137                                  
   138                                  
   139                                  	cpu 8086
   140                                  	section INIT0 start=0 vstart=0
   141                                  init0_start:
   142                                  %if _DEVICE
   143                                  		; The device header is of a fixed format.
   144                                  		;  For our purposes, the 4-byte code for
   145                                  		;  each the strategy entry and the
   146                                  		;  interrupt entry is part of this format.
   147                                  		; (DOS may read the attributes or entrypoint
   148                                  		;  offsets before calling either, so in the inicomp
   149                                  		;  stage we need to recreate in the entrypoints part
   150                                  		;  exactly what the application has here.)
   151                                  device_header:
   152                                  .next:
   153                                   %if _DEVICE_ZERO_ENTRYPOINT
   154                                  	fill 2, -1, jmp strict short j_zero_entrypoint
   155                                  	dw -1
   156                                   %else
   157                                  	dd -1				; link to next device
   158                                   %endif
   159                                  .attributes:
   160                                  	dw _DEVICE_ATTRIBUTE		; attributes
   161                                  .strategy:
   162                                  	dw .strategy_entry		; -> strategy entry
   163                                  .interrupt:
   164                                  	dw .interrupt_entry		; -> interrupt entry
   165                                  .name:
   166                                  	fill 8, 32, db _DEVICE_NAME	; character device name,
   167                                  					;  or block device number of units
   168                                  					;  + optional name
   169                                  .strategy_entry:
   170                                  	fill 4, 90h, jmp device_entrypoint
   171                                  .interrupt_entry:
   172                                  	fill 4, 90h, retf
   173                                  %endif
   174                                  
   175                                  
   176                                  j_zero_entrypoint:
   177                                  
   178                                  %if _IMAGE_EXE || _DEVICE
   179 00000000 90                      	nop
   180 00000001 90<rep 1Fh>             	align 32, nop
   181                                  init0_kernel_entry:
   182                                  		; cs:ip = load seg : 32 here
   183                                  %if ($ - $$) != 32
   184                                   %error Wrong kernel mode entrypoint
   185                                  %endif
   186                                  %if _TEST_PROGRAM
   187                                  @@:
   188 00000020 CC                      	int3
   189 00000021 FB                      	sti
   190 00000022 F4                      	hlt
   191 00000023 EBFB                    	jmp @B
   192                                  %endif
   193 00000025 31DB                    	xor bx, bx		; 0 = kernel mode
   194 00000027 50                      	push ax
   195 00000028 8CC8                    	mov ax, cs
   196 0000002A 83C020                  	add ax, (init0_end - init0_start) >> 4
   197 0000002D 8B56E2                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   198 00000030 BE6000                  	mov si, 60h		; => destination
   199 00000033 EB1B                    	jmp init0_common
   200                                  
   201                                   %if _IMAGE_EXE
   202 00000035 90<rep Bh>              	align 64, nop
   203                                  init0_exe_entry:
   204                                  		; NOTE:	This part is called with ip = 256 + 64, cs = PSP.
   205                                  %if ($ - $$) != 64
   206                                   %error Wrong EXE mode entrypoint
   207                                  %endif
   208 00000040 BB0100                  	mov bx, 1		; EXE mode
   209 00000043 50                      	push ax
   210 00000044 8CD2                    	mov dx, ss		; => after end of available space
   211 00000046 8CC8                    	mov ax, cs
   212 00000048 83C030                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   213 0000004B 8CCE                    	mov si, cs
   214 0000004D 83C610                  	add si, 256 >> 4	; => destination
   215                                   %endif
   216                                  
   217                                  init0_common:
   218                                  		; NOTE:	This part must be position-independent, as it is
   219                                  		;	 called either with ip = init0_common (kernel mode)
   220                                  		;	 or ip = init0_common + 256 (EXE mode).
   221 00000050 FC                      	cld
   222                                  %if _TEST_PROGRAM
   223 00000051 81EABD0D                	sub dx, ( (payload_end - payload) ) >> 4
   224 00000055 721A                    	jc .error
   225 00000057 B94826                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   229 0000005A 29CA                    	sub dx, cx
   230 0000005C 7213                    	jc .error
   231 0000005E 39C2                    	cmp dx, ax
   232 00000060 720F                    	jb .error
   233                                  %else
   234                                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   237                                  	sub dx, cx
   238                                  %endif
   239 00000062 56                      	push si
   240 00000063 E82C00                  	call init0_movp
   241 00000066 5E                      	pop si
   242                                  %else
   243                                  	cld
   244                                  	mov ax, cs
   245                                  	add ax, (init0_end - init0_start) >> 4
   246                                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   249                                  	mov dx, word [ bp + ldLoadTop ]
   250                                  	sub dx, cx
   251                                  	call init0_movp
   252                                  %endif
   253                                  
   254 00000067 89D0                    	mov ax, dx
   255                                  %if _TEST_PROGRAM
   256 00000069 05540E                  	add ax, ( 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   260                                  %else
   261                                  	add ax, ( 		+ (payload_end - payload) 		) >> 4
   264                                  %endif
   265 0000006C 31C9                    	xor cx, cx
   266 0000006E 50                      	push ax
   267 0000006F 51                      	push cx
   268 00000070 CB                      	retf			; jump to relocated INIT1:init1_start
   269                                  
   270                                  
   271                                  %if _TEST_PROGRAM
   272                                  .error:
   273 00000071 0E                      	push cs
   274 00000072 1F                      	pop ds
   275 00000073 BA[1402]                	mov dx, init0_msg.error_stderr + 256
   276 00000076 B92500                  	mov cx, init0_msg.error_stderr.length
   277 00000079 BB0200                  	mov bx, 2
   278 0000007C B440                    	mov ah, 40h
   279 0000007E CD21                    	int 21h
   280 00000080 BA[3902]                	mov dx, init0_msg.error_stdout + 256
   281 00000083 B90600                  	mov cx, init0_msg.error_stdout.length
   282 00000086 BB0100                  	mov bx, 1
   283 00000089 B440                    	mov ah, 40h
   284 0000008B CD21                    	int 21h
   285 0000008D B8FF4C                  	mov ax, 4CFFh
   286 00000090 CD21                    	int 21h
   287                                  %endif
   288                                  
   289                                  
   290                                  %if _DEVICE
   291                                  device_entrypoint:
   292                                  %if _TEST_PROGRAM
   293                                  @@:
   294                                  	int3
   295                                  	sti
   296                                  	hlt
   297                                  	jmp @B
   298                                  %endif
   299                                  	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   300                                  	je @F
   301                                  
   302                                  	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   303                                  	retf
   304                                  
   305                                  @@:
   306                                  	or word [cs:device_header.next], -1
   307                                  	push cs
   308                                  	push word [cs:device_header.strategy]
   309                                  					; -> far return to payload's strategy
   310                                  	push bp
   311                                  	push ds
   312                                  	push si
   313                                  	push di
   314                                  	push dx
   315                                  	push cx
   316                                  	push ax
   317                                  	push bx
   318                                  	push es
   319                                  
   320                                  	mov ax, word [es:bx + 14 + 2]
   321                                  	xor dx, dx
   322                                  	mov cx, 4
   323                                  @@:
   324                                  	shl ax, 1
   325                                  	rcl dx, 1
   326                                  	loop @B
   327                                  	add ax, word [es:bx + 14]
   328                                  	adc dx, 0		; dx:ax = linear address behind end
   329                                  
   330                                  	mov cl, 4
   331                                  @@:
   332                                  	shr dx, 1
   333                                  	rcr ax, 1
   334                                  	loop @B			; ax => behind end
   335                                  
   336                                  	mov di, cs
   337                                  image_size: equ  ( (init0_end - init0_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   341                                  	add di, image_size >> 4		; di => end of image
   342                                  
   343                                  	cmp ax, di			; enough memory to hold all of us ?
   344                                  	jae .have_some_memory		; yes -->
   345                                  
   346                                  	push cs
   347                                  	pop ds
   348                                  	mov dx, .msg_no_memory
   349                                  	mov ah, 09h
   350                                  	int 21h
   351                                  
   352                                  	mov ax, 3000h
   353                                  	int 21h
   354                                  	cmp al, 5
   355                                  	jae @F
   356                                  	mov dx, .msg_dos_below_5
   357                                  	mov ah, 09h
   358                                  	int 21h
   359                                  @@:
   360                                  
   361                                  	mov dx, .msg_linebreak
   362                                  	mov ah, 09h
   363                                  	int 21h
   364                                  
   365                                  		; tear down the stack frame and modify the request header
   366                                  	pop es
   367                                  	pop bx
   368                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   369                                  	mov byte [es:bx + 13], 0	; set number of units = 0
   370                                  	mov word [es:bx + 14 + 2], cs
   371                                  	and word [es:bx + 14], 0	; -> after end of memory to allocate
   372                                  	pop ax
   373                                  	pop cx
   374                                  	pop dx
   375                                  	pop di
   376                                  	pop si
   377                                  	pop ds
   378                                  	pop bp
   379                                  	add sp, 4		; discard far return to payload's strategy
   380                                  	retf			; return to DOS
   381                                  
   382                                  .msg_no_memory:		ascic "Load error: Not enough memory."
   383                                  .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   384                                  .msg_linebreak:		ascic 13,10
   385                                  
   386                                  
   387                                  .have_some_memory:
   388                                  	mov dx, ax		; => after end of memory
   389                                  	mov bx, 2		; device mode
   390                                  	push ax
   391                                  	mov ax, cs
   392                                  	add ax, (init0_end - init0_start) >> 4
   393                                  	mov si, cs		; => destination
   394                                  	jmp init0_common
   395                                  %endif
   396                                  
   397                                  
   398                                  		; Move paragraphs
   399                                  		;
   400                                  		; INP:	ax => source
   401                                  		;	dx => destination
   402                                  		;	cx = number of paragraphs
   403                                  		; CHG:	cx, ds, si, es, di
   404                                  		; OUT:	ax and dx unchanged
   405                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   406                                  		;	Do not provide a wrapped/HMA source or destination!
   407                                  init0_movp:
   408 00000092 39D0                    	cmp ax, dx		; source above destination ?
   409 00000094 770A                    	ja .up			; yes, move up (forwards) -->
   410 00000096 747B                    	je .return		; same, no need to move -->
   411 00000098 50                      	push ax
   412 00000099 01C8                    	add ax, cx		; (expected not to carry)
   413 0000009B 39D0                    	cmp ax, dx		; end of source is above destination ?
   414 0000009D 58                      	pop ax
   415 0000009E 7730                    	ja .down		; yes, move from top down -->
   416                                  	; Here, the end of source is below-or-equal the destination,
   417                                  	;  so they do not overlap. In this case we prefer moving up.
   418                                  
   419                                  .up:
   420 000000A0 50                      	push ax
   421 000000A1 52                      	push dx
   422                                  .uploop:
   423 000000A2 8ED8                    	mov ds, ax
   424 000000A4 8EC2                    	mov es, dx
   425 000000A6 31FF                    	xor di, di
   426 000000A8 31F6                    	xor si, si		; -> start of segment
   427 000000AA 81E90010                	sub cx, 1000h		; 64 KiB left ?
   428 000000AE 7610                    	jbe .uplast		; no -->
   429 000000B0 51                      	push cx
   430 000000B1 B90080                  	mov cx, 10000h /2
   431 000000B4 F3A5                    	rep movsw		; move 64 KiB
   432 000000B6 59                      	pop cx
   433 000000B7 050010                  	add ax, 1000h
   434 000000BA 81C20010                	add dx, 1000h		; -> next segment
   435 000000BE EBE2                    	jmp short .uploop	; proceed for more -->
   436                                  .uplast:
   437 000000C0 81C10010                	add cx, 1000h		; restore counter
   438 000000C4 D1E1                    	shl cx, 1
   439 000000C6 D1E1                    	shl cx, 1
   440 000000C8 D1E1                    	shl cx, 1		; *8, paragraphs to words
   441 000000CA F3A5                    	rep movsw		; move last part
   442 000000CC 5A                      	pop dx
   443 000000CD 58                      	pop ax
   444 000000CE EB43                    	jmp short .return
   445                                  
   446                                  .down:
   447 000000D0 FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   448                                  .dnloop:
   449 000000D1 81E90010                	sub cx, 1000h		; 64 KiB left ?
   450 000000D5 761A                    	jbe .dnlast		; no -->
   451 000000D7 50                      	push ax
   452 000000D8 52                      	push dx
   453 000000D9 01C8                    	add ax, cx
   454 000000DB 01CA                    	add dx, cx
   455 000000DD 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   456 000000DF 8EC2                    	mov es, dx
   457 000000E1 5A                      	pop dx
   458 000000E2 58                      	pop ax
   459 000000E3 BFFEFF                  	mov di, -2
   460 000000E6 89FE                    	mov si, di		; moved from last word down
   461 000000E8 51                      	push cx
   462 000000E9 B90080                  	mov cx, 10000h /2
   463 000000EC F3A5                    	rep movsw		; move 64 KiB
   464 000000EE 59                      	pop cx
   465 000000EF EBE0                    	jmp short .dnloop	; proceed for more -->
   466                                  .dnlast:
   467 000000F1 81C10010                	add cx, 1000h		; restore counter
   468 000000F5 D1E1                    	shl cx, 1
   469 000000F7 D1E1                    	shl cx, 1
   470 000000F9 D1E1                    	shl cx, 1		; *8, paragraphs to words
   471 000000FB 89CF                    	mov di, cx
   472 000000FD 4F                      	dec di
   473 000000FE D1E7                    	shl di, 1		; words to offset, -> last word
   474 00000100 89FE                    	mov si, di
   475 00000102 8ED8                    	mov ds, ax
   476 00000104 8EC2                    	mov es, dx		; first segment correct
   477                                  
   478                                  
   479                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   480                                  %if 0
   481                                  
   482                                  Jack R. Ellis pointed out this erratum:
   483                                  
   484                                  Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
   485                                  
   486                                  109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
   487                                  
   488                                  Description
   489                                  
   490                                  In certain situations a REP MOVS instruction may lead to
   491                                  incorrect results. An incorrect address size, data size
   492                                  or source operand segment may be used or a succeeding
   493                                  instruction may be skipped. This may occur under the
   494                                  following conditions:
   495                                  
   496                                  * EFLAGS.DF=1 (the string is being moved in the reverse direction).
   497                                  
   498                                  * The number of items being moved (RCX) is between 1 and 20.
   499                                  
   500                                  * The REP MOVS instruction is preceded by some microcoded instruction
   501                                    that has not completely retired by the time the REP MOVS begins
   502                                    execution. The set of such instructions includes BOUND, CLI, LDS,
   503                                    LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
   504                                  
   505                                  Potential Effect on System
   506                                  
   507                                  Incorrect results may be produced or the system may hang.
   508                                  
   509                                  Suggested Workaround
   510                                  
   511                                  Contact your AMD representative for information on a BIOS update.
   512                                  
   513                                  %endif
   514                                  
   515                                  %if _AMD_ERRATUM_109_WORKAROUND
   516 00000106 E308                    	jcxz @FF
   517 00000108 83F914                  	cmp cx, 20
   518 0000010B 7703                    	ja @FF
   519                                  @@:
   520 0000010D A5                      	movsw
   521 0000010E E2FD                    	loop @B
   522                                  @@:
   523                                  %endif
   524 00000110 F3A5                    	rep movsw		; move first part
   525 00000112 FC                      	cld
   526                                  .return:
   527 00000113 C3                      	retn
   528                                  
   529                                  
   530                                  	section PAYLOAD align=16 follows=INIT0
   531                                  payload:
   532 00000000 <bin DBC2h>             	incbin _PAYLOAD_FILE
   533                                  .end:
   534 0000DBC2 26<rep Eh>              	align 16, db 38
   535                                  payload_end:
   536                                  
   537                                  
   538                                  	section INIT1 align=16 follows=PAYLOAD vstart=0
   539                                  init1_start:
   540                                  		; INP:	ax = cs = INIT1
   541                                  		;	dx = cs - (payload_end - payload) >> 4 => source data
   542                                  		;	if kernel mode:
   543                                  		;	 ss:bp -> LOADDATA and LOADSTACKVARS
   544                                  		;	 ss:sp -> valid stack above [bp + ldLoadTop]
   545                                  		;	 60h => destination
   546                                  		;	any mode:
   547                                  		;	 word [ss:sp] = value for ax
   548                                  		;	 bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode
   549                                  		;	 si => destination (60h for kernel mode,
   550                                  		;		after PSP for EXE mode,
   551                                  		;		at device header for device mode)
   552                                  		;	 if EXE mode:
   553                                  		;	  ss:sp -> valid stack above INIT1
   554                                  		;	  bp = unset
   555                                  		;	 if device mode:
   556                                  		;	  ss:sp -> device entrypoint stack
   557                                  		;	  holds: es, bx, ax, cx, dx, di, si, ds, bp,
   558                                  		;		  far address of payload strategy entrypoint,
   559                                  		;		  far return address to DOS
   560                                  		;	  bp = unset
   561                                  		; STT:	UP
   562                                  		; CHG:	ax, bx, cx, dx, es, ds, si, di
   563                                  %if _IMAGE_EXE || _DEVICE
   564                                  	lframe
   565 00000000 5589E5                  	lenter
   566                                  	lvar word,	exemode		; must be bp - 2!
   567 00000003 53                      	 push bx
   568                                   %if ?exemode != -2
   569                                    %error exemode variable must be directly below bp
   570                                   %endif
   571 00000004 56                      	push si
   572                                  %else
   573                                  	xor bx, bx		; always tell them it is kernel mode
   574                                  %endif
   575                                  
   576                                  %if _IMAGE_EXE
   577 00000005 8EC6                    	mov es, si		; es => destination
   578                                  %else
   579                                  	mov ax, 60h
   580                                  	mov es, ax		; es => destination
   581                                  %endif
   582 00000007 31FF                    	xor di, di		; -> destination
   583                                  
   584 00000009 8EDA                    	mov ds, dx
   585 0000000B 31F6                    	xor si, si		; -> source
   586                                  
   587 0000000D B9C2DB                  	mov cx, (payload.end - payload) & 0FFFFh
   588                                  %if (payload.end - payload) >> 16
   589                                  	mov dx, (payload.end - payload) >> 16	; = length of source
   590                                  %else
   591 00000010 31D2                    	xor dx, dx
   592                                  %endif
   593                                  %if _PAYLOAD_KERNEL_MAX_PARAS
   594                                  	mov ax, _PAYLOAD_KERNEL_MAX_PARAS
   595                                  	test bx, bx
   596                                  	jz @F
   597                                  %endif
   598 00000012 B8FFFF                  	mov ax, -1
   599                                  @@:
   600                                  		; INP:	ds:si -> source
   601                                  		;	dx:cx = length of source
   602                                  		;	es:di -> destination (below source)
   603                                  		;	bx = EXE mode flag
   604                                  		;	 (1 if EXE mode, 0 if kernel mode)
   605                                  		;	 (always 0 if this is a build without EXE mode)
   606                                  		;	if _PAYLOAD_KERNEL_MAX_PARAS:
   607                                  		;	 ax = maximum amount in paragraphs of destination needed
   608                                  		;	 (-1 if full source should be decompressed)
   609                                  		;	else:
   610                                  		;	 ax = -1
   611                                  		; Note:	The destination reaches up to below the source.
   612 00000015 E8A902                  	call depack
   613                                  %ifn _TEST_PROGRAM
   614                                  	jc strict short error
   615                                  %endif
   616                                  %if _IMAGE_EXE
   617 00000018 5E                      	pop si			; si
   618                                   %if _TEST_PROGRAM
   619 00000019 58                      	pop ax			; (discard ?exemode, leave bx as returned)
   620                                   %else
   621                                  	pop bx			; ?exemode
   622                                   %endif
   623 0000001A 5D                      	pop bp			; bp
   624 0000001B 58                      	pop ax			; ax
   625                                  	lleave ctx
   626                                  %endif
   627                                  %if _TEST_PROGRAM
   628 0000001C CB                      	retf
   629 0000001D 90                      	nop
   630                                  %endif
   631                                  
   632                                  %if _DEVICE
   633                                  	test bl, 2
   634                                  	jz .jmp_exe_or_kernel_mode
   635                                  
   636                                  .jmp_device_mode:
   637                                  	mov ds, si
   638                                  	or word [device_header.next], -1
   639                                  	pop es
   640                                  	pop bx
   641                                  	pop ax
   642                                  	pop cx
   643                                  	pop dx
   644                                  	pop di
   645                                  	pop si
   646                                  	pop ds
   647                                  	pop bp
   648                                  	retf			; transfer to payload strategy entrypoint
   649                                  				; still on stack: far return address to DOS
   650                                  
   651                                  .jmp_exe_or_kernel_mode:
   652                                  %endif
   653                                  
   654                                  %if _IMAGE_EXE
   655 0000001E F6C301                  	test bl, 1
   656 00000021 7410                    	jz .jmp_kernel_mode
   657                                  
   658                                  .jmp_exe_mode:
   659                                  %if ! _IMAGE_EXE_AUTO_STACK
   660                                  	mov cx, cs
   661                                  	lea dx, [si + _IMAGE_EXE_SS]
   662                                  	push dx			; stack = relocated ss value
   663                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
   664                                  	cmp cx, dx		; INIT1 code is above intended stack ?
   665                                  	jae @F			; yes -->
   666                                  
   667                                  	lframe
   668                                  	lenter
   669                                  	lvar	word, exemode
   670                                  	 push bx
   671                                   %if ?exemode != -2
   672                                    %error exemode variable must be directly below bp
   673                                   %endif
   674                                  	mov bx, -1		; unimplemented, return error
   675                                  	jmp error
   676                                  	lleave ctx
   677                                  @@:
   678                                  	cli
   679                                  	pop ss			; = relocated ss value
   680                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
   681                                  	sti
   682                                  %endif
   683                                  
   684 00000023 31C9                    	xor cx, cx
   685 00000025 51                      	push cx			; put zero on top of stack
   686                                  
   687                                  %if _IMAGE_EXE_IP < 256
   688                                  	mov cl, _IMAGE_EXE_IP
   689                                  %elif (_IMAGE_EXE_IP & 255) == 0
   690                                  	mov ch, _IMAGE_EXE_IP >> 8
   691                                  %else
   692 00000026 B94001                  	mov cx, _IMAGE_EXE_IP
   693                                  %endif
   694                                  
   695                                  %if _IMAGE_EXE_CS == -16
   696 00000029 83C6F0                  	add si, -16
   697 0000002C 8EDE                    	mov ds, si
   698 0000002E 8EC6                    	mov es, si
   699                                  %else
   700                                  	lea dx, [si - 10h]	; => PSP
   701                                  	mov ds, dx
   702                                  	mov es, dx		; ds = es => PSP
   703                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
   704                                  %endif
   705 00000030 56                      	push si
   706 00000031 51                      	push cx
   707 00000032 CB                      	retf			; jump to EXE mode of image
   708                                  
   709                                  %endif
   710                                  .jmp_kernel_mode:
   711 00000033 EA20006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
   712                                  
   713                                  
   714                                  error:
   715 00000038 0E                      	push cs
   716 00000039 1F                      	pop ds
   717                                  %if _DEBUG0
   718                                  	mov si, msg.error_begin
   719                                  	call disp_error
   720                                  	xchg ax, bx			; ax = error code
   721                                  	call disp_ax_hex
   722                                  	mov si, msg.error_end
   723                                  %else
   724 0000003A BE[7600]                	mov si, msg.error
   725                                  %endif
   726 0000003D E81400                  	call disp_error
   727                                  
   728                                  %if _DEVICE
   729                                  	test byte [bp - 2], 2
   730                                  	jz .exit_app_or_kernel
   731                                  
   732                                  	pop si				; => device segment
   733                                  	pop bx				; mode word
   734                                  	pop bp
   735                                  	pop ax
   736                                  	mov es, si
   737                                  	xor di, di			; -> device header
   738                                  	 push cs
   739                                  	 pop ds
   740                                  	mov si, device_header_copy	; -> to reset header
   741                                  	mov cx, words(device_header_copy.length)
   742                                  	rep movsw		; overwrite device header with default
   743                                  				;  (reset to a valid state after unsuccessful
   744                                  				;  decompression, which may have partially
   745                                  				;  written the header already)
   746                                  	 push es
   747                                  	 pop ds				; -> device segment
   748                                  	pop es
   749                                  	pop bx
   750                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   751                                  	mov byte [es:bx + 13], 0	; set number of units = 0
   752                                  	mov word [es:bx + 14 + 2], ds
   753                                  	and word [es:bx + 14], 0	; -> after end of memory to allocate
   754                                  	pop ax
   755                                  	pop cx
   756                                  	pop dx
   757                                  	pop di
   758                                  	pop si
   759                                  	pop ds
   760                                  	pop bp
   761                                  	add sp, 4		; discard far return to payload's strategy
   762                                  	retf			; return to DOS
   763                                  
   764                                  
   765                                  .exit_app_or_kernel:
   766                                  %endif
   767                                  
   768                                  %if _IMAGE_EXE
   769 00000040 F646FE01                	test byte [bp - 2], 1
   770 00000044 7405                    	jz .exit_kernel_mode
   771                                  
   772 00000046 B87F4C                  	mov ax, 4C7Fh
   773 00000049 CD21                    	int 21h
   774                                  
   775                                  .exit_kernel_mode:
   776                                  %endif
   777 0000004B 31C0                    	xor ax, ax
   778 0000004D CD16                    	int 16h
   779 0000004F CD19                    	int 19h
   780                                  
   781                                  
   782                                  %if _DEVICE
   783                                  	align 16
   784                                  device_header_copy:
   785                                  .:
   786                                  .next:
   787                                  	dd -1				; already initialised
   788                                  .attributes:
   789                                  	dw _DEVICE_ATTRIBUTE
   790                                  .strategy:
   791                                  	dw .strategy_entry - .		; -> strategy entry
   792                                  .interrupt:
   793                                  	dw .interrupt_entry - .		; -> interrupt entry
   794                                  .name:
   795                                  	fill 8, 32, db _DEVICE_NAME
   796                                  .strategy_entry:
   797                                  	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
   798                                  .interrupt_entry:
   799                                  	fill 4, 90h, retf
   800                                  
   801                                  .set_error:
   802                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   803                                  	retf
   804                                  .length: equ $ - .
   805                                  %endif
   806                                  
   807                                  
   808                                  disp_error.loop:
   809 00000051 E80600                  	call disp_al
   810                                  disp_error:
   811 00000054 AC                      	lodsb
   812 00000055 84C0                    	test al, al
   813 00000057 75F8                    	jnz .loop
   814 00000059 C3                      	retn
   815                                  
   816                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
   817                                  disp_ax_hex:			; ax
   818                                  		xchg al,ah
   819                                  		call disp_al_hex		; display former ah
   820                                  		xchg al,ah			;  and fall trough for al
   821                                  disp_al_hex:			; al
   822                                  		push cx
   823                                  		mov cl,4
   824                                  		ror al,cl
   825                                  		call disp_al_lownibble_hex	; display former high-nibble
   826                                  		rol al,cl
   827                                  		pop cx
   828                                  						;  and fall trough for low-nibble
   829                                  disp_al_lownibble_hex:
   830                                  		push ax			 ; save ax for call return
   831                                  		and al,00001111b		; high nibble must be zero
   832                                  		add al,'0'			; if number is 0-9, now it's the correct character
   833                                  		cmp al,'9'
   834                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
   835                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
   836                                   .decimalnum:
   837                                  		call disp_al
   838                                  		pop ax
   839                                  		retn
   840                                  %endif
   841                                  
   842                                  disp_al:
   843                                  %if _TEST_PROGRAM
   844 0000005A C3                      	retn
   845                                  %else
   846                                  	push ax
   847                                  %endif
   848 0000005B 53                      	push bx
   849 0000005C 55                      	push bp
   850 0000005D B40E                    	mov ah, 0Eh
   851 0000005F BB0700                  	mov bx, 7
   852                                  %if _IMAGE_EXE || _DEVICE
   853 00000062 52                      	push dx
   854                                  
   855 00000063 F646FE03                	test byte [bp - 2], 1 | 2
   856 00000067 7406                    	jz .display_kernel_mode
   857                                  
   858 00000069 92                      	xchg dx, ax				; dl = input al
   859 0000006A B402                    	mov ah, 02h
   860 0000006C CD21                    	int 21h
   861 0000006E A9                      	db __TEST_IMM16				; (skip int)
   862                                  
   863                                  .display_kernel_mode:
   864                                  %endif
   865 0000006F CD10                    	int 10h
   866                                  %if _IMAGE_EXE
   867 00000071 5A                      	pop dx
   868                                  %endif
   869 00000072 5D                      	pop bp
   870 00000073 5B                      	pop bx
   871 00000074 58                      	pop ax
   872                                  disp_error.ret:
   873 00000075 C3                      	retn
   874                                  
   875                                  
   876                                  msg:
   877                                  %if _DEBUG0
   878                                  .error_begin:	db "Load error: Decompression failure, code ",0
   879                                  .error_end:	db "h.",13,10,0
   880                                  %else
   881 00000076 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
   881 0000007F 723A204465636F6D70-
   881 00000088 72657373696F6E2066-
   881 00000091 61696C7572652E0D0A-
   881 0000009A 00                 
   882                                  %endif
   883                                  
   884                                  
   885                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
   886                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
   887                                  %assign CHECK_POINTERS_VARIABLE_DST 1
   888                                  
   889                                  		; Specific depacker's file is included within label msg.
   890                                  		; In the file, lframe is used and lleave ctx is not used.
   891                                  
   892                                  %if _BRIEFLZ
   893                                  	%include "brieflz.asm"
   894                                  %endif
   895                                  
   896                                  
   897                                  %if _LZ4
   898                                  	%include "lz4.asm"
   899                                  %endif
   900                                  
   901                                  
   902                                  %if _SNAPPY
   903                                  	%include "snappy.asm"
   904                                  %endif
   905                                  
   906                                  
   907                                  %if _EXODECR
   908                                  	%include "exodecr.asm"
   909                                  %endif
   910                                  
   911                                  
   912                                  %if _X
   913                                  	%include "x.asm"
   914                                  %endif
   915                                  
   916                                  
   917                                  %if _HEATSHRINK
   918                                  	%include "heatshr.asm"
   919                                  %endif
   920                                  
   921                                  
   922                                  %if _LZD
   923                                  	%include "lzd.asm"
   924                              <1> 
   925                              <1> %if 0
   926                              <1> 
   927                              <1>     Lzd - Educational decompressor for the lzip format
   928                              <1>     Copyright (C) 2013-2019 Antonio Diaz Diaz.
   929                              <1> 
   930                              <1>     This program is free software. Redistribution and use in source and
   931                              <1>     binary forms, with or without modification, are permitted provided
   932                              <1>     that the following conditions are met:
   933                              <1> 
   934                              <1>     1. Redistributions of source code must retain the above copyright
   935                              <1>     notice, this list of conditions and the following disclaimer.
   936                              <1> 
   937                              <1>     2. Redistributions in binary form must reproduce the above copyright
   938                              <1>     notice, this list of conditions and the following disclaimer in the
   939                              <1>     documentation and/or other materials provided with the distribution.
   940                              <1> 
   941                              <1>     This program is distributed in the hope that it will be useful,
   942                              <1>     but WITHOUT ANY WARRANTY; without even the implied warranty of
   943                              <1>     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   944                              <1> 
   945                              <1> %endif
   946                              <1> 
   947                              <1> 
   948                              <1> 	numdef COUNTER,		0, 128
   949                              <1> %if (_COUNTER - 1) & _COUNTER
   950                              <1>  %error COUNTER must be a power of two
   951                              <1> %endif
   952                              <1> 
   953                              <1> 
   954                              <1> amount_states equ 12
   955                              <1> 
   956                              <1> 		numdef XLATBSEQ, 7
   957                              <1> 		numdef WARNXLATBSEQ, 0
   958                              <1> 
   959                              <1> 
   960                              <1> %if _XLATBSEQ != 7
   961                              <1> next_states.beforealign:
   962                              <1> 	align 2
   963                              <1> next_states:
   964                              <1> .:
   965                              <1> 	times 4 db 0
   966                              <1> 	db 1, 2, 3, 4, 5, 6, 4, 5
   967                              <1> .amount: equ $ - .
   968                              <1>  %if .amount != amount_states
   969                              <1>   %error Invalid next_states array content
   970                              <1>  %endif
   971                              <1>  %assign XLATBTABSIZE $ - .beforealign
   972                              <1> %else
   973                              <1>  %assign XLATBTABSIZE 0
   974                              <1> %endif
   975                              <1> 
   976                              <1> 
   977                              <1> State:
   978                              <1> 		; INP:	ds:bx -> localvariables
   979                              <1> 		;	byte [bx + state.st]
   980                              <1> 		; OUT:	CY if st < 7 (is_char() == true)
   981                              <1> 		;	NC if st >= 7 (is_char() == false)
   982                              <1> 		; CHG:	-
   983                              <1> .is_char:
   984 0000009B 807F2807            <1> 	cmp byte [bx + state.st], 7
   985 0000009F C3                  <1> 	retn
   986                              <1> 
   987                              <1> 
   988                              <1> 		; INP:	ds:bx -> localvariables
   989                              <1> 		;	byte [bx + state.st]
   990                              <1> 		; OUT:	byte [bx + state.st] = al = next state
   991                              <1> 		; CHG:	al, ah (ah only if _XLATBSEQ == 6)
   992                              <1> .set_char:
   993                              <1> 
   994                              <1> .xlatbseq:
   995                              <1> %if 0 == _XLATBSEQ	; 10
   996                              <1> 	push bx
   997                              <1> 	mov al, byte [bx + state.st]
   998                              <1> 	mov bx, next_states
   999                              <1> 	cs xlatb
  1000                              <1> 		; Problem: It is reported that prior to the 386
  1001                              <1> 		;  a segment override on an xlatb instruction
  1002                              <1> 		;  does not have any effect. So this choice is
  1003                              <1> 		;  possibly wrong on those machines.
  1004                              <1> 	pop bx
  1005                              <1> %elif 1 == _XLATBSEQ	; 13
  1006                              <1> 	push bx
  1007                              <1> 	mov al, byte [bx + state.st]
  1008                              <1> 	mov bx, next_states
  1009                              <1> 	push ds
  1010                              <1> 	 push cs
  1011                              <1> 	 pop ds
  1012                              <1> 	xlatb
  1013                              <1> 	pop ds
  1014                              <1> 	pop bx
  1015                              <1> %elif 2 == _XLATBSEQ	; 16
  1016                              <1> 	push bx
  1017                              <1> 	mov al, byte [bx + state.st]
  1018                              <1> 	mov bx, next_states
  1019                              <1> 	add bl, al
  1020                              <1> 	adc bh, 0
  1021                              <1> 	mov al, byte [cs:bx]
  1022                              <1> 	pop bx
  1023                              <1> %elif 3 == _XLATBSEQ	; 14
  1024                              <1> 	push bx
  1025                              <1> 	mov al, byte [bx + state.st]
  1026                              <1> 	xor bx, bx
  1027                              <1> 	mov bl, al
  1028                              <1> 	mov al, byte [cs:next_states + bx]
  1029                              <1> 	pop bx
  1030                              <1> %elif 4 == _XLATBSEQ	; 12
  1031                              <1> 	push bx
  1032                              <1> 	mov bl, byte [bx + state.st]
  1033                              <1> 	mov bh, 0
  1034                              <1> 	mov al, byte [cs:next_states + bx]
  1035                              <1> 	pop bx
  1036                              <1> %elif 5 == _XLATBSEQ	; 10
  1037                              <1> 	push bx
  1038                              <1> 	mov bl, byte [bx + state.st]
  1039                              <1> 	; mov bh, 0
  1040                              <1> 		; ! because the pointer stored in ?localvariables
  1041                              <1> 		;    is normalised bh is already zero here.
  1042                              <1> 	mov al, byte [cs:next_states + bx]
  1043                              <1> 	pop bx
  1044                              <1> %elif 6 == _XLATBSEQ	; 12
  1045                              <1> 	xor ax, ax
  1046                              <1> 	mov al, byte [bx + state.st]
  1047                              <1> 	xchg ax, bx
  1048                              <1> 	mov bl, byte [cs:next_states + bx]
  1049                              <1> 	xchg ax, bx
  1050                              <1> %elif 7 == _XLATBSEQ	; 16, but minus 13 for table
  1051 000000A0 8A4728              <1> 	mov al, byte [bx + state.st]
  1052 000000A3 2C03                <1> 	sub al, 3		; below 4 ?
  1053 000000A5 7607                <1> 	jbe .zero		; yes -->
  1054 000000A7 3C07                <1> 	cmp al, 10 - 3		; 10 or 11 initially ?
  1055 000000A9 7202                <1> 	jb .have		; no -->
  1056 000000AB 2C03                <1> 	sub al, 3		; convert
  1057                              <1> .have:
  1058 000000AD A9                  <1> 	db __TEST_IMM16		; (skip mov)
  1059                              <1> .zero:
  1060 000000AE B000                <1> 	mov al, 0
  1061                              <1> %else
  1062                              <1>  %error Invalid xlatb sequence specified
  1063                              <1> %endif
  1064                              <1> %if _WARNXLATBSEQ
  1065                              <1> %assign SIZE $ - .xlatbseq
  1066                              <1> %warning xlatb sequence takes SIZE bytes plus XLATBTABSIZE table
  1067                              <1> %endif
  1068                              <1> .end:
  1069 000000B0 884728              <1> 	mov byte [bx + state.st], al
  1070 000000B3 C3                  <1> 	retn
  1071                              <1> 
  1072                              <1> 
  1073                              <1> 		; INP:	ds:bx -> localvariables
  1074                              <1> 		;	byte [bx + state.st]
  1075                              <1> 		;	al = value to use if is_char() == true
  1076                              <1> 		;	ah = value to use else
  1077                              <1> 		; OUT:	byte [bx + state.st] = al = value to use
  1078                              <1> 		; CHG:	al
  1079                              <1> .select:
  1080 000000B4 E8E4FF              <1> 	call .is_char
  1081 000000B7 72F7                <1> 	jc .end
  1082 000000B9 88E0                <1> 	mov al, ah
  1083 000000BB EBF3                <1> 	jmp .end
  1084                              <1> 
  1085                              <1> 
  1086                              <1>   min_dictionary_size:		equ 1 << 12
  1087                              <1>   max_dictionary_size:		equ 1 << 29
  1088                              <1>   literal_context_bits:		equ 3
  1089                              <1>   literal_pos_state_bits:	equ 0		; not used
  1090                              <1>   pos_state_bits:		equ 2
  1091                              <1>   pos_states:			equ 1 << pos_state_bits
  1092                              <1>   pos_state_mask:		equ pos_states - 1
  1093                              <1> 
  1094                              <1>   len_states:			equ 4
  1095                              <1>   dis_slot_bits:		equ 6
  1096                              <1>   start_dis_model:		equ 4
  1097                              <1>   end_dis_model:		equ 14
  1098                              <1>   modeled_distances:		equ 1 << ( end_dis_model / 2 )		; 128
  1099                              <1>   dis_align_bits:		equ 4
  1100                              <1>   dis_align_size:		equ 1 << dis_align_bits
  1101                              <1> 
  1102                              <1>   len_low_bits:			equ 3
  1103                              <1>   len_mid_bits:			equ 3
  1104                              <1>   len_high_bits:		equ 8
  1105                              <1>   len_low_symbols:		equ 1 << len_low_bits
  1106                              <1>   len_mid_symbols:		equ 1 << len_mid_bits
  1107                              <1>   len_high_symbols:		equ 1 << len_high_bits
  1108                              <1>   max_len_symbols:		equ len_low_symbols + len_mid_symbols + len_high_symbols
  1109                              <1> 
  1110                              <1>   min_match_len:		equ 2		; must be 2
  1111                              <1> 
  1112                              <1>   bit_model_move_bits:		equ 5
  1113                              <1>   bit_model_total_bits:		equ 11
  1114                              <1>   bit_model_total:		equ 1 << bit_model_total_bits
  1115                              <1> 
  1116                              <1> 
  1117                              <1> 	struc bit_model
  1118 00000000 ????                <1> .probability:	resw 1		; initialise to bit_model_total / 2
  1119                              <1> 				; at most bit_model_total (800h)
  1120                              <1> 	endstruc
  1121                              <1> 
  1122                              <1> 	struc len_model
  1123 00000000 ????                <1> .choice1:	resb bit_model_size
  1124 00000002 ????                <1> .choice2:	resb bit_model_size
  1125 00000004 <res 40h>           <1> .bm_low:	resb bit_model_size * pos_states * len_low_symbols
  1126 00000044 <res 40h>           <1> .bm_mid:	resb bit_model_size * pos_states * len_mid_symbols
  1127 00000084 <res 200h>          <1> .bm_high:	resb bit_model_size * len_high_symbols
  1128                              <1> 	endstruc
  1129                              <1> 
  1130                              <1> 	struc lzip_header
  1131 00000000 ????????            <1> .magic:			resd 1
  1132 00000004 ??                  <1> .version:		resb 1
  1133 00000005 ??                  <1> .coded_dict_size:	resb 1
  1134                              <1> 	endstruc
  1135                              <1> 
  1136                              <1> 	struc lzip_trailer
  1137 00000000 ????????            <1> .uncompressed_checksum:	resd 1
  1138 00000004 ????????????????    <1> .uncompressed_size:	resq 1
  1139 0000000C ????????????????    <1> .member_size:		resq 1
  1140                              <1> 	endstruc
  1141                              <1> 
  1142                              <1> 	struc range_decoder
  1143 00000000 ????????            <1> .member_pos:		resd 1
  1144 00000004 ????????            <1> .code:			resd 1
  1145 00000008 ????????            <1> .range:			resd 1
  1146                              <1> 	endstruc
  1147                              <1> 
  1148                              <1> 		; INP:	ds:bx -> range_decoder structure
  1149                              <1> 		;	ss:bp -> depack stack frame
  1150                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1151                              <1> 		; CHG:	es, di, ax, cx
  1152                              <1> Range_decoder.init:
  1153 000000BD 1E                  <1> 	push ds
  1154 000000BE 07                  <1> 	pop es
  1155 000000BF B80600              <1> 	mov ax, 6
  1156 000000C2 89DF                <1> 	mov di, bx		; -> .member_pos
  1157 000000C4 AB                  <1> 	stosw			; low word of .member_pos
  1158 000000C5 31C0                <1> 	xor ax, ax
  1159 000000C7 AB                  <1> 	stosw			; high word of .member_pos
  1160 000000C8 AB                  <1> 	stosw
  1161 000000C9 AB                  <1> 	stosw			; .code
  1162 000000CA 48                  <1> 	dec ax
  1163 000000CB AB                  <1> 	stosw
  1164 000000CC AB                  <1> 	stosw			; .range
  1165 000000CD B90500              <1> 	mov cx, 5
  1166                              <1> .loop:
  1167 000000D0 E81900              <1> 	call getbyteshiftcode
  1168 000000D3 E2FB                <1> 	loop .loop
  1169 000000D5 C3                  <1> 	retn
  1170                              <1> 
  1171                              <1> 
  1172                              <1> 		; INP:	ds:bx -> range_decoder structure
  1173                              <1> 		;	ss:bp -> depack stack frame
  1174                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1175                              <1> 		; CHG:	-
  1176                              <1> normaliserange:
  1177 000000D6 807F0B00            <1> 	cmp byte [bx + range_decoder.range + 3], 0
  1178 000000DA 7521                <1> 	jnz @F			; (retn)
  1179 000000DC 50                  <1> 	push ax
  1180 000000DD 8B4709              <1> 	mov ax, word [bx + range_decoder.range + 1]
  1181 000000E0 89470A              <1> 	mov word [bx + range_decoder.range + 2], ax
  1182 000000E3 8A6708              <1> 	mov ah, byte [bx + range_decoder.range]
  1183 000000E6 B000                <1> 	mov al, 0
  1184 000000E8 894708              <1> 	mov word [bx + range_decoder.range], ax
  1185 000000EB 58                  <1> 	pop ax
  1186                              <1> 		; fall through
  1187                              <1> 
  1188                              <1> 
  1189                              <1> 		; INP:	ds:bx -> range_decoder structure
  1190                              <1> 		;	ss:bp -> depack stack frame
  1191                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1192                              <1> 		; CHG:	-
  1193                              <1> getbyteshiftcode:
  1194 000000EC 50                  <1> 	push ax
  1195 000000ED 8B4705              <1> 	mov ax, word [bx + range_decoder.code + 1]
  1196 000000F0 894706              <1> 	mov word [bx + range_decoder.code + 2], ax
  1197 000000F3 8A6704              <1> 	mov ah, byte [bx + range_decoder.code]
  1198 000000F6 E88606              <1> 	call Range_decoder.get_byte
  1199 000000F9 894704              <1> 	mov word [bx + range_decoder.code], ax
  1200 000000FC 58                  <1> 	pop ax
  1201                              <1> @@:
  1202 000000FD C3                  <1> 	retn
  1203                              <1> 
  1204                              <1> 
  1205                              <1> 		; INP:	ds:bx -> range_decoder structure
  1206                              <1> 		;	cx = num_bits
  1207                              <1> 		;	ss:bp -> depack stack frame
  1208                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1209                              <1> 		;	If success,
  1210                              <1> 		;	 dx:ax = symbol
  1211                              <1> 		; CHG:	di, cx
  1212                              <1> Range_decoder.decode:
  1213 000000FE 31D2                <1> 	xor dx, dx
  1214 00000100 31C0                <1> 	xor ax, ax
  1215 00000102 E32C                <1> 	jcxz .end
  1216                              <1> .loop:
  1217 00000104 D16F0A              <1> 	shr word [bx + range_decoder.range + 2], 1
  1218 00000107 D15F08              <1> 	rcr word [bx + range_decoder.range], 1
  1219 0000010A D1E0                <1> 	shl ax, 1
  1220 0000010C D1D2                <1> 	rcl dx, 1
  1221 0000010E 8B7F06              <1> 	mov di, word [bx + range_decoder.code + 2]
  1222 00000111 3B7F0A              <1> 	cmp di, word [bx + range_decoder.range + 2]
  1223 00000114 7506                <1> 	jne @F
  1224 00000116 8B7F04              <1> 	mov di, word [bx + range_decoder.code]
  1225 00000119 3B7F08              <1> 	cmp di, word [bx + range_decoder.range]
  1226                              <1> @@:				; code >= range ?
  1227 0000011C 720D                <1> 	jnae @F			; no, skip -->
  1228 0000011E 8B7F08              <1> 	mov di, word [bx + range_decoder.range]
  1229 00000121 297F04              <1> 	sub word [bx + range_decoder.code], di
  1230 00000124 8B7F0A              <1> 	mov di, word [bx + range_decoder.range + 2]
  1231 00000127 197F06              <1> 	sbb word [bx + range_decoder.code + 2], di
  1232 0000012A 40                  <1> 	inc ax			; symbol |= 1 (lowest bit always was zero)
  1233                              <1> @@:
  1234 0000012B E8A8FF              <1> 	call normaliserange
  1235 0000012E E2D4                <1> 	loop .loop
  1236                              <1> .end:
  1237 00000130 C3                  <1> 	retn
  1238                              <1> 
  1239                              <1> 
  1240                              <1> 		; INP:	ds:bx -> range_decoder structure
  1241                              <1> 		;	es:di -> bit_model structure
  1242                              <1> 		;	ss:bp -> depack stack frame
  1243                              <1> 		; OUT:	al = read bit
  1244                              <1> 		;	NC if zero read
  1245                              <1> 		;	CY if one read
  1246                              <1> 		;	! If an error occurs, jumps to depack.error
  1247                              <1> 		; CHG:	cx, dx, ax
  1248                              <1> Range_decoder.decode_bit:
  1249 00000131 8B570A              <1> 	mov dx, word [bx + range_decoder.range + 2]
  1250 00000134 8B4708              <1> 	mov ax, word [bx + range_decoder.range]
  1251 00000137 B90B00              <1> 	mov cx, bit_model_total_bits
  1252                              <1> @@:
  1253 0000013A D1EA                <1> 	shr dx, 1
  1254 0000013C D1D8                <1> 	rcr ax, 1
  1255 0000013E E2FA                <1> 	loop @B
  1256                              <1> 
  1257 00000140 89D1                <1> 	mov cx, dx
  1258 00000142 26F725              <1> 	mul word [es:di + bit_model.probability]
  1259                              <1> 				; dx:ax = low word + first high word
  1260 00000145 52                  <1> 	 push dx
  1261 00000146 50                  <1> 	 push ax		; on stack = low word + first high word
  1262 00000147 91                  <1> 	xchg ax, cx
  1263 00000148 26F725              <1> 	mul word [es:di + bit_model.probability]
  1264                              <1> 				; ax = second high word (dx overflow)
  1265 0000014B 91                  <1> 	xchg ax, cx		; cx
  1266 0000014C 58                  <1> 	 pop ax
  1267 0000014D 5A                  <1> 	 pop dx
  1268 0000014E 01CA                <1> 	add dx, cx		; = full uint32_t result
  1269 00000150 B90500              <1> 	mov cx, bit_model_move_bits
  1270                              <1> 
  1271 00000153 395706              <1> 	cmp word [bx + range_decoder.code + 2], dx
  1272 00000156 7503                <1> 	jne @F
  1273 00000158 394704              <1> 	cmp word [bx + range_decoder.code], ax
  1274                              <1> @@:
  1275 0000015B 7317                <1> 	jnb .not_code_below_bound
  1276                              <1> 
  1277                              <1> .code_below_bound:
  1278 0000015D 894708              <1> 	mov word [bx + range_decoder.range], ax
  1279 00000160 89570A              <1> 	mov word [bx + range_decoder.range + 2], dx
  1280 00000163 B80008              <1> 	mov ax, bit_model_total
  1281 00000166 262B05              <1> 	sub ax, word [es:di + bit_model.probability]
  1282 00000169 7228                <1> 	jc .error
  1283 0000016B D3E8                <1> 	shr ax, cl
  1284 0000016D 260105              <1> 	add word [es:di + bit_model.probability], ax
  1285 00000170 B000                <1> 	mov al, 0
  1286 00000172 EB18                <1> 	jmp .after_if
  1287                              <1> 
  1288                              <1> .not_code_below_bound:
  1289 00000174 294708              <1> 	sub word [bx + range_decoder.range], ax
  1290 00000177 19570A              <1> 	sbb word [bx + range_decoder.range + 2], dx
  1291 0000017A 294704              <1> 	sub word [bx + range_decoder.code], ax
  1292 0000017D 195706              <1> 	sbb word [bx + range_decoder.code + 2], dx
  1293                              <1> 
  1294 00000180 268B05              <1> 	mov ax, word [es:di + bit_model.probability]
  1295 00000183 D3E8                <1> 	shr ax, cl
  1296 00000185 262905              <1> 	sub word [es:di + bit_model.probability], ax
  1297 00000188 7209                <1> 	jc .error
  1298 0000018A B001                <1> 	mov al, 1
  1299                              <1> 
  1300                              <1> .after_if:
  1301 0000018C E847FF              <1> 	call normaliserange
  1302 0000018F 3C01                <1> 	cmp al, 1		; CY if 0, NC if 1
  1303 00000191 F5                  <1> 	cmc			; NC if 0, CY if 1
  1304 00000192 C3                  <1> 	retn
  1305                              <1> 
  1306                              <1> .error:
  1307 00000193 E9E405              <1> 	jmp depack.error
  1308                              <1> 
  1309                              <1> 
  1310                              <1> 		; INP:	ds:bx -> range_decoder structure
  1311                              <1> 		;	es:di -> bit_model structure array
  1312                              <1> 		;	cx = num_bits, <= 15
  1313                              <1> 		;	ss:bp -> depack stack frame
  1314                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1315                              <1> 		;	If success,
  1316                              <1> 		;	 dx:ax = ax = symbol
  1317                              <1> 		; CHG:	cx, si
  1318                              <1> Range_decoder.decode_tree:
  1319 00000196 BE0100              <1> 	mov si, 1		; symbol = 1
  1320 00000199 83F90F              <1> 	cmp cx, 15
  1321 0000019C 7721                <1> 	ja .error
  1322 0000019E 51                  <1> 	push cx
  1323 0000019F E312                <1> 	jcxz .end
  1324                              <1> .loop:
  1325 000001A1 57                  <1> 	push di
  1326                              <1> 		; Here si (symbol) is at most 1 << 14.
  1327                              <1> %if bit_model_size != 2
  1328                              <1>  %error Assuming word size for bit_model_size
  1329                              <1> %endif
  1330 000001A2 D1E6                <1> 	shl si, 1		; Note that this shift is both used instead of
  1331                              <1> 				;  multiplying symbol (si) by bit_model_size
  1332                              <1> 				;  and to actually shift symbol (si) left!
  1333 000001A4 01F7                <1> 	add di, si		; index into bit_model array
  1334 000001A6 7217                <1> 	jc .error_pop_2
  1335 000001A8 51                  <1> 	push cx
  1336 000001A9 E885FF              <1> 	call Range_decoder.decode_bit
  1337 000001AC 59                  <1> 	pop cx
  1338 000001AD 83D600              <1> 	adc si, 0		; add in the decoded bit
  1339 000001B0 5F                  <1> 	pop di
  1340 000001B1 E2EE                <1> 	loop .loop
  1341                              <1> .end:
  1342 000001B3 59                  <1> 	pop cx
  1343 000001B4 B80100              <1> 	mov ax, 1
  1344 000001B7 D3E0                <1> 	shl ax, cl		; = 1 << num_bits
  1345 000001B9 29C6                <1> 	sub si, ax		; symbol - ( 1 << num_bits )
  1346 000001BB 96                  <1> 	xchg ax, si
  1347 000001BC 31D2                <1> 	xor dx, dx		; return symbol
  1348 000001BE C3                  <1> 	retn
  1349                              <1> 
  1350                              <1> .error_pop_2:
  1351                              <1> .error:
  1352 000001BF E9B805              <1> 	jmp depack.error
  1353                              <1> 
  1354                              <1> 
  1355                              <1> 		; INP:	ds:bx -> range_decoder structure
  1356                              <1> 		;	es:di -> bit_model structure array
  1357                              <1> 		;	cx = num_bits, <= 15
  1358                              <1> 		;	ss:bp -> depack stack frame
  1359                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1360                              <1> 		;	If success,
  1361                              <1> 		;	 dx:ax = ax = reversed_symbol
  1362                              <1> 		; CHG:	cx, si
  1363                              <1> Range_decoder.decode_tree_reversed:
  1364 000001C2 51                  <1> 	push cx
  1365 000001C3 E8D0FF              <1> 	call Range_decoder.decode_tree
  1366 000001C6 59                  <1> 	pop cx
  1367 000001C7 92                  <1> 	xchg dx, ax		; dx = symbol
  1368 000001C8 31C0                <1> 	xor ax, ax		; = reversed_symbol
  1369 000001CA E306                <1> 	jcxz .end
  1370                              <1> .loop:
  1371 000001CC D1EA                <1> 	shr dx, 1
  1372 000001CE D1D0                <1> 	rcl ax, 1
  1373 000001D0 E2FA                <1> 	loop .loop
  1374                              <1> .end:
  1375 000001D2 31D2                <1> 	xor dx, dx
  1376 000001D4 C3                  <1> 	retn
  1377                              <1> 
  1378                              <1> 
  1379                              <1> 		; INP:	ds:bx -> range_decoder structure
  1380                              <1> 		;	es:di -> bit_model structure array
  1381                              <1> 		;	al = match_byte
  1382                              <1> 		;	ss:bp -> depack stack frame
  1383                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1384                              <1> 		;	If success,
  1385                              <1> 		;	 al = return value (symbol & 0FFh)
  1386                              <1> 		; CHG:	cx, dx, ax
  1387                              <1> Range_decoder.decode_matched:
  1388 000001D5 88C6                <1> 	mov dh, al		; = match_byte
  1389                              <1> 
  1390 000001D7 B80100              <1> 	mov ax, 1		; initialise symbol = 1
  1391                              <1> 
  1392 000001DA B90800              <1> 	mov cx, 8
  1393                              <1> .loop:
  1394 000001DD 52                  <1> 	push dx			; preserve dh = match_byte
  1395 000001DE 51                  <1> 	push cx			; preserve loop counter
  1396 000001DF 49                  <1> 	dec cx
  1397 000001E0 D2EE                <1> 	shr dh, cl		; match_byte >> i
  1398 000001E2 81E20001            <1> 	and dx, 100h		; dh &= 1 = match_bit, dl = 0
  1399 000001E6 52                  <1> 	push dx
  1400 000001E7 FEC6                <1> 	inc dh			; = (match_bit << 8) + 100h
  1401 000001E9 01C2                <1> 	add dx, ax		; = symbol + (match_bit << 8) + 100h
  1402                              <1> 		; As symbol is below 256, this is at most 255 + 100h + 100h,
  1403                              <1> 		;  which is 2FFh. As such, the bm_literal array's
  1404                              <1> 		;  entries are arrays of 300h bit_model each.
  1405 000001EB 57                  <1> 	push di
  1406 000001EC 50                  <1> 	push ax
  1407                              <1> %if bit_model_size != 2
  1408                              <1>  %error Assuming word size for bit_model_size
  1409                              <1> %endif
  1410 000001ED 01D2                <1> 	add dx, dx
  1411                              <1> 		; As dx was < 300h before this addition, it cannot carry.
  1412 000001EF 01D7                <1> 	add di, dx
  1413                              <1> 		; We assume that this does not carry.
  1414 000001F1 E83DFF              <1> 	call Range_decoder.decode_bit
  1415 000001F4 91                  <1> 	xchg ax, cx		; cl = result (1 or 0)
  1416 000001F5 58                  <1> 	pop ax			; = symbol
  1417 000001F6 5F                  <1> 	pop di
  1418 000001F7 5A                  <1> 	pop dx			; = match_bit << 8
  1419 000001F8 D1D0                <1> 	rcl ax, 1		; shift symbol, OR in the bit
  1420                              <1> 		; As the loop counter is initialised to 8,
  1421                              <1> 		;  the symbol variable stays below 256.
  1422 000001FA 38F1                <1> 	cmp cl, dh		; if( match_bit != bit ) ...-
  1423 000001FC 59                  <1> 	pop cx			; = loop counter
  1424 000001FD 5A                  <1> 	pop dx			; = dh = match_byte
  1425 000001FE 7519                <1> 	jne .inner_next		; -... do the following -->
  1426                              <1> .next:
  1427 00000200 E2DB                <1> 	loop .loop
  1428                              <1> .end:
  1429 00000202 30E4                <1> 	xor ah, ah		; return ax = symbol & 0FFh
  1430 00000204 C3                  <1> 	retn
  1431                              <1> 
  1432                              <1> .error_pop_2:
  1433                              <1> .error:
  1434 00000205 E97205              <1> 	jmp depack.error
  1435                              <1> 
  1436                              <1> 
  1437                              <1> .inner_loop:
  1438 00000208 50                  <1> 	push ax
  1439                              <1> %if bit_model_size != 2
  1440                              <1>  %error Assuming word size for bit_model_size
  1441                              <1> %endif
  1442 00000209 01C0                <1> 	add ax, ax
  1443 0000020B 57                  <1> 	push di
  1444 0000020C 01C7                <1> 	add di, ax
  1445 0000020E 72F5                <1> 	jc .error_pop_2
  1446 00000210 E81EFF              <1> 	call Range_decoder.decode_bit
  1447 00000213 5F                  <1> 	pop di
  1448 00000214 58                  <1> 	pop ax
  1449 00000215 D1D0                <1> 	rcl ax, 1
  1450 00000217 72EC                <1> 	jc .error
  1451                              <1> 
  1452                              <1> .inner_next:
  1453 00000219 3D0001              <1> 	cmp ax, 100h
  1454 0000021C 72EA                <1> 	jb .inner_loop
  1455 0000021E EBE2                <1> 	jmp .end
  1456                              <1> 
  1457                              <1> 
  1458                              <1> 		; INP:	ds:bx -> range_decoder structure
  1459                              <1> 		;	es:di -> len_model structure
  1460                              <1> 		;	ax = pos_state
  1461                              <1> 		;	ss:bp -> depack stack frame
  1462                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1463                              <1> 		;	If success,
  1464                              <1> 		;	 dx:ax = return
  1465                              <1> 		; CHG:	cx, si
  1466                              <1> Range_decoder.decode_len:
  1467 00000220 89C6                <1> 	mov si, ax		; = pos_state
  1468 00000222 57                  <1> 	 push di		; = len_model_struc (on stack)
  1469                              <1> 
  1470 00000223 8D3D                <1> 	lea di, [di + len_model.choice1]
  1471 00000225 E809FF              <1> 	call Range_decoder.decode_bit
  1472 00000228 5F                  <1> 	 pop di			; reset to ?len_model_struc
  1473 00000229 57                  <1> 	 push di
  1474 0000022A 7218                <1> 	jc .not_decode_bit_choice1_equals_zero
  1475                              <1> 
  1476 0000022C 8D7D04              <1> 	lea di, [di + len_model.bm_low]
  1477 0000022F B81000              <1> 	mov ax, len_low_symbols * bit_model_size
  1478 00000232 F7E6                <1> 	mul si
  1479 00000234 85D2                <1> 	test dx, dx
  1480 00000236 7546                <1> 	jnz .error
  1481 00000238 01C7                <1> 	add di, ax
  1482 0000023A 7242                <1> 	jc .error
  1483 0000023C B90300              <1> 	mov cx, len_low_bits
  1484 0000023F E854FF              <1> 	call Range_decoder.decode_tree
  1485 00000242 EB38                <1> 	jmp .ret
  1486                              <1> 
  1487                              <1> .not_decode_bit_choice1_equals_zero:
  1488 00000244 8D7D02              <1> 	lea di, [di + len_model.choice2]
  1489 00000247 E8E7FE              <1> 	call Range_decoder.decode_bit
  1490 0000024A 5F                  <1> 	 pop di			; reset to ?len_model_struc
  1491 0000024B 57                  <1> 	 push di
  1492 0000024C 721E                <1> 	jc .not_decode_bit_choice2_equals_zero
  1493                              <1> 
  1494 0000024E 8D7D44              <1> 	lea di, [di + len_model.bm_mid]
  1495 00000251 B81000              <1> 	mov ax, len_mid_symbols * bit_model_size
  1496 00000254 F7E6                <1> 	mul si
  1497 00000256 85D2                <1> 	test dx, dx
  1498 00000258 7524                <1> 	jnz .error
  1499 0000025A 01C7                <1> 	add di, ax
  1500 0000025C 7220                <1> 	jc .error
  1501 0000025E B90300              <1> 	mov cx, len_mid_bits
  1502 00000261 E832FF              <1> 	call Range_decoder.decode_tree
  1503 00000264 83C008              <1> 	add ax, len_low_symbols & 0FFFFh
  1504 00000267 83D200              <1> 	adc dx, len_low_symbols >> 16
  1505 0000026A EB10                <1> 	jmp .ret
  1506                              <1> 
  1507                              <1> .not_decode_bit_choice2_equals_zero:
  1508 0000026C 8DBD8400            <1> 	lea di, [di + len_model.bm_high]
  1509 00000270 B90800              <1> 	mov cx, len_high_bits
  1510 00000273 E820FF              <1> 	call Range_decoder.decode_tree
  1511 00000276 83C010              <1> 	add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh
  1512 00000279 83D200              <1> 	adc dx, (len_low_symbols + len_mid_symbols) >> 16
  1513                              <1> .ret:
  1514 0000027C 5F                  <1> 	 pop di
  1515 0000027D C3                  <1> 	retn
  1516                              <1> 
  1517                              <1> .error:
  1518 0000027E E9F904              <1> 	jmp depack.error
  1519                              <1> 
  1520                              <1> 
  1521                              <1> 	struc lz_decoder
  1522 00000000 <res Ch>            <1> .range_decoder:		resb range_decoder_size
  1523 0000000C ????????            <1> 			alignb 8
  1524 00000010 ????????            <1> .dictionary_size:	resd 1
  1525 00000014 ????????            <1> .pos:			resd 1
  1526                              <1> 	endstruc
  1527                              <1> 
  1528                              <1> 
  1529                              <1> 		; INP:	ds:bx -> lz_decoder structure, localvariables structure
  1530                              <1> 		;	dx:ax = distance
  1531                              <1> 		; OUT:	al = ax = byte from buffer
  1532                              <1> 		; CHG:	dx, cx, di, si, es
  1533                              <1> LZ_decoder.peek:
  1534 00000281 395716              <1> 	cmp word [bx + lz_decoder.pos + 2], dx
  1535 00000284 7503                <1> 	jne @F
  1536 00000286 394714              <1> 	cmp word [bx + lz_decoder.pos], ax
  1537                              <1> @@:
  1538 00000289 760A                <1> 	jna .not_pos_above_distance
  1539                              <1> 
  1540 0000028B E80A00              <1> 	call calculate_peek_pointer_disi
  1541                              <1> 
  1542 0000028E 8EC7                <1> 	mov es, di			; es:si -> peek address
  1543 00000290 31C0                <1> 	xor ax, ax
  1544 00000292 26AC                <1> 	es lodsb
  1545 00000294 C3                  <1> 	retn
  1546                              <1> 
  1547                              <1> .not_pos_above_distance:
  1548 00000295 31C0                <1> 	xor ax, ax
  1549 00000297 C3                  <1> 	retn
  1550                              <1> 
  1551                              <1> 
  1552                              <1> 		; INP:	dx:ax = peek distance
  1553                              <1> 		;	ds:bx -> local variables
  1554                              <1> 		; OUT:	di:si -> peek address
  1555                              <1> 		; CHG:	cx, dx, ax
  1556                              <1> calculate_peek_pointer_disi:
  1557 00000298 53                  <1> 	push bx
  1558 00000299 FF772E              <1> 	 push word [bx + destinationbuffer_constant + 2]
  1559 0000029C FF772C              <1> 	 push word [bx + destinationbuffer_constant]
  1560                              <1> 
  1561 0000029F F7DA                <1> 	neg dx
  1562 000002A1 F7D8                <1> 	neg ax
  1563 000002A3 83DA00              <1> 	sbb dx, byte 0			; neg dx:ax = - distance
  1564 000002A6 83E801              <1> 	sub ax, 1
  1565 000002A9 83DA00              <1> 	sbb dx, 0			; - 1
  1566 000002AC 034714              <1> 	add ax, word [bx + lz_decoder.pos]
  1567 000002AF 135716              <1> 	adc dx, word [bx + lz_decoder.pos + 2]
  1568                              <1> 					; + pos
  1569 000002B2 91                  <1> 	xchg cx, ax
  1570 000002B3 87DA                <1> 	xchg bx, dx
  1571                              <1> 
  1572 000002B5 E86A06              <1> 	call normalise_pointer_with_displacement_bxcx
  1573 000002B8 5E                  <1> 	 pop si
  1574 000002B9 5F                  <1> 	 pop di				; di:si -> source
  1575 000002BA 5B                  <1> 	pop bx
  1576 000002BB C3                  <1> 	retn
  1577                              <1> 
  1578                              <1> 
  1579                              <1> 		; INP:	ss:bp -> depack stack frame
  1580                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1581                              <1> 		;	If success,
  1582                              <1> 		;	 al = byte
  1583                              <1> 		; CHG:	-
  1584                              <1> LZ_decoder.get_byte: equ Range_decoder.get_byte
  1585                              <1> 
  1586                              <1> 
  1587                              <1> 	struc localvariables
  1588                              <1> lz_decoder_struc:
  1589 00000000 <res 18h>           <1> 		resb lz_decoder_size
  1590                              <1> 		alignb 4
  1591                              <1> zeros_start:
  1592 00000018 ????????            <1> rep0:		resd 1
  1593 0000001C ????????            <1> rep1:		resd 1
  1594 00000020 ????????            <1> rep2:		resd 1
  1595 00000024 ????????            <1> rep3:		resd 1
  1596 00000028 ????                <1> state.st:	resw 1		; initialise to zero
  1597 0000002A ????                <1> 		alignb 4
  1598                              <1> zeros_end:
  1599 0000002C ????????            <1> destinationbuffer_constant:	resd 1		; stays constant
  1600                              <1> 		alignb 16
  1601                              <1> bit_models_start:
  1602 00000030 <res 60h>           <1> bm_match:	resb bit_model_size * amount_states * pos_states
  1603 00000090 <res 18h>           <1> bm_rep:		resb bit_model_size * amount_states
  1604 000000A8 <res 18h>           <1> bm_rep0:	resb bit_model_size * amount_states
  1605 000000C0 <res 18h>           <1> bm_rep1:	resb bit_model_size * amount_states
  1606 000000D8 <res 18h>           <1> bm_rep2:	resb bit_model_size * amount_states
  1607 000000F0 <res 3000h>         <1> bm_literal:	resb bit_model_size * (1 << literal_context_bits) * 300h
  1608 000030F0 <res 60h>           <1> bm_len:		resb bit_model_size * amount_states * pos_states
  1609 00003150 <res 200h>          <1> bm_dis_slot:	resb bit_model_size * len_states * (1 << dis_slot_bits)
  1610 00003350 <res E6h>           <1> bm_dis:		resb bit_model_size * (modeled_distances - end_dis_model + 1)
  1611 00003436 <res 20h>           <1> bm_align:	resb bit_model_size * dis_align_size
  1612 00003456 <res 284h>          <1> match_len_model:resb len_model_size
  1613 000036DA <res 284h>          <1> rep_len_model:	resb len_model_size
  1614                              <1> bit_models_end:
  1615 0000395E ????                <1> 		alignb 16
  1616                              <1> 	endstruc
  1617                              <1> %if lz_decoder_struc != 0
  1618                              <1>  %error Expecting lz_decoder structure at start of localvariables structure
  1619                              <1> %endif
  1620                              <1> %assign STRUCSIZE localvariables_size
  1621                              <1> %warning localvariables has STRUCSIZE bytes
  1621          ******************  <1>  warning: localvariables has 14688 bytes [-w+user]
  1622                              <1> 
  1623                              <1> 
  1624                              <1> 	align 4
  1625                              <1> lzip_header_bytes:
  1626                              <1> .:
  1627 000002BC 4C5A495001          <1> 	db "LZIP",1
  1628                              <1> .length: equ $ - .
  1629                              <1> 
  1630                              <1> 
  1631                              <1> 		; INP:	ds:si -> source
  1632                              <1> 		;	dx:cx = length of source
  1633                              <1> 		;	es:di -> destination (below source)
  1634                              <1> 		;	if _IMAGE_EXE:
  1635                              <1> 		;	 bx = EXE mode flag (bit 0)
  1636                              <1> 		;	else:
  1637                              <1> 		;	 bx = 0
  1638                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
  1639                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
  1640                              <1> 		;	 (-1 if full source should be decompressed)
  1641                              <1> 		;	else:
  1642                              <1> 		;	 ax = -1
  1643                              <1> 		; OUT:	NC if success
  1644                              <1> 		;	CY if error,
  1645                              <1> 		;	 bx = ?errordata (if _DEBUG0)
  1646                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
  1647                              <1> 		; STT:	UP
  1648                              <1> 		;
  1649                              <1> 		; Note:	The destination reaches up to below the source.
  1650                              <1> 		; Note:	The input pointers need not be normalised yet.
  1651                              <1> 		;	 Normalised means that the offset part is below 16.
  1652                              <1> depack:
  1653                              <1> 	lframe near
  1654                              <1> %if _IMAGE_EXE || _COUNTER || _DEBUG0
  1655 000002C1 5589E5              <1> 	lenter early
  1656                              <1>  %if _IMAGE_EXE
  1657                              <1> 	lvar word,	exemode	; must be bp - 2!
  1658 000002C4 53                  <1> 	 push bx
  1659                              <1>   %if ?exemode != -2
  1660                              <1>    %error exemode variable must be directly below bp
  1661                              <1>   %endif
  1662                              <1>  %endif
  1663                              <1>  %if _COUNTER || _DEBUG0
  1664                              <1> 	xor bx, bx
  1665                              <1>  %endif
  1666                              <1> %endif
  1667                              <1> %if _COUNTER
  1668                              <1> 	lvar word,	counter
  1669                              <1> 	 push bx		; initialise counter to zero
  1670                              <1> %endif
  1671                              <1> d0	lvar word,	errordata
  1672                              <1> d0	 push bx
  1673                              <1> 	lvar dword,	distance
  1674                              <1> 	lvar dword,	len
  1675                              <1> 	lvar dword,	dis_slot
  1676                              <1> 	lvar word,	len_state
  1677                              <1> 	lvar word,	pos_state
  1678 000002C5 8D66EE              <1> 	lenter
  1679                              <1> 
  1680 000002C8 E82C06              <1> 	call normalise_both_pointers
  1681                              <1> 
  1682                              <1> 		; ! di < 16, so dih == 0
  1683                              <1> 	lvar dword,	src
  1684 000002CB 1E                  <1> 	 push ds
  1685 000002CC 56                  <1> 	 push si
  1686                              <1> 	lvar dword,	final_dst
  1687 000002CD 06                  <1> 	 push es
  1688 000002CE 57                  <1> 	 push di
  1689                              <1> 	lequ ?final_dst,	localvariables
  1690                              <1> 		; ! offset of ?localvariables is always < 16
  1691                              <1> 		;  required for State.set_char with _XLATBSEQ == 5
  1692                              <1> 	lvar dword,	length_of_source
  1693 000002CF 52                  <1> 	 push dx
  1694 000002D0 51                  <1> 	 push cx
  1695                              <1> 
  1696                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
  1697                              <1> 	cmp ax, -1		; no maximum specified ?
  1698                              <1> 	je @FF			; retain -1 in ax -->
  1699                              <1> 	test di, di		; do we need an additional paragraph ?
  1700                              <1> 	jz @F			; no -->
  1701                              <1> 	inc ax			; es + ax => paragraph after necessary part
  1702                              <1> @@:
  1703                              <1> 	mov dx, es
  1704                              <1> 	add ax, dx		; => paragraph after necessary part
  1705                              <1> 		; If the normalised destination pointer's segment grows
  1706                              <1> 		;  to this segment then enough has been decompressed.
  1707                              <1> d0	mov byte [bp + ?errordata], 40h
  1708                              <1> 	jc .error_CY_a1		; should not carry
  1709                              <1> @@:
  1710                              <1> 	lvar word,	dst_max_segment
  1711                              <1> 	 push ax
  1712                              <1> %endif
  1713                              <1> 
  1714 000002D1 1E                  <1> 	 push ds
  1715 000002D2 56                  <1> 	 push si
  1716 000002D3 E87B06              <1> 	call pointer_to_linear
  1717                              <1> 
  1718 000002D6 87DA                <1> 	xchg bx, dx
  1719 000002D8 91                  <1> 	xchg cx, ax		; bx:cx = source linear, clobber dx:ax
  1720                              <1> 
  1721 000002D9 06                  <1> 	 push es
  1722 000002DA 57                  <1> 	 push di
  1723 000002DB E87306              <1> 	call pointer_to_linear
  1724                              <1> 
  1725                              <1> %if _ALLOW_OVERLAPPING
  1726 000002DE 034EE2              <1> 	add cx, word [bp + ?length_of_source]
  1727 000002E1 135EE4              <1> 	adc bx, word [bp + ?length_of_source + 2]
  1728                              <1> 		; In case of allowing overlapping source and destination,
  1729                              <1> 		;  the ?length_of_destination variable is set to
  1730                              <1> 		;  ?src + ?length_of_source - ?dst, allowing to write to
  1731                              <1> 		;  all of the source buffer (with the checks already in place
  1732                              <1> 		;  from the default handling). Additional checks are done by
  1733                              <1> 		;  calling check_pointers_not_overlapping. This is done after
  1734                              <1> 		;  every change of ?dst to verify that the write pointer stays
  1735                              <1> 		;  below-or-equal the read pointer.
  1736                              <1> 		; This means the remaining source data may be corrupted by a
  1737                              <1> 		;  write, but nothing after the source data is written to,
  1738                              <1> 		;  so the error handling (in INIT1 after the data) still works.
  1739                              <1> %endif
  1740                              <1> 
  1741 000002E4 29C1                <1> 	sub cx, ax
  1742 000002E6 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
  1743                              <1> 
  1744 000002E8 81E96039            <1> 	sub cx, localvariables_size & 0FFFFh
  1745 000002EC 83DB00              <1> 	sbb bx, localvariables_size >> 16
  1746 000002EF 7703E98604          <1> 	jbe .error		; make variables buffer available
  1747                              <1> 
  1748                              <1> 	lvar dword,	length_of_destination
  1749 000002F4 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
  1750 000002F5 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
  1751                              <1> 
  1752 000002F6 06                  <1> 	push es
  1753 000002F7 57                  <1> 	push di
  1754                              <1> %if localvariables_size >> 16
  1755                              <1> 	mov bx, localvariables_size >> 16
  1756                              <1> %else
  1757 000002F8 31DB                <1> 	xor bx, bx
  1758                              <1> %endif
  1759 000002FA B96039              <1> 	mov cx, localvariables_size & 0FFFFh
  1760 000002FD E82206              <1> 	call normalise_pointer_with_displacement_bxcx
  1761 00000300 5F                  <1> 	pop di
  1762 00000301 07                  <1> 	pop es
  1763                              <1> 
  1764                              <1> 	lvar dword,	original_dst
  1765 00000302 06                  <1> 	 push es
  1766 00000303 57                  <1> 	 push di
  1767                              <1> 	lvar dword,	dst
  1768 00000304 06                  <1> 	 push es
  1769 00000305 57                  <1> 	 push di
  1770                              <1> 
  1771                              <1> %if _ALLOW_OVERLAPPING
  1772 00000306 E8D005              <1> 	call check_pointers_not_overlapping
  1773                              <1> 		; Note:	We initially check here that the write pointer is
  1774                              <1> 		;	 low enough, ie below-or-equal the read pointer.
  1775                              <1> 		;	Unlike the other decompressors, this check is done
  1776                              <1> 		;	 after any copied match or literal too, because
  1777                              <1> 		;	 literals can presumably be encoded with less than
  1778                              <1> 		;	 one byte of source data to the range decoder.
  1779                              <1> d0	mov byte [bp + ?errordata], 1Bh
  1780                              <1> .error_CY_a1:
  1781 00000309 7243                <1> 	jc short .error_CY_a
  1782                              <1> %else
  1783                              <1>  .error_CY_a1 equ .error_CY_a
  1784                              <1> %endif
  1785                              <1> 
  1786                              <1> 
  1787                              <1> member_min_size equ lzip_header_size + lzip_trailer_size
  1788                              <1> 
  1789                              <1> .loop_member:
  1790 0000030B 837EE400            <1> 	cmp word [bp + ?length_of_source + 2], 0
  1791 0000030F 7504                <1> 	jne @F
  1792 00000311 837EE21A            <1> 	cmp word [bp + ?length_of_source], member_min_size
  1793                              <1> @@:
  1794 00000315 770F                <1> 	ja .got_member
  1795                              <1> 
  1796 00000317 837EE400            <1> 	cmp word [bp + ?length_of_source + 2], 0
  1797 0000031B 7504                <1> 	jne @F
  1798 0000031D 837EE20F            <1> 	cmp word [bp + ?length_of_source], 15
  1799                              <1> @@:
  1800 00000321 7710                <1> 	ja short .error_NZ_a		; (NZ if jumping)
  1801 00000323 E92004              <1> 	jmp .end
  1802                              <1> 
  1803                              <1> .got_member:
  1804 00000326 C576EA              <1> 	lds si, [bp + ?src]		; ds:si -> lzip_header.magic, .version
  1805 00000329 0E                  <1> 	push cs
  1806 0000032A 07                  <1> 	pop es
  1807 0000032B BF[BC02]            <1> 	mov di, lzip_header_bytes
  1808 0000032E B90500              <1> 	mov cx, lzip_header_bytes.length
  1809 00000331 F3A6                <1> 	repe cmpsb
  1810                              <1> .error_NZ_a:
  1811 00000333 7403E94204          <1> 	jne .error
  1812                              <1> %if _COUNTER
  1813                              <1> 	mov al, '#'
  1814                              <1> 	call disp_al
  1815                              <1> %endif
  1816 00000338 31C0                <1> 	xor ax, ax
  1817 0000033A AC                  <1> 	lodsb				; ax = lzip_header.coded_dict_size
  1818                              <1> 
  1819 0000033B 1E                  <1> 	 push ds
  1820 0000033C 56                  <1> 	 push si
  1821 0000033D E8C605              <1> 	call normalise_pointer
  1822 00000340 8F46EA              <1> 	 pop word [bp + ?src]
  1823 00000343 8F46EC              <1> 	 pop word [bp + ?src + 2]
  1824 00000346 836EE206            <1> 	sub word [bp + ?length_of_source], 6
  1825 0000034A 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1826                              <1> .error_CY_a:
  1827 0000034E 7235                <1> 	jc short .error_CY_b
  1828                              <1> 
  1829 00000350 50                  <1> 	push ax
  1830 00000351 241F                <1> 	and al, 1Fh
  1831 00000353 91                  <1> 	xchg cx, ax			; cx = coded dict size & 1Fh, clobber ax
  1832 00000354 B80100              <1> 	mov ax, 1
  1833 00000357 31D2                <1> 	xor dx, dx
  1834                              <1> @@:
  1835 00000359 D1E0                <1> 	shl ax, 1
  1836 0000035B D1D2                <1> 	rcl dx, 1
  1837 0000035D E2FA                <1> 	loop @B
  1838                              <1> 
  1839 0000035F 89D3                <1> 	mov bx, dx
  1840 00000361 89C7                <1> 	mov di, ax			; bx:di = dict_size
  1841 00000363 B104                <1> 	mov cl, 4
  1842                              <1> @@:
  1843 00000365 D1EB                <1> 	shr bx, 1
  1844 00000367 D1DF                <1> 	rcr di, 1
  1845 00000369 E2FA                <1> 	loop @B				; bx:di = dict_size / 16
  1846 0000036B 59                  <1> 	pop cx
  1847 0000036C 88CD                <1> 	mov ch, cl
  1848 0000036E B105                <1> 	mov cl, 5
  1849 00000370 D2ED                <1> 	shr ch, cl
  1850 00000372 88E9                <1> 	mov cl, ch
  1851 00000374 B500                <1> 	mov ch, 0
  1852 00000376 E331                <1> 	jcxz @FF
  1853                              <1> 
  1854 00000378 52                  <1> 	push dx
  1855 00000379 50                  <1> 	push ax
  1856                              <1> 
  1857 0000037A 89F8                <1> 	mov ax, di			; ax = low word of input
  1858 0000037C F7E1                <1> 	mul cx
  1859 0000037E 93                  <1> 	xchg ax, bx			; ax = high word of input
  1860 0000037F 89D7                <1> 	mov di, dx			; di:bx = low word + first high word
  1861 00000381 F7E1                <1> 	mul cx				; = high word
  1862 00000383 01C7                <1> 	add di, ax			; add into sum
  1863                              <1> .error_CY_b:
  1864 00000385 7217                <1> 	jc short .error_CY_c
  1865 00000387 85D2                <1> 	test dx, dx			; overflows ?
  1866 00000389 7403E9EC03          <1> 	jnz .error
  1867                              <1> 					; bx:di = dict_size / 16 * fraction
  1868 0000038E 58                  <1> 	pop ax
  1869 0000038F 5A                  <1> 	pop dx
  1870 00000390 29D8                <1> 	sub ax, bx
  1871 00000392 19FA                <1> 	sbb dx, di
  1872 00000394 7208                <1> 	jc short .error_CY_c
  1873                              <1> 
  1874 00000396 83FA00              <1> 	cmp dx, min_dictionary_size >> 16
  1875 00000399 7503                <1> 	jne @F
  1876 0000039B 3D0010              <1> 	cmp ax, min_dictionary_size & 0FFFFh
  1877                              <1> @@:
  1878                              <1> .error_CY_c:
  1879 0000039E 7265                <1> 	jb short .error_CY_d
  1880                              <1> 
  1881 000003A0 81FA0020            <1> 	cmp dx, max_dictionary_size >> 16
  1882 000003A4 7503                <1> 	jne @F
  1883 000003A6 83F800              <1> 	cmp ax, max_dictionary_size & 0FFFFh
  1884                              <1> @@:
  1885 000003A9 7603E9CC03          <1> 	ja .error
  1886                              <1> 
  1887 000003AE C55EE6              <1> 	lds bx, [bp + ?final_dst]
  1888 000003B1 FF76D8              <1> 	push word [bp + ?dst + 2]
  1889 000003B4 FF76D6              <1> 	push word [bp + ?dst]
  1890 000003B7 8F472C              <1> 	pop word [bx + destinationbuffer_constant]
  1891 000003BA 8F472E              <1> 	pop word [bx + destinationbuffer_constant + 2]
  1892                              <1> 
  1893                              <1> 
  1894                              <1> 		; decode_member start (inlined)
  1895                              <1> 		; INP:	?localvariables = ds:bx -> localvariables structure,
  1896                              <1> 		;	 destinationbuffer_constant pre-initialised
  1897                              <1> 		;	dx:ax = dictionary size
  1898                              <1> 		;	Following variables of depack frame initialised:
  1899                              <1> 		;	 dword [ss:bp + ?src] -> source buffer
  1900                              <1> 		;	 dword [ss:bp + ?length_of_source] = remaining length
  1901                              <1> 		;	 dword [ss:bp + ?dst] -> destination buffer
  1902                              <1> 		;	 dword [ss:bp + ?length_of_destination] = remaining
  1903                              <1> 		; OUT:	NC if success
  1904                              <1> 		;	CY if error
  1905                              <1> 		; CHG:	all
  1906                              <1> ; LZ_decoder.decode_member:
  1907                              <1> 
  1908 000003BD 52                  <1> 	 push dx
  1909 000003BE 50                  <1> 	 push ax			; preserve dictionary size
  1910 000003BF 1E                  <1> 	push ds
  1911 000003C0 07                  <1> 	pop es
  1912 000003C1 89DF                <1> 	mov di, bx
  1913 000003C3 B90C00              <1> 	mov cx, fromdwords(dwords(lz_decoder_size)) / 2
  1914 000003C6 31C0                <1> 	xor ax, ax
  1915 000003C8 F3AB                <1> 	rep stosw			; initialise lz_decoder structure
  1916                              <1> 
  1917 000003CA E8F0FC              <1> 	call Range_decoder.init		; initialise embedded range_decoder
  1918                              <1> 
  1919 000003CD 8F4710              <1> 	 pop word [bx + lz_decoder.dictionary_size]
  1920 000003D0 8F4712              <1> 	 pop word [bx + lz_decoder.dictionary_size + 2]
  1921                              <1> 					; set dictionary size
  1922                              <1> 
  1923 000003D3 8D7F30              <1> 	lea di, [bx + bit_models_start]
  1924 000003D6 B9971C              <1> 	mov cx, (bit_models_end - bit_models_start) / bit_model_size
  1925 000003D9 B80004              <1> 	mov ax, bit_model_total / 2	; initial value for bit_model
  1926                              <1> %if bit_model_size != 2
  1927                              <1>  %error Assuming word size for bit_model_size
  1928                              <1> %endif
  1929 000003DC F3AB                <1> 	rep stosw			; initialise this bit_model
  1930                              <1> 					; loop for all bit_model and len_model
  1931                              <1> 
  1932 000003DE 8D7F18              <1> 	lea di, [bx + zeros_start]
  1933 000003E1 31C0                <1> 	xor ax, ax
  1934 000003E3 B10A                <1> 	mov cl, (zeros_end - zeros_start) / 2
  1935 000003E5 F3AB                <1> 	rep stosw
  1936                              <1> 
  1937                              <1> .loop:
  1938                              <1> %if _COUNTER
  1939                              <1> 	inc byte [bp + ?counter]
  1940                              <1> 	test byte [bp + ?counter], _COUNTER - 1
  1941                              <1> 	jnz @F
  1942                              <1> 	mov al, '.'
  1943                              <1> 	call disp_al
  1944                              <1> @@:
  1945                              <1> %endif
  1946 000003E7 8B5EE6              <1> 	mov bx, word [bp + ?localvariables]
  1947 000003EA 8B4714              <1> 	mov ax, word [bx + lz_decoder.pos]
  1948 000003ED 83E003              <1> 	and ax, pos_state_mask
  1949 000003F0 91                  <1> 	xchg cx, ax			; cx = pos_state, ax clobbered
  1950 000003F1 894EEE              <1> 	mov word [bp + ?pos_state], cx
  1951                              <1> 
  1952 000003F4 1E                  <1> 	push ds
  1953 000003F5 07                  <1> 	pop es
  1954 000003F6 8D7F30              <1> 	lea di, [bx + bm_match]		; es:di -> bm_match 2D array
  1955 000003F9 B80800              <1> 	mov ax, bit_model_size * pos_states
  1956 000003FC F76728              <1> 	mul word [bx + state.st]	; dx:ax = first index is state
  1957                              <1> 		; bit_model_size = 2
  1958                              <1> 		; pos_states = 4
  1959                              <1> 		; state.st < 12
  1960                              <1> 		; multiplication 2 * 4 * 11 = 88
  1961                              <1> %if bit_model_size != 2
  1962                              <1>  %error Assuming word size for bit_model_size
  1963                              <1> %endif
  1964 000003FF 01C9                <1> 	add cx, cx			; = second index (from pos_state)
  1965                              <1> 		; pos_state < 4
  1966                              <1> 		; cx < 8
  1967                              <1> 		; ax <= 88
  1968 00000401 01C8                <1> 	add ax, cx			; = second index is pos_state
  1969 00000403 01C7                <1> 	add di, ax			; es:di -> bm_match[state()][pos_state]
  1970                              <1> .error_CY_d:
  1971 00000405 7222                <1> 	jc short .error_CY_1
  1972 00000407 E827FD              <1> 	call Range_decoder.decode_bit
  1973 0000040A 7244                <1> 	jc .1st_bit_not_zero
  1974                              <1> 
  1975                              <1> .1st_bit_zero:			; literal byte
  1976 0000040C 31C0                <1> 	xor ax, ax
  1977 0000040E 31D2                <1> 	xor dx, dx
  1978 00000410 E86EFE              <1> 	call LZ_decoder.peek		; al = prev_byte
  1979                              <1> 
  1980 00000413 B105                <1> 	mov cl, 8 - literal_context_bits
  1981 00000415 D2E8                <1> 	shr al, cl			; = literal_state
  1982 00000417 1E                  <1> 	push ds
  1983 00000418 07                  <1> 	pop es
  1984 00000419 8DBFF000            <1> 	lea di, [bx + bm_literal]	; -> 2D array bm_literal
  1985 0000041D B90006              <1> 	mov cx, bit_model_size * 300h
  1986 00000420 F7E1                <1> 	mul cx				; first index is literal_state
  1987 00000422 85D2                <1> 	test dx, dx
  1988 00000424 F9                  <1> 	stc
  1989 00000425 7502                <1> 	jnz short .error_CY_1
  1990 00000427 01C7                <1> 	add di, ax			; es:di -> bm_literal[literal_state]
  1991                              <1> .error_CY_1:
  1992 00000429 7232                <1> 	jc short .error_CY_2
  1993                              <1> 
  1994 0000042B E86DFC              <1> 	call State.is_char
  1995 0000042E 7308                <1> 	jnc .not_is_char
  1996                              <1> .is_char:
  1997 00000430 B90800              <1> 	mov cx, 8
  1998 00000433 E860FD              <1> 	call Range_decoder.decode_tree
  1999 00000436 EB10                <1> 	jmp @F
  2000                              <1> 
  2001                              <1> .not_is_char:
  2002 00000438 8B4718              <1> 	mov ax, word [bx + rep0]
  2003 0000043B 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  2004 0000043E 06                  <1> 	push es
  2005 0000043F 57                  <1> 	push di
  2006 00000440 E83EFE              <1> 	call LZ_decoder.peek
  2007 00000443 5F                  <1> 	pop di
  2008 00000444 07                  <1> 	pop es
  2009 00000445 E88DFD              <1> 	call Range_decoder.decode_matched
  2010                              <1> @@:
  2011 00000448 E85B03              <1> 	call LZ_decoder.put_byte
  2012 0000044B E852FC              <1> 	call State.set_char
  2013 0000044E EB97                <1> 	jmp .loop
  2014                              <1> 
  2015                              <1> 
  2016                              <1> .1st_bit_not_zero:		; match or repeated match
  2017 00000450 1E                  <1> 	push ds
  2018 00000451 07                  <1> 	pop es
  2019 00000452 8DBF9000            <1> 	lea di, [bx + bm_rep]		; es:di -> bm_rep array
  2020                              <1> %if bit_model_size != 2
  2021                              <1>  %error Assuming word size for bit_model_size
  2022                              <1> %endif
  2023 00000456 8B4728              <1> 	mov ax, word [bx + state.st]
  2024 00000459 01C0                <1> 	add ax, ax			; ax = index is state
  2025                              <1> 	; jc short .error_CY_2	; (state.st is always < 12)
  2026 0000045B 01C7                <1> 	add di, ax			; es:di -> bm_rep[state()]
  2027                              <1> .error_CY_2:
  2028 0000045D 7230                <1> 	jc short .error_CY_3
  2029 0000045F E8CFFC              <1> 	call Range_decoder.decode_bit
  2030 00000462 7203E9EA00          <1> 	jnc .2nd_bit_zero
  2031                              <1> 
  2032                              <1> .2nd_bit_not_zero:
  2033 00000467 1E                  <1> 	push ds
  2034 00000468 07                  <1> 	pop es
  2035 00000469 8DBFA800            <1> 	lea di, [bx + bm_rep0]		; es:di -> bm_rep0 array
  2036                              <1> %if bit_model_size != 2
  2037                              <1>  %error Assuming word size for bit_model_size
  2038                              <1> %endif
  2039 0000046D 8B4728              <1> 	mov ax, word [bx + state.st]
  2040 00000470 01C0                <1> 	add ax, ax			; ax = index is state
  2041                              <1> 	; jc short .error_CY_3	; (state.st is always < 12)
  2042 00000472 01C7                <1> 	add di, ax			; es:di -> bm_rep0[state()]
  2043 00000474 7219                <1> 	jc short .error_CY_3
  2044 00000476 E8B8FC              <1> 	call Range_decoder.decode_bit
  2045 00000479 7233                <1> 	jc .3rd_bit_not_zero
  2046                              <1> 
  2047                              <1> .3rd_bit_zero:
  2048 0000047B 1E                  <1> 	push ds
  2049 0000047C 07                  <1> 	pop es
  2050 0000047D 8DBFF030            <1> 	lea di, [bx + bm_len]		; es:di -> bm_len 2D array
  2051 00000481 B80800              <1> 	mov ax, bit_model_size * pos_states
  2052                              <1> 				; (2 * 4 = 8)
  2053 00000484 F76728              <1> 	mul word [bx + state.st]; (< 12)
  2054                              <1> 					; dx:ax = first index is state
  2055                              <1> 	; test dx, dx
  2056                              <1> 	; stc
  2057                              <1> 	; jnz short .error_CY_3	; (dx:ax is always < 12 * 8)
  2058                              <1> %if bit_model_size != 2
  2059                              <1>  %error Assuming word size for bit_model_size
  2060                              <1> %endif
  2061                              <1> %rep bit_model_size
  2062                              <1> 	add ax, word [bp + ?pos_state]
  2063                              <1> 	; jc short .error_CY_3	; (pos_state is always < 4
  2064                              <1> 				;  and state_st is always < 12
  2065                              <1> 				;  and ax is < 12 * 8 prior to adding)
  2066                              <1> %endrep
  2062 00000487 0346EE              <2>  add ax, word [bp + ?pos_state]
  2063                              <2> 
  2064                              <2> 
  2065                              <2> 
  2062 0000048A 0346EE              <2>  add ax, word [bp + ?pos_state]
  2063                              <2> 
  2064                              <2> 
  2065                              <2> 
  2067 0000048D 01C7                <1> 	add di, ax			; es:di -> bm_len[state()]
  2068                              <1> .error_CY_3:
  2069 0000048F 722A                <1> 	jc short .error_CY_4
  2070 00000491 E89DFC              <1> 	call Range_decoder.decode_bit
  2071 00000494 7303E99500          <1> 	jc .4th_bit_not_zero
  2072                              <1> 
  2073                              <1> .4th_bit_zero:
  2074                              <1> ; State.set_short_rep
  2075 00000499 B8090B              <1> 	mov ax, 9 | (11 << 8)
  2076 0000049C E815FC              <1> 	call State.select
  2077                              <1> 
  2078 0000049F 8B4718              <1> 	mov ax, word [bx + rep0]
  2079 000004A2 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  2080 000004A5 E8D9FD              <1> 	call LZ_decoder.peek
  2081 000004A8 E8FB02              <1> 	call LZ_decoder.put_byte
  2082 000004AB E939FF              <1> 	jmp .loop
  2083                              <1> 
  2084                              <1> .3rd_bit_not_zero:
  2085 000004AE 1E                  <1> 	push ds
  2086 000004AF 07                  <1> 	pop es
  2087 000004B0 8DBFC000            <1> 	lea di, [bx + bm_rep1]		; es:di -> bm_rep1 array
  2088                              <1> %if bit_model_size != 2
  2089                              <1>  %error Assuming word size for bit_model_size
  2090                              <1> %endif
  2091 000004B4 8B4728              <1> 	mov ax, word [bx + state.st]
  2092 000004B7 01C0                <1> 	add ax, ax			; ax = index is state
  2093                              <1> 	; jc short .error_CY_4	; (state.st is always < 12)
  2094 000004B9 01C7                <1> 	add di, ax			; es:di -> bm_rep1[state()]
  2095                              <1> .error_CY_4:
  2096 000004BB 7220                <1> 	jc short .error_CY_4a
  2097 000004BD E871FC              <1> 	call Range_decoder.decode_bit
  2098 000004C0 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero
  2099                              <1> 
  2100                              <1> .3rd_bit_not_zero.4th_bit_zero:
  2101 000004C2 FF771E              <1> 	push word [bx + rep1 + 2]
  2102 000004C5 FF771C              <1> 	push word [bx + rep1]
  2103 000004C8 8F46FA              <1> 	pop word [bp + ?distance]
  2104 000004CB 8F46FC              <1> 	pop word [bp + ?distance + 2]
  2105 000004CE EB46                <1> 	jmp .3rd_bit_not_zero.common
  2106                              <1> 
  2107                              <1> .3rd_bit_not_zero.4th_bit_not_zero:
  2108 000004D0 1E                  <1> 	push ds
  2109 000004D1 07                  <1> 	pop es
  2110 000004D2 8DBFD800            <1> 	lea di, [bx + bm_rep2]		; es:di -> bm_rep2 array
  2111                              <1> %if bit_model_size != 2
  2112                              <1>  %error Assuming word size for bit_model_size
  2113                              <1> %endif
  2114 000004D6 8B4728              <1> 	mov ax, word [bx + state.st]
  2115 000004D9 01C0                <1> 	add ax, ax			; ax = index is state
  2116                              <1> 	; jc short .error_CY_5	; (state.st is always < 12)
  2117 000004DB 01C7                <1> 	add di, ax			; es:di -> bm_rep2[state()]
  2118                              <1> .error_CY_4a:
  2119 000004DD 7267                <1> 	jc short .error_CY_5
  2120 000004DF E84FFC              <1> 	call Range_decoder.decode_bit
  2121 000004E2 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero
  2122                              <1> 
  2123                              <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_zero:
  2124 000004E4 FF7722              <1> 	push word [bx + rep2 + 2]
  2125 000004E7 FF7720              <1> 	push word [bx + rep2]
  2126 000004EA 8F46FA              <1> 	pop word [bp + ?distance]
  2127 000004ED 8F46FC              <1> 	pop word [bp + ?distance + 2]
  2128 000004F0 EB18                <1> 	jmp .3rd_bit_not_zero.4th_bit_not_zero.common
  2129                              <1> 
  2130                              <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero:
  2131 000004F2 FF7726              <1> 	push word [bx + rep3 + 2]
  2132 000004F5 FF7724              <1> 	push word [bx + rep3]
  2133 000004F8 8F46FA              <1> 	pop word [bp + ?distance]
  2134 000004FB 8F46FC              <1> 	pop word [bp + ?distance + 2]	; distance = rep3
  2135 000004FE FF7722              <1> 	push word [bx + rep2 + 2]
  2136 00000501 FF7720              <1> 	push word [bx + rep2]
  2137 00000504 8F4724              <1> 	pop word [bx + rep3]
  2138 00000507 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  2139                              <1> 
  2140                              <1> .3rd_bit_not_zero.4th_bit_not_zero.common:
  2141 0000050A FF771E              <1> 	push word [bx + rep1 + 2]
  2142 0000050D FF771C              <1> 	push word [bx + rep1]
  2143 00000510 8F4720              <1> 	pop word [bx + rep2]
  2144 00000513 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  2145                              <1> 
  2146                              <1> .3rd_bit_not_zero.common:
  2147 00000516 FF771A              <1> 	push word [bx + rep0 + 2]
  2148 00000519 FF7718              <1> 	push word [bx + rep0]
  2149 0000051C 8F471C              <1> 	pop word [bx + rep1]
  2150 0000051F 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  2151 00000522 FF76FC              <1> 	push word [bp + ?distance + 2]
  2152 00000525 FF76FA              <1> 	push word [bp + ?distance]
  2153 00000528 8F4718              <1> 	pop word [bx + rep0]
  2154 0000052B 8F471A              <1> 	pop word [bx + rep0 + 2]	; rep0 = distance
  2155                              <1> 
  2156                              <1> .4th_bit_not_zero:
  2157                              <1> ; State.set_rep
  2158 0000052E B8080B              <1> 	mov ax, 8 | (11 << 8)
  2159 00000531 E880FB              <1> 	call State.select
  2160                              <1> 
  2161 00000534 8B46EE              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  2162 00000537 1E                  <1> 	push ds
  2163 00000538 07                  <1> 	pop es
  2164 00000539 8DBFDA36            <1> 	lea di, [bx + rep_len_model]	; -> len_model to use
  2165 0000053D E8E0FC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  2166 00000540 83C002              <1> 	add ax, min_match_len
  2167 00000543 83D200              <1> 	adc dx, 0
  2168                              <1> .error_CY_5:
  2169 00000546 7250                <1> 	jc short .error_CY_6
  2170 00000548 8946F6              <1> 	mov word [bp + ?len], ax
  2171 0000054B 8956F8              <1> 	mov word [bp + ?len + 2], dx
  2172 0000054E E93001              <1> 	jmp .handle_match
  2173                              <1> 
  2174                              <1> .2nd_bit_zero:			; match
  2175 00000551 FF7722              <1> 	push word [bx + rep2 + 2]
  2176 00000554 FF7720              <1> 	push word [bx + rep2]
  2177 00000557 8F4724              <1> 	pop word [bx + rep3]
  2178 0000055A 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  2179                              <1> 
  2180 0000055D FF771E              <1> 	push word [bx + rep1 + 2]
  2181 00000560 FF771C              <1> 	push word [bx + rep1]
  2182 00000563 8F4720              <1> 	pop word [bx + rep2]
  2183 00000566 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  2184                              <1> 
  2185 00000569 FF771A              <1> 	push word [bx + rep0 + 2]
  2186 0000056C FF7718              <1> 	push word [bx + rep0]
  2187 0000056F 8F471C              <1> 	pop word [bx + rep1]
  2188 00000572 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  2189                              <1> 
  2190 00000575 8B46EE              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  2191 00000578 1E                  <1> 	push ds
  2192 00000579 07                  <1> 	pop es
  2193 0000057A 8DBF5634            <1> 	lea di, [bx + match_len_model]	; -> len_model to use
  2194 0000057E E89FFC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  2195                              <1> 
  2196 00000581 8946F0              <1> 	mov word [bp + ?len_state], ax
  2197 00000584 85D2                <1> 	test dx, dx
  2198 00000586 7505                <1> 	jnz @F
  2199 00000588 83F803              <1> 	cmp ax, len_states - 1
  2200 0000058B 7205                <1> 	jb @FF
  2201                              <1> @@:
  2202 0000058D C746F00300          <1> 	mov word [bp + ?len_state], len_states - 1
  2203                              <1> @@:
  2204                              <1> 
  2205 00000592 83C002              <1> 	add ax, min_match_len
  2206 00000595 83D200              <1> 	adc dx, 0
  2207                              <1> .error_CY_6:
  2208 00000598 723C                <1> 	jc short .error_CY_7
  2209                              <1> 
  2210 0000059A 8946F6              <1> 	mov word [bp + ?len], ax
  2211 0000059D 8956F8              <1> 	mov word [bp + ?len + 2], dx
  2212                              <1> 
  2213 000005A0 1E                  <1> 	push ds
  2214 000005A1 07                  <1> 	pop es
  2215 000005A2 8DBF5031            <1> 	lea di, [bx + bm_dis_slot]	; -> 2D array bm_dis_slot
  2216                              <1> 
  2217 000005A6 B88000              <1> 	mov ax, bit_model_size * (1 << dis_slot_bits)
  2218 000005A9 F766F0              <1> 	mul word [bp + ?len_state]	; first index is len_state
  2219                              <1> 		; bit_model_size = 2
  2220                              <1> 		; 1 << dis_slot_bits = 1 << 6 = 64
  2221                              <1> 		; ?len_state < 4
  2222                              <1> 		; multiplication 2 * 64 * 3 = 384
  2223                              <1> 					; dx:ax = first index into array
  2224 000005AC 01C7                <1> 	add di, ax			; -> 1D array at bm_dis_slot[len_state]
  2225 000005AE B90600              <1> 	mov cx, dis_slot_bits
  2226 000005B1 E8E2FB              <1> 	call Range_decoder.decode_tree
  2227 000005B4 894718              <1> 	mov word [bx + rep0], ax
  2228 000005B7 89571A              <1> 	mov word [bx + rep0 + 2], dx
  2229                              <1> 
  2230 000005BA 85D2                <1> 	test dx, dx			; (same flags as cmp dx, 0)
  2231 000005BC 7503                <1> 	jne @F
  2232 000005BE 83F804              <1> 	cmp ax, start_dis_model
  2233                              <1> @@:
  2234 000005C1 7303E99B00          <1> 	jnae .not_rep0_ae_start_dis_model
  2235                              <1> 
  2236                              <1> .rep0_ae_start_dis_model:
  2237 000005C6 8946F2              <1> 	mov word [bp + ?dis_slot], ax
  2238 000005C9 8956F4              <1> 	mov word [bp + ?dis_slot + 2], dx
  2239                              <1> 
  2240 000005CC D1EA                <1> 	shr dx, 1
  2241 000005CE D1D8                <1> 	rcr ax, 1			; dis_slot >> 1
  2242 000005D0 83E801              <1> 	sub ax, 1
  2243 000005D3 83DA00              <1> 	sbb dx, 0			; - 1
  2244                              <1> .error_CY_7:
  2245                              <1> .error_CY_8:
  2246 000005D6 7230                <1> 	jc short .error_CY_9
  2247 000005D8 F9                  <1> 	stc
  2248 000005D9 752D                <1> 	jnz short .error_CY_9
  2249 000005DB 91                  <1> 	xchg cx, ax			; cx = direct_bits, clobber ax
  2250 000005DC 31D2                <1> 	xor dx, dx
  2251 000005DE B80100              <1> 	mov ax, 1
  2252 000005E1 2246F2              <1> 	and al, byte [bp + ?dis_slot]
  2253 000005E4 0C02                <1> 	or al, 2
  2254 000005E6 51                  <1> 	push cx
  2255 000005E7 E306                <1> 	jcxz @FF
  2256                              <1> @@:
  2257 000005E9 D1E0                <1> 	shl ax, 1
  2258 000005EB D1D2                <1> 	rcl dx, 1
  2259 000005ED E2FA                <1> 	loop @B
  2260                              <1> @@:
  2261 000005EF 59                  <1> 	pop cx
  2262 000005F0 894718              <1> 	mov word [bx + rep0], ax
  2263 000005F3 89571A              <1> 	mov word [bx + rep0 + 2], dx
  2264                              <1> 
  2265 000005F6 837EF400            <1> 	cmp word [bp + ?dis_slot + 2], 0
  2266 000005FA 7504                <1> 	jne @F
  2267 000005FC 837EF20E            <1> 	cmp word [bp + ?dis_slot], end_dis_model
  2268                              <1> @@:
  2269 00000600 7328                <1> 	jnb .not_dis_slot_below_end_dis_model
  2270                              <1> 
  2271                              <1> .dis_slot_below_end_dis_model:
  2272 00000602 2B46F2              <1> 	sub ax, word [bp + ?dis_slot]
  2273 00000605 1B56F4              <1> 	sbb dx, word [bp + ?dis_slot + 2]
  2274                              <1> 					; dx:ax = index into bm_dis array
  2275                              <1> 					;  = rep0 - dis_slot
  2276                              <1> .error_CY_9:
  2277 00000608 722D                <1> 	jc short .error_CY_10
  2278                              <1> 
  2279                              <1> %if bit_model_size != 2
  2280                              <1>  %error Assuming word size for bit_model_size
  2281                              <1> %endif
  2282 0000060A 01C0                <1> 	add ax, ax
  2283 0000060C 11D2                <1> 	adc dx, dx			; dx:ax *= 2
  2284 0000060E 7227                <1> 	jc short .error_CY_10
  2285 00000610 F9                  <1> 	stc
  2286 00000611 7524                <1> 	jnz short .error_CY_10		; if dx != 0 -->
  2287 00000613 1E                  <1> 	push ds
  2288 00000614 07                  <1> 	pop es
  2289 00000615 8DBF5033            <1> 	lea di, [bx + bm_dis]		; es:di -> bm_dis array
  2290 00000619 01C7                <1> 	add di, ax			; index into the array
  2291 0000061B 721A                <1> 	jc short .error_CY_10
  2292 0000061D E8A2FB              <1> 	call Range_decoder.decode_tree_reversed
  2293 00000620 014718              <1> 	add word [bx + rep0], ax
  2294 00000623 11571A              <1> 	adc word [bx + rep0 + 2], dx
  2295 00000626 720F                <1> 	jc short .error_CY_10
  2296 00000628 EB37                <1> 	jmp .after_dis_slot_below
  2297                              <1> 
  2298                              <1> .not_dis_slot_below_end_dis_model:
  2299 0000062A 83E904              <1> 	sub cx, dis_align_bits
  2300 0000062D E8CEFA              <1> 	call Range_decoder.decode
  2301 00000630 B90400              <1> 	mov cx, dis_align_bits
  2302                              <1> @@:
  2303 00000633 D1E0                <1> 	shl ax, 1
  2304 00000635 D1D2                <1> 	rcl dx, 1
  2305                              <1> .error_CY_10:
  2306 00000637 721A                <1> 	jc short .error_CY_11
  2307 00000639 E2F8                <1> 	loop @B
  2308 0000063B 014718              <1> 	add word [bx + rep0], ax
  2309 0000063E 11571A              <1> 	adc word [bx + rep0 + 2], dx
  2310                              <1> 
  2311 00000641 B90400              <1> 	mov cx, dis_align_bits
  2312 00000644 1E                  <1> 	push ds
  2313 00000645 07                  <1> 	pop es
  2314 00000646 8DBF3634            <1> 	lea di, [bx + bm_align]
  2315 0000064A E875FB              <1> 	call Range_decoder.decode_tree_reversed
  2316 0000064D 014718              <1> 	add word [bx + rep0], ax
  2317 00000650 11571A              <1> 	adc word [bx + rep0 + 2], dx
  2318                              <1> .error_CY_11:
  2319 00000653 727D                <1> 	jc .error_CY_12
  2320                              <1> 
  2321 00000655 837F1AFF            <1> 	cmp word [bx + rep0 + 2], -1	; rep0 = 0FFFF_FFFFh ?
  2322 00000659 7504                <1> 	jne @F
  2323 0000065B 837F18FF            <1> 	cmp word [bx + rep0], -1
  2324                              <1> @@:
  2325 0000065F 7479                <1> 	je .end_member			; yes, end (marker found) -->
  2326                              <1> 
  2327                              <1> .after_dis_slot_below:
  2328                              <1> 
  2329                              <1> .not_rep0_ae_start_dis_model:
  2330                              <1> 
  2331                              <1> ; State.set_match
  2332 00000661 B8070A              <1> 	mov ax, 7 | (10 << 8)
  2333 00000664 E84DFA              <1> 	call State.select
  2334                              <1> 
  2335 00000667 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  2336 0000066A 8B4718              <1> 	mov ax, word [bx + rep0]
  2337                              <1> 
  2338 0000066D 3B5712              <1> 	cmp dx, word [bx + lz_decoder.dictionary_size + 2]
  2339 00000670 7503                <1> 	jne @F
  2340 00000672 3B4710              <1> 	cmp ax, word [bx + lz_decoder.dictionary_size]
  2341                              <1> @@:
  2342 00000675 7308                <1> 	jae short .error_AE_1
  2343                              <1> 
  2344                              <1> 		; check for (rep0 >= pos && !pos_wrapped)
  2345                              <1> 		;  (pos_wrapped is always false for us)
  2346 00000677 3B5716              <1> 	cmp dx, word [bx + lz_decoder.pos + 2]
  2347 0000067A 7503                <1> 	jne @F
  2348 0000067C 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  2349                              <1> @@:
  2350                              <1> .error_AE_1:
  2351 0000067F 7356                <1> 	jae short .error_1
  2352                              <1> 
  2353                              <1> .handle_match:
  2354 00000681 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  2355 00000684 8B4718              <1> 	mov ax, word [bx + rep0]
  2356                              <1> 
  2357 00000687 E80EFC              <1> 	call calculate_peek_pointer_disi
  2358                              <1> 
  2359 0000068A 8B46F6              <1> 	mov ax, word [bp + ?len]
  2360 0000068D 8B56F8              <1> 	mov dx, word [bp + ?len + 2]	; dx:ax = length
  2361                              <1> 
  2362                              <1> 
  2363                              <1> 		; INP:	dx:ax = length of match
  2364                              <1> 		;	di:si -> source (normalised)
  2365                              <1> 		;	ds:bx -> local variables structure
  2366                              <1> 		;	ss:bp -> depack stack frame,
  2367                              <1> 		;		with ?length_of_destination, ?dst
  2368                              <1> 		; OUT:	NC if success,
  2369                              <1> 		;	 ?length_of_destination and ?dst updated
  2370                              <1> 		;	CY if error
  2371                              <1> 		;	 (destination buffer too small or overlap error)
  2372                              <1> 		;	! may jump to depack.end if ?dst_max_segment reached
  2373                              <1> 		; CHG:	ax, cx, dx, di, si, es
  2374                              <1> ; handle_match:
  2375 00000690 014714              <1> 	add word [bx + lz_decoder.pos], ax
  2376 00000693 115716              <1> 	adc word [bx + lz_decoder.pos + 2], dx
  2377 00000696 723A                <1> 	jc short .error_CY_12		; (CY) -->
  2378                              <1> 
  2379 00000698 2946DE              <1> 	sub word [bp + ?length_of_destination], ax
  2380 0000069B 1956E0              <1> 	sbb word [bp + ?length_of_destination + 2], dx
  2381                              <1> 					; enough space left ?
  2382 0000069E 7232                <1> 	jb short .error_CY_12		; no --> (below == CY)
  2383                              <1> 
  2384 000006A0 1E                  <1> 	push ds
  2385                              <1> 
  2386 000006A1 8EDF                <1> 	mov ds, di			; ds:si -> source
  2387 000006A3 C47ED6              <1> 	les di, [bp + ?dst]		; es:di -> destination
  2388                              <1> .hm_loop:
  2389 000006A6 B9F0FF              <1> 	mov cx, 64 * 1024 - 16		; block size
  2390                              <1> 		; If both pointers are normalised, moving 0FFF0h bytes is
  2391                              <1> 		;  valid and results in a maximum offset of 0FFFFh in either.
  2392                              <1> 
  2393 000006A9 85D2                <1> 	test dx, dx			; >= 1_0000h ?
  2394 000006AB 7508                <1> 	jnz @F				; yes, full block -->
  2395 000006AD 85C0                <1> 	test ax, ax			; == 0 ?
  2396 000006AF 7415                <1> 	jz .hm_end			; yes, done -->
  2397 000006B1 39C8                <1> 	cmp ax, cx			; can move in one (last) block ?
  2398 000006B3 7607                <1> 	jbe .hm_last			; yes -->
  2399                              <1> @@:
  2400                              <1> 					; no, move one block and continue
  2401 000006B5 29C8                <1> 	sub ax, cx
  2402 000006B7 83DA00              <1> 	sbb dx, 0			; left over remaining
  2403 000006BA EB03                <1> 	jmp .hm_copy
  2404                              <1> 
  2405                              <1> .hm_last:
  2406 000006BC 91                  <1> 	xchg cx, ax			; cx = remaining length
  2407 000006BD 31C0                <1> 	xor ax, ax			; no more remaining
  2408                              <1> 
  2409                              <1> .hm_copy:
  2410 000006BF F3A4                <1> 	rep movsb			; move one block (full or partial)
  2411                              <1> 
  2412 000006C1 E83302              <1> 	call normalise_both_pointers
  2413 000006C4 EBE0                <1> 	jmp .hm_loop
  2414                              <1> 
  2415                              <1> .hm_end:
  2416 000006C6 897ED6              <1> 	mov word [bp + ?dst], di
  2417 000006C9 8C46D8              <1> 	mov word [bp + ?dst + 2], es
  2418                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
  2419                              <1> 	mov ax, es
  2420                              <1> 	cmp ax, word [bp + ?dst_max_segment]
  2421                              <1> 	jae depack.end
  2422                              <1> 		; note that we have the depack stack frame pointed to by
  2423                              <1> 		;  ss:bp here, which is needed for running depack.end
  2424                              <1> %endif
  2425 000006CC 1F                  <1> 	pop ds
  2426                              <1> %if _ALLOW_OVERLAPPING
  2427 000006CD 53                  <1> 	push bx
  2428 000006CE E80802              <1> 	call check_pointers_not_overlapping
  2429 000006D1 5B                  <1> 	pop bx				; returns CF
  2430                              <1> .error_CY_12:
  2431 000006D2 7203                <1> 	jc short .error_1
  2432                              <1> %endif
  2433 000006D4 E910FD              <1> 	jmp .loop
  2434                              <1> 
  2435                              <1> %if ! _ALLOW_OVERLAPPING
  2436                              <1> .error_CY_12:
  2437                              <1> %endif
  2438                              <1> .error_1:
  2439 000006D7 E9A000              <1> 	jmp .error
  2440                              <1> 
  2441                              <1> 
  2442                              <1> .end_member:			; End Of Stream marker
  2443 000006DA 837EF800            <1> 	cmp word [bp + ?len + 2], min_match_len >> 16
  2444 000006DE 7504                <1> 	jne @F
  2445 000006E0 837EF602            <1> 	cmp word [bp + ?len], min_match_len & 0FFFFh
  2446                              <1> @@:
  2447 000006E4 75F1                <1> 	jne short .error_1
  2448                              <1> 
  2449                              <1> 		; decode_member succeeded
  2450                              <1> 
  2451 000006E6 C55EE6              <1> 	lds bx, [bp + ?final_dst]	; -> localvariables
  2452                              <1> 
  2453 000006E9 836EE214            <1> 	sub word [bp + ?length_of_source], lzip_trailer_size
  2454 000006ED 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  2455 000006F1 7303E98400          <1> 	jc .error
  2456                              <1> 
  2457 000006F6 C476EA              <1> 	les si, [bp + ?src]	; es:si -> lzip_trailer.uncompressed_checksum
  2458 000006F9 83C604              <1> 	add si, 4			; skip CRC
  2459                              <1> 
  2460                              <1> 				; es:si -> lzip_trailer.uncompressed_size
  2461 000006FC 26AD                <1> 	es lodsw			; does the destination length match ?
  2462 000006FE 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  2463 00000701 7577                <1> 	jne .error
  2464 00000703 26AD                <1> 	es lodsw
  2465 00000705 3B4716              <1> 	cmp ax, word [bx + lz_decoder.pos + 2]
  2466 00000708 7570                <1> 	jne .error			; if no -->
  2467 0000070A 26AD                <1> 	es lodsw
  2468 0000070C 85C0                <1> 	test ax, ax
  2469 0000070E 756A                <1> 	jnz .error
  2470 00000710 26AD                <1> 	es lodsw
  2471 00000712 85C0                <1> 	test ax, ax
  2472 00000714 7564                <1> 	jnz .error
  2473                              <1> 
  2474 00000716 830714              <1> 	add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size
  2475 00000719 83570200            <1> 	adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0
  2476 0000071D 725B                <1> 	jc .error
  2477                              <1> 
  2478                              <1> 				; es:si -> lzip_trailer.member_size
  2479 0000071F 26AD                <1> 	es lodsw			; does the source length match ?
  2480 00000721 3B07                <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos]
  2481 00000723 7555                <1> 	jne .error
  2482 00000725 26AD                <1> 	es lodsw
  2483 00000727 3B4702              <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2]
  2484 0000072A 754E                <1> 	jne .error
  2485 0000072C 26AD                <1> 	es lodsw
  2486 0000072E 85C0                <1> 	test ax, ax
  2487 00000730 7548                <1> 	jnz .error
  2488 00000732 26AD                <1> 	es lodsw
  2489 00000734 85C0                <1> 	test ax, ax
  2490 00000736 7542                <1> 	jnz .error
  2491                              <1> 
  2492                              <1> 				; es:si -> behind lzip_trailer
  2493 00000738 06                  <1> 	 push es
  2494 00000739 56                  <1> 	 push si
  2495 0000073A E8C901              <1> 	call normalise_pointer
  2496 0000073D 8F46EA              <1> 	 pop word [bp + ?src]
  2497 00000740 8F46EC              <1> 	 pop word [bp + ?src + 2]
  2498                              <1> 
  2499 00000743 E9C5FB              <1> 	jmp .loop_member
  2500                              <1> 
  2501                              <1> .end:
  2502                              <1> 
  2503                              <1> .final:
  2504                              <1> %if _COUNTER
  2505                              <1> 	mov al, '%'
  2506                              <1> 	call disp_al
  2507                              <1> %endif
  2508 00000746 C47EE6              <1> 	les di, [bp + ?final_dst]
  2509                              <1> 				; -> destination
  2510 00000749 C576DA              <1> 	lds si, [bp + ?original_dst]
  2511                              <1> 				; -> source
  2512 0000074C 1E                  <1> 	 push ds
  2513 0000074D 56                  <1> 	 push si
  2514 0000074E E80002              <1> 	call pointer_to_linear	; dx:ax = linear ?original_dst
  2515 00000751 91                  <1> 	xchg cx, ax
  2516 00000752 87DA                <1> 	xchg bx, dx		; bx:cx = linear ?original_dst, clobber dx:ax
  2517 00000754 FF76D8              <1> 	 push word [bp + ?dst + 2]
  2518 00000757 FF76D6              <1> 	 push word [bp + ?dst]
  2519 0000075A E8F401              <1> 	call pointer_to_linear
  2520 0000075D 29C8                <1> 	sub ax, cx
  2521 0000075F 19DA                <1> 	sbb dx, bx		; = linear dst minus linear original_dst
  2522                              <1> 
  2523 00000761 B90400              <1> 	mov cx, 4
  2524 00000764 83C00F              <1> 	add ax, 15
  2525 00000767 83D200              <1> 	adc dx, 0
  2526                              <1> @@:
  2527 0000076A D1EA                <1> 	shr dx, 1
  2528 0000076C D1D8                <1> 	rcr ax, 1
  2529 0000076E E2FA                <1> 	loop @B
  2530 00000770 89C1                <1> 	mov cx, ax
  2531 00000772 85D2                <1> 	test dx, dx
  2532                              <1> d0	mov byte [bp + ?errordata], 84h
  2533 00000774 7504                <1> 	jnz .error
  2534                              <1> 
  2535 00000776 E8C800              <1> 	call x_mov_p
  2536                              <1> 
  2537 00000779 A8                  <1> 	db __TEST_IMM8			; (NC)
  2538                              <1> .error:
  2539 0000077A F9                  <1> 	stc
  2540                              <1> 
  2541                              <1> %if _COUNTER
  2542                              <1> 	lahf
  2543                              <1> 	mov al, 13
  2544                              <1> 	call disp_al
  2545                              <1> 	mov al, 10
  2546                              <1> 	call disp_al
  2547                              <1> 	sahf
  2548                              <1> %endif
  2549                              <1> d0	mov bx, word [bp + ?errordata]
  2550 0000077B 89EC5D              <1> 	lleave code
  2551 0000077E C3                  <1> 	lret
  2552                              <1> 
  2553                              <1> 
  2554                              <1> 		; INP:	ds:bx -> range_decoder structure
  2555                              <1> 		;	ss:bp -> depack stack frame
  2556                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  2557                              <1> 		;	If success,
  2558                              <1> 		;	 al = byte read
  2559                              <1> 		; CHG:	-
  2560                              <1> Range_decoder.get_byte:
  2561 0000077F 830701              <1> 	add word [bx + range_decoder.member_pos], 1
  2562 00000782 83570200            <1> 	adc word [bx + range_decoder.member_pos + 2], 0
  2563 00000786 72F2                <1> 	jc short .error
  2564                              <1> 
  2565                              <1> 		; INP:	ds:bx -> range_decoder structure
  2566                              <1> 		;	ss:bp -> depack stack frame
  2567                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  2568                              <1> 		;	If success,
  2569                              <1> 		;	 al = value read
  2570                              <1> 		; CHG:	-
  2571                              <1> ; get_byte:
  2572 00000788 1E                  <1> 	push ds
  2573 00000789 56                  <1> 	push si
  2574                              <1> 
  2575 0000078A 836EE201            <1> 	sub word [bp + ?length_of_source], 1
  2576 0000078E 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  2577 00000792 72E6                <1> 	jc short .error
  2578                              <1> 
  2579 00000794 C576EA              <1> 	lds si, [bp + ?src]
  2580 00000797 AC                  <1> 	lodsb
  2581 00000798 1E                  <1> 	 push ds
  2582 00000799 56                  <1> 	 push si
  2583 0000079A E86901              <1> 	call normalise_pointer
  2584 0000079D 8F46EA              <1> 	 pop word [bp + ?src]
  2585 000007A0 8F46EC              <1> 	 pop word [bp + ?src + 2]
  2586 000007A3 5E                  <1> 	pop si
  2587 000007A4 1F                  <1> 	pop ds
  2588 000007A5 C3                  <1> 	retn
  2589                              <1> 
  2590                              <1> .error: equ depack.error
  2591                              <1> 
  2592                              <1> 
  2593                              <1> 		; INP:	ds:bx -> lz_decoder structure
  2594                              <1> 		;	al = byte to write to buffer
  2595                              <1> 		;	ss:bp -> depack stack frame
  2596                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  2597                              <1> 		; CHG:	cx, dx, ax, di, es
  2598                              <1> LZ_decoder.put_byte:
  2599 000007A6 C47ED6              <1> 	les di, [bp + ?dst]
  2600                              <1> 
  2601 000007A9 83471401            <1> 	add word [bx + lz_decoder.pos], 1
  2602 000007AD 83571600            <1> 	adc word [bx + lz_decoder.pos + 2], 0
  2603 000007B1 72C7                <1> 	jc short .error
  2604                              <1> 
  2605 000007B3 836EDE01            <1> 	sub word [bp + ?length_of_destination], 1
  2606 000007B7 835EE000            <1> 	sbb word [bp + ?length_of_destination + 2], 0
  2607 000007BB 72BD                <1> 	jb short .error
  2608                              <1> 
  2609 000007BD AA                  <1> 	stosb
  2610 000007BE 06                  <1> 	 push es
  2611 000007BF 57                  <1> 	 push di
  2612 000007C0 E84301              <1> 	call normalise_pointer
  2613 000007C3 8F46D6              <1> 	 pop word [bp + ?dst]
  2614 000007C6 8F46D8              <1> 	 pop word [bp + ?dst + 2]
  2615                              <1> 
  2616                              <1> %if _ALLOW_OVERLAPPING
  2617 000007C9 53                  <1> 	push bx
  2618 000007CA E80C01              <1> 	call check_pointers_not_overlapping
  2619 000007CD 5B                  <1> 	pop bx			; returns CF
  2620 000007CE 72AA                <1> 	jc short .error
  2621                              <1> %endif
  2622 000007D0 C3                  <1> 	retn
  2623                              <1> 
  2624                              <1> .error: equ depack.error
  2625                              <1> 
  2626                              <1> 
  2627                              <1> 		; INP:	ds:si = pointer
  2628                              <1> 		;	es:di = pointer
  2629                              <1> 		; OUT:	ds:si anti normalised
  2630                              <1> 		;	es:di anti normalised
  2631                              <1> anti_normalise_both_pointers:
  2632 000007D1 1E                  <1> 	 push ds
  2633 000007D2 56                  <1> 	 push si
  2634 000007D3 E80A00              <1> 	call anti_normalise_pointer
  2635 000007D6 5E                  <1> 	 pop si
  2636 000007D7 1F                  <1> 	 pop ds
  2637                              <1> 
  2638 000007D8 06                  <1> 	 push es
  2639 000007D9 57                  <1> 	 push di
  2640 000007DA E80300              <1> 	call anti_normalise_pointer
  2641 000007DD 5F                  <1> 	 pop di
  2642 000007DE 07                  <1> 	 pop es
  2643 000007DF C3                  <1> 	retn
  2644                              <1> 
  2645                              <1> 
  2646                              <1> 		; INP:	word [ss:sp + 2] = segment
  2647                              <1> 		;	word [ss:sp] = offset
  2648                              <1> 		;
  2649                              <1> 		; Note:	Does not work correctly with pointers that point to
  2650                              <1> 		;	 a HMA location. Do not use then!
  2651                              <1> anti_normalise_pointer:
  2652                              <1> 	lframe near, nested
  2653                              <1> 	lpar word,	segment
  2654                              <1> 	lpar word,	offset
  2655                              <1> 	lpar_return
  2656 000007E0 5589E5              <1> 	lenter
  2657 000007E3 53                  <1> 	push bx
  2658 000007E4 51                  <1> 	push cx
  2659                              <1> 
  2660 000007E5 31DB                <1> 	xor bx, bx
  2661 000007E7 31C9                <1> 	xor cx, cx
  2662 000007E9 FF7606              <1> 	 push word [bp + ?segment]
  2663 000007EC FF7604              <1> 	 push word [bp + ?offset]
  2664 000007EF E80A00              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  2665 000007F2 8F4604              <1> 	 pop word [bp + ?offset]
  2666 000007F5 8F4606              <1> 	 pop word [bp + ?segment]
  2667                              <1> 
  2668 000007F8 59                  <1> 	pop cx
  2669 000007F9 5B                  <1> 	pop bx
  2670 000007FA 5D                  <1> 	lleave
  2671 000007FB C3                  <1> 	lret
  2672                              <1> 
  2673                              <1> 
  2674                              <1> 		; INP:	word [ss:sp + 2] = segment
  2675                              <1> 		;	word [ss:sp] = offset
  2676                              <1> 		;	bx:cx = add/sub displacement
  2677                              <1> 		; OUT:	dword [ss:sp] = anti-normalised address
  2678                              <1> 		;
  2679                              <1> 		; An anti-normalised pointer has an offset as high as possible,
  2680                              <1> 		;  which is in the range 0FFF0h to 0FFFFh unless the pointed-to
  2681                              <1> 		;  location is in the first 64 KiB of memory.
  2682                              <1> anti_normalise_pointer_with_displacement_bxcx:
  2683                              <1> 	lframe near, nested
  2684                              <1> 	lpar word,	segment
  2685                              <1> 	lpar word,	offset
  2686                              <1> 	lpar_return
  2687 000007FC 5589E5              <1> 	lenter
  2688 000007FF 50                  <1> 	push ax
  2689 00000800 52                  <1> 	push dx
  2690                              <1> 
  2691 00000801 FF7606              <1> 	 push word [bp + ?segment]
  2692 00000804 FF7604              <1> 	 push word [bp + ?offset]
  2693 00000807 E84701              <1> 	call pointer_to_linear
  2694                              <1> 
  2695 0000080A 01C8                <1> 	add ax, cx
  2696 0000080C 11DA                <1> 	adc dx, bx			; dx:ax += bx:cx
  2697                              <1> 
  2698 0000080E 83FA01              <1> 	cmp dx, 1
  2699 00000811 7223                <1> 	jb @F
  2700                              <1> 
  2701 00000813 50                  <1> 	push ax
  2702 00000814 83C8F0              <1> 	or ax, 0FFF0h
  2703 00000817 894604              <1> 	mov word [bp + ?offset], ax
  2704 0000081A 58                  <1> 	pop ax
  2705                              <1> 
  2706 0000081B 83E8F0              <1> 	sub ax, 0FFF0h
  2707 0000081E 83DA00              <1> 	sbb dx, 0
  2708                              <1> 
  2709                              <1> %rep 4
  2710                              <1> 	shr dx, 1
  2711                              <1> 	rcr ax, 1
  2712                              <1> %endrep
  2710 00000821 D1EA                <2>  shr dx, 1
  2711 00000823 D1D8                <2>  rcr ax, 1
  2710 00000825 D1EA                <2>  shr dx, 1
  2711 00000827 D1D8                <2>  rcr ax, 1
  2710 00000829 D1EA                <2>  shr dx, 1
  2711 0000082B D1D8                <2>  rcr ax, 1
  2710 0000082D D1EA                <2>  shr dx, 1
  2711 0000082F D1D8                <2>  rcr ax, 1
  2713 00000831 894606              <1> 	mov word [bp + ?segment], ax
  2714                              <1> 
  2715 00000834 EB07                <1> 	jmp .return
  2716                              <1> 
  2717                              <1> 		; dx:ax = 0000:offset
  2718                              <1> @@:
  2719 00000836 894604              <1> 	mov word [bp + ?offset], ax
  2720 00000839 83660600            <1> 	and word [bp + ?segment], 0
  2721                              <1> 
  2722                              <1> .return:
  2723 0000083D 5A                  <1> 	pop dx
  2724 0000083E 58                  <1> 	pop ax
  2725 0000083F 5D                  <1> 	lleave
  2726 00000840 C3                  <1> 	lret
  2727                              <1> 
  2728                              <1> 
  2729                              <1> 		; Move paragraphs
  2730                              <1> 		;
  2731                              <1> 		; INP:	ds:si -> source
  2732                              <1> 		;	es:di -> destination
  2733                              <1> 		;	cx = number of paragraphs
  2734                              <1> 		; CHG:	ax, bx, cx, dx
  2735                              <1> 		; OUT:	ds:si -> after source (normalised)
  2736                              <1> 		;	es:di -> after destination (normalised)
  2737                              <1> 		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  2738                              <1> 		;	Do not provide a wrapped/HMA source or destination!
  2739                              <1> x_mov_p:
  2740 00000841 E8B300              <1> 	call normalise_both_pointers
  2741 00000844 8CD8                <1> 	mov ax, ds
  2742 00000846 8CC2                <1> 	mov dx, es
  2743                              <1> 
  2744 00000848 85C9                <1> 	test cx, cx
  2745 0000084A 7503E98800          <1> 	jz .return
  2746                              <1> 
  2747 0000084F 39D0                <1> 	cmp ax, dx		; source above destination ?
  2748 00000851 7716                <1> 	ja .up			; yes, move up (forwards) -->
  2749 00000853 7206                <1> 	jb .check_down
  2750                              <1> 
  2751 00000855 39FE                <1> 	cmp si, di
  2752 00000857 7710                <1> 	ja .up
  2753 00000859 747C                <1> 	je .return		; pointers are the same, no need to move -->
  2754                              <1> .check_down:
  2755 0000085B 50                  <1> 	push ax
  2756 0000085C 01C8                <1> 	add ax, cx		; (expected not to carry)
  2757 0000085E 39D0                <1> 	cmp ax, dx		; end of source is above destination ?
  2758 00000860 58                  <1> 	pop ax
  2759 00000861 7726                <1> 	ja .down		; yes, move from top down -->
  2760 00000863 7204                <1> 	jb .up
  2761 00000865 39FE                <1> 	cmp si, di
  2762 00000867 7720                <1> 	ja .down
  2763                              <1> 
  2764                              <1> 	; Here, the end of source is below-or-equal the destination,
  2765                              <1> 	;  so they do not overlap. In this case we prefer moving up.
  2766                              <1> .up:
  2767                              <1> .uploop:
  2768 00000869 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  2769 0000086D 760C                <1> 	jbe .uplast		; no -->
  2770 0000086F 51                  <1> 	push cx
  2771 00000870 B9F87F              <1> 	mov cx, 0FFF0h /2
  2772 00000873 F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  2773 00000875 59                  <1> 	pop cx
  2774 00000876 E87E00              <1> 	call normalise_both_pointers
  2775 00000879 EBEE                <1> 	jmp short .uploop	; proceed for more -->
  2776                              <1> .uplast:
  2777 0000087B 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  2778 0000087F D1E1                <1> 	shl cx, 1
  2779 00000881 D1E1                <1> 	shl cx, 1
  2780 00000883 D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  2781 00000885 F3A5                <1> 	rep movsw		; move last part
  2782 00000887 EB4E                <1> 	jmp short .return
  2783                              <1> 
  2784                              <1> .down:
  2785 00000889 FD                  <1> 	std			; _AMD_ERRATUM_109_WORKAROUND as below
  2786                              <1> 
  2787 0000088A 89C8                <1> 	mov ax, cx
  2788 0000088C 31DB                <1> 	xor bx, bx
  2789 0000088E 51                  <1> 	push cx
  2790 0000088F B90400              <1> 	mov cx, 4
  2791                              <1> @@:
  2792 00000892 D1E0                <1> 	shl ax, 1
  2793 00000894 D1D3                <1> 	rcl bx, 1
  2794 00000896 E2FA                <1> 	loop @B
  2795 00000898 83E802              <1> 	sub ax, 2
  2796 0000089B 83DB00              <1> 	sbb bx, 0		; -> point at last word
  2797                              <1> 		; (Cannot borrow here because we checked that cx
  2798                              <1> 		;  was nonzero at the intro to this function, so
  2799                              <1> 		;  bx:ax is at least 16 prior to this subtraction.)
  2800 0000089E 91                  <1> 	xchg ax, cx		; bx:cx = displacement to point to last word
  2801 0000089F 1E                  <1> 	 push ds
  2802 000008A0 56                  <1> 	 push si
  2803 000008A1 E858FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  2804 000008A4 5E                  <1> 	 pop si
  2805 000008A5 1F                  <1> 	 pop ds			; -> last word of source
  2806 000008A6 06                  <1> 	 push es
  2807 000008A7 57                  <1> 	 push di
  2808 000008A8 E851FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  2809 000008AB 5F                  <1> 	 pop di
  2810 000008AC 07                  <1> 	 pop es			; -> last word of destination
  2811 000008AD 59                  <1> 	pop cx
  2812                              <1> 
  2813                              <1> .dnloop:
  2814 000008AE 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  2815 000008B2 760C                <1> 	jbe .dnlast		; no -->
  2816 000008B4 51                  <1> 	push cx
  2817 000008B5 B9F87F              <1> 	mov cx, 0FFF0h /2
  2818 000008B8 F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  2819 000008BA 59                  <1> 	pop cx
  2820 000008BB E813FF              <1> 	call anti_normalise_both_pointers
  2821 000008BE EBEE                <1> 	jmp short .dnloop	; proceed for more -->
  2822                              <1> .dnlast:
  2823 000008C0 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  2824 000008C4 D1E1                <1> 	shl cx, 1
  2825 000008C6 D1E1                <1> 	shl cx, 1
  2826 000008C8 D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  2827                              <1> 
  2828                              <1> 
  2829                              <1> 	numdef AMD_ERRATUM_109_WORKAROUND, 1
  2830                              <1> %if 0
  2831                              <1> 
  2832                              <1> Jack R. Ellis pointed out this erratum:
  2833                              <1> 
  2834                              <1> Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
  2835                              <1> 
  2836                              <1> 109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
  2837                              <1> 
  2838                              <1> Description
  2839                              <1> 
  2840                              <1> In certain situations a REP MOVS instruction may lead to
  2841                              <1> incorrect results. An incorrect address size, data size
  2842                              <1> or source operand segment may be used or a succeeding
  2843                              <1> instruction may be skipped. This may occur under the
  2844                              <1> following conditions:
  2845                              <1> 
  2846                              <1> * EFLAGS.DF=1 (the string is being moved in the reverse direction).
  2847                              <1> 
  2848                              <1> * The number of items being moved (RCX) is between 1 and 20.
  2849                              <1> 
  2850                              <1> * The REP MOVS instruction is preceded by some microcoded instruction
  2851                              <1>   that has not completely retired by the time the REP MOVS begins
  2852                              <1>   execution. The set of such instructions includes BOUND, CLI, LDS,
  2853                              <1>   LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
  2854                              <1> 
  2855                              <1> Potential Effect on System
  2856                              <1> 
  2857                              <1> Incorrect results may be produced or the system may hang.
  2858                              <1> 
  2859                              <1> Suggested Workaround
  2860                              <1> 
  2861                              <1> Contact your AMD representative for information on a BIOS update.
  2862                              <1> 
  2863                              <1> %endif
  2864                              <1> 
  2865                              <1> %if _AMD_ERRATUM_109_WORKAROUND
  2866 000008CA E308                <1> 	jcxz @FF
  2867 000008CC 83F914              <1> 	cmp cx, 20
  2868 000008CF 7703                <1> 	ja @FF
  2869                              <1> @@:
  2870 000008D1 A5                  <1> 	movsw
  2871 000008D2 E2FD                <1> 	loop @B
  2872                              <1> @@:
  2873                              <1> %endif
  2874 000008D4 F3A5                <1> 	rep movsw		; move first part
  2875 000008D6 FC                  <1> 	cld
  2876                              <1> .return:
  2877 000008D7 EB1E                <1> 	jmp normalise_both_pointers
   924                                  %endif
   925                                  
   926                                  
   927                                  %if _LZO
   928                                  	%include "lzo.asm"
   929                                  %endif
   930                                  
   931                                  
   932                                  %if _LZSA2
   933                                  	%include "lzsa2.asm"
   934                                  %endif
   935                                  
   936                                  
   937                                  %if _APL
   938                                  	%include "apl.asm"
   939                                  %endif
   940                                  
   941                                  
   942                                  %if _BZP
   943                                  	%include "bzp.asm"
   944                                  %endif
   945                                  
   946                                  
   947                                  %if _ALLOW_OVERLAPPING
   948                                  		; INP:	?src, ?dst
   949                                  		; OUT:	CY if error (?src < ?dst)
   950                                  		;	NC if success
   951                                  		; CHG:	ax, bx, cx, dx
   952                                  check_pointers_not_overlapping:
   953                                  %if CHECK_POINTERS_VARIABLE_DST
   954 000008D9 FF76D8                  	 push word [bp + ?dst + 2]
   955 000008DC FF76D6                  	 push word [bp + ?dst]
   956                                  %else
   957                                  	 push es
   958                                  	 push di
   959                                  %endif
   960 000008DF E86F00                  	call pointer_to_linear
   961                                  
   962 000008E2 91                      	xchg cx, ax
   963 000008E3 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
   964                                  
   965                                  %if CHECK_POINTERS_VARIABLE_SRC
   966 000008E5 FF76EC                  	 push word [bp + ?src + 2]
   967 000008E8 FF76EA                  	 push word [bp + ?src]
   968                                  %else
   969                                  	 push ds
   970                                  	 push si
   971                                  %endif
   972 000008EB E86300                  	call pointer_to_linear		; dx:ax = linear ?src before next read
   973                                  
   974 000008EE 39DA                    	cmp dx, bx			; ?src >= ?dst ?
   975 000008F0 7704                    	ja @F
   976 000008F2 7202                    	jb .ret				; (CY)
   977 000008F4 39C8                    	cmp ax, cx
   978                                  	; jb .ret			; (CY)
   979                                  					; (NC) yes, no error
   980                                  @@:
   981                                  .ret:
   982 000008F6 C3                      	retn
   983                                  %endif
   984                                  
   985                                  	; This leaves the lframe context created within the
   986                                  	;  specific depacker's file. The above function
   987                                  	;  check_pointers_not_overlapping uses the frame.
   988                                  	lleave ctx
   989                                  
   990                                  
   991                                  		; INP:	ds:si = pointer
   992                                  		;	es:di = pointer
   993                                  		; OUT:	ds:si normalised
   994                                  		;	es:di normalised
   995                                  normalise_both_pointers:
   996 000008F7 06                      	 push es
   997 000008F8 57                      	 push di
   998 000008F9 E80A00                  	call normalise_pointer
   999 000008FC 5F                      	 pop di
  1000 000008FD 07                      	 pop es
  1001                                  
  1002                                  normalise_dssi_pointer:
  1003 000008FE 1E                      	 push ds
  1004 000008FF 56                      	 push si
  1005 00000900 E80300                  	call normalise_pointer
  1006 00000903 5E                      	 pop si
  1007 00000904 1F                      	 pop ds
  1008 00000905 C3                      	retn
  1009                                  
  1010                                  
  1011                                  		; INP:	word [ss:sp + 2] = segment
  1012                                  		;	word [ss:sp] = offset
  1013                                  		;
  1014                                  		; Note:	Does not work correctly with pointers that point to
  1015                                  		;	 a HMA location. Do not use then!
  1016                                  normalise_pointer:
  1017                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1018                                  	lframe near
  1019                                  	lpar word,	segment
  1020                                  	lpar word,	offset
  1021                                  	lpar_return
  1022 00000906 5589E5                  	lenter
  1023 00000909 53                      	push bx
  1024 0000090A 51                      	push cx
  1025                                  
  1026 0000090B 31DB                    	xor bx, bx
  1027 0000090D 31C9                    	xor cx, cx
  1028 0000090F FF7606                  	 push word [bp + ?segment]
  1029 00000912 FF7604                  	 push word [bp + ?offset]
  1030 00000915 E80A00                  	call normalise_pointer_with_displacement_bxcx
  1031 00000918 8F4604                  	 pop word [bp + ?offset]
  1032 0000091B 8F4606                  	 pop word [bp + ?segment]
  1033                                  
  1034 0000091E 59                      	pop cx
  1035 0000091F 5B                      	pop bx
  1036 00000920 5D                      	lleave
  1037 00000921 C3                      	lret
  1038                                  
  1039                                  
  1040                                  		; INP:	word [ss:sp + 2] = segment
  1041                                  		;	word [ss:sp] = offset
  1042                                  		;	bx:cx = add/sub displacement
  1043                                  		; OUT:	CY if the displacement carries
  1044                                  		;	NC if not
  1045                                  normalise_pointer_with_displacement_bxcx:
  1046                                  %endif
  1047                                  	lframe near
  1048                                  	lpar word,	segment
  1049                                  	lpar word,	offset
  1050                                  	lpar_return
  1051 00000922 5589E5                  	lenter
  1052 00000925 50                      	push ax
  1053 00000926 51                      	push cx
  1054 00000927 52                      	push dx
  1055                                  
  1056 00000928 FF7606                  	 push word [bp + ?segment]
  1057 0000092B FF7604                  	 push word [bp + ?offset]
  1058 0000092E E82000                  	call pointer_to_linear
  1059                                  
  1060                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1061                                  	; push bx
  1062                                  	; 				; sign-extend cx into bx:cx
  1063                                  	; cmp cx, 8000h			; CY if < 8000h (NC if negative)
  1064                                  	; cmc				; NC if positive
  1065                                  	; sbb bx, bx			; 0 if was NC, -1 if was CY
  1066                                  
  1067 00000931 01C1                    	add cx, ax
  1068 00000933 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1069                                  	; pop bx
  1070 00000935 9F                      	lahf				; ah = flags
  1071                                  %else
  1072                                  	xchg ax, cx
  1073                                  %endif
  1074                                  
  1075                                  %if 0
  1076                                  		; Adds in HMA support for this function. Not currently used.
  1077                                  	cmp dx, 10h			; dx:ax >= 10_0000h ?
  1078                                  	jb @F				; no, linear-to-pointer normally -->
  1079                                  	; ja .error
  1080                                  
  1081                                  	add cx, 10h
  1082                                  	; jc .error
  1083                                  	mov word [bp + ?offset], cx
  1084                                  	or word [bp + ?segment], -1
  1085                                  	jmp .return
  1086                                  @@:
  1087                                  %endif
  1088                                  
  1089 00000936 53                      	push bx
  1090 00000937 89CB                    	mov bx, cx
  1091 00000939 83E10F                  	and cx, 15
  1092 0000093C 894E04                  	mov word [bp + ?offset], cx
  1093                                  
  1094 0000093F B104                    	mov cl, 4
  1095                                  @@:
  1096 00000941 D1EA                    	shr dx, 1
  1097 00000943 D1DB                    	rcr bx, 1
  1098 00000945 E2FA                    	loop @B
  1099                                  
  1100 00000947 895E06                  	mov word [bp + ?segment], bx
  1101 0000094A 5B                      	pop bx
  1102                                  
  1103                                  	; test dx, dx
  1104                                  	; jnz .error
  1105                                  
  1106                                  .return:
  1107                                  
  1108                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1109 0000094B 9E                      	sahf				; restore flags from ah
  1110                                  %endif
  1111 0000094C 5A                      	pop dx
  1112 0000094D 59                      	pop cx
  1113 0000094E 58                      	pop ax
  1114 0000094F 5D                      	lleave
  1115 00000950 C3                      	lret
  1116                                  
  1117                                  
  1118                                  		; INP:	word [ss:sp + 2] = segment
  1119                                  		;	word [ss:sp] = offset
  1120                                  		; OUT:	dx:ax = linear address
  1121                                  pointer_to_linear:
  1122                                  	lframe near
  1123                                  	lpar word,	segment
  1124                                  	lpar word,	offset
  1125 00000951 5589E5                  	lenter
  1126                                  
  1127 00000954 8B4606                  	mov ax, word [bp + ?segment]
  1128 00000957 31D2                    	xor dx, dx
  1129 00000959 51                      	push cx
  1130 0000095A B90400                  	mov cx, 4
  1131                                  @@:
  1132 0000095D D1E0                    	shl ax, 1
  1133 0000095F D1D2                    	rcl dx, 1
  1134 00000961 E2FA                    	loop @B
  1135                                  
  1136 00000963 034604                  	add ax, word [bp + ?offset]
  1137 00000966 11CA                    	adc dx, cx			; cx = 0 here
  1138 00000968 59                      	pop cx
  1139                                  
  1140 00000969 5D                      	lleave
  1141 0000096A C20400                  	lret
  1142                                  
  1143                                  
  1144 0000096D 90<rep 3h>              	align 16
  1145                                  init1_end:
  1146                                  
  1147                                  
  1148                                  	section INIT0
  1149                                  %if _TEST_PROGRAM
  1150                                  init0_msg:
  1151 00000114 4572726F723A204E6F-     .error_stderr:	db "Error: Not enough memory allocated.",13,10
  1151 0000011D 7420656E6F75676820-
  1151 00000126 6D656D6F727920616C-
  1151 0000012F 6C6F63617465642E0D-
  1151 00000138 0A                 
  1152                                  .error_stderr.length: equ $ - .error_stderr
  1153 00000139 39373532                .error_stdout:	_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  1158 0000013D 0D0A                    		db 13,10
  1159                                  .error_stdout.length: equ $ - .error_stdout
  1160                                  
  1161 0000013F 90<rep C1h>             	align 512
  1162                                  %if ($ - $$) != 512
  1163                                   %error Wrong INIT0 size
  1164                                  %endif
  1165                                  %endif
  1166                                  
  1167                                  	align 16
  1168                                  init0_end:
  1169                                  
  1170                                  
  1171                                  %assign num (init1_end - init1_start) + (init0_end - init0_start)
  1172                                  %if _BRIEFLZ
  1173                                  %define which iniblz
  1174                                  %elif _LZ4
  1175                                  %define which inilz4
  1176                                  %elif _SNAPPY
  1177                                  %define which inisz
  1178                                  %elif _EXODECR
  1179                                  %define which iniexo
  1180                                  %elif _X
  1181                                  %define which inix
  1182                                  %elif _HEATSHRINK
  1183                                  %define which inihs
  1184                                  %elif _LZD
  1185                                  %define which inilz
  1186                                  %elif _LZO
  1187                                  %define which inilzo
  1188                                  %elif _LZSA2
  1189                                  %define which inilzsa2
  1190                                  %elif _APL
  1191                                  %define which iniapl
  1192                                  %elif _BZP
  1193                                  %define which inibzp
  1194                                  %endif
  1195                                  %warning which: num bytes used for depacker
  1195          ******************       warning: inilz: 2928 bytes used for depacker [-w+user]
  1196                                  
  1197                                  
  1198                                  %if _TEST_PROGRAM
  1199                                  	section INIT2 align=16 follows=INIT1 vstart=0
  1200                                  init2_start:
  1201                                  		; si => after PSP
  1202                                  		; cs => INIT2
  1203                                  		; psp, free, payload, init1, init2, payload space, stack
  1204                                  		;
  1205                                  		; The correct allocation for the test program
  1206                                  		;  is image size (init0, payload, init1, init2)
  1207                                  		;  minus init0 plus compressed payload size
  1208                                  		;  plus decompressed size plus stack. For
  1209                                  		;  simplicity, init0 subtraction may be skipped.
  1210 00000000 8CCA                    	mov dx, cs
  1211 00000002 81C2F417                	add dx, (init2_end - init2_start) >> 4
  1212                                  				; => payload saving area
  1213 00000006 8CC8                    	mov ax, cs
  1214 00000008 2D540E                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  1217 0000000B B9BD0D                  	mov cx, (payload_end - payload) >> 4
  1218 0000000E E84602                  	call init2_movp		; copy payload to payload saving area
  1219                                  		; We save away the payload here because a failure
  1220                                  		;  to decompress generally overwrites part of that
  1221                                  		;  payload which was used as source.
  1222                                  
  1223 00000011 89C2                    	mov dx, ax		; dx => payload source to use
  1224 00000013 8CC8                    	mov ax, cs
  1225 00000015 2D9700                  	sub ax, (init1_end - init1_start) >> 4
  1226                                  				; ax => INIT1
  1227 00000018 BB0100                  	mov bx, 1		; say we're in EXE mode
  1228 0000001B 52                      	push dx
  1229 0000001C 50                      	push ax
  1230 0000001D 56                      	push si			; si => target
  1231 0000001E 0E                      	push cs
  1232 0000001F E8C700                  	call .transfer		; call decompression
  1233 00000022 5E                      	pop si
  1234 00000023 58                      	pop ax
  1235 00000024 5A                      	pop dx
  1236                                  		; Returns here after decompression.
  1237                                  		; CY if error.
  1238 00000025 7309                    	jnc @F
  1239                                  
  1240 00000027 BA[A201]                	mov dx, init2_msg.initial_error
  1241 0000002A B93C00                  	mov cx, init2_msg.initial_error.length
  1242 0000002D E9F800                  	jmp init2_error
  1243                                  
  1244                                  @@:
  1245                                  	numdef INCLUDE_UNCOMPRESSED
  1246                                  	numdef WRITE_WRONG_FILE
  1247                                  %if _INCLUDE_UNCOMPRESSED
  1248                                  payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed
  1249                                  
  1250 00000030 E8BC00                  	call checkdecompressed
  1251 00000033 7409                    	je @F
  1252                                  
  1253                                  %if _WRITE_WRONG_FILE
  1254                                  	call writefiles
  1255                                  %endif
  1256                                  
  1257                                  %if _DEBUG0
  1258                                  	mov bx, -1
  1259                                  %endif
  1260 00000035 BA[DE01]                	mov dx, init2_msg.initial_error_2
  1261 00000038 B93C00                  	mov cx, init2_msg.initial_error_2.length
  1262 0000003B E9EA00                  	jmp init2_error
  1263                                  
  1264                                  @@:
  1265                                  %endif
  1266                                  
  1267                                  	lframe
  1268 0000003E 5589E5                  	lenter
  1269                                  	lvar word,	upperbound
  1270 00000041 52                      	 push dx
  1271                                  	lvar word,	lowerbound
  1272 00000042 56                      	 push si
  1273                                  	lvar word,	current_init1
  1274 00000043 50                      	 push ax
  1275                                  
  1276                                  %if _TEST_PROGRESS
  1277 00000044 BA[9701]                	mov dx, init2_msg.progress.1
  1278 00000047 B90700                  	mov cx, init2_msg.progress.1.length
  1279                                  .loop:
  1280 0000004A 0E                      	push cs
  1281 0000004B 1F                      	pop ds
  1282 0000004C BB0200                  	mov bx, 2
  1283 0000004F B440                    	mov ah, 40h
  1284 00000051 CD21                    	int 21h
  1285                                  %else
  1286                                  .loop:
  1287                                  %endif
  1288                                  
  1289 00000053 8B56FE                  	mov dx, [bp + ?upperbound]
  1290 00000056 2B56FC                  	sub dx, [bp + ?lowerbound]
  1291 00000059 7465                    	jz .found
  1292 0000005B D1EA                    	shr dx, 1
  1293                                  		; Rounding down, so that we never retry upper bound.
  1294                                  		;  The upper bound is known to be working.
  1295 0000005D 0356FC                  	add dx, [bp + ?lowerbound]
  1296 00000060 52                      	push dx
  1297 00000061 81C2BD0D                	add dx, (payload_end - payload) >> 4
  1298 00000065 8B46FA                  	mov ax, [bp + ?current_init1]
  1299 00000068 B99700                  	mov cx, (init1_end - init1_start) >> 4
  1300 0000006B E8E901                  	call init2_movp
  1301 0000006E 8956FA                  	mov [bp + ?current_init1], dx
  1302 00000071 5A                      	pop dx
  1303                                  
  1304 00000072 8CC8                    	mov ax, cs
  1305 00000074 05F417                  	add ax, (init2_end - init2_start) >> 4
  1306                                  				; => payload in saving area
  1307 00000077 B9BD0D                  	mov cx, (payload_end - payload) >> 4
  1308 0000007A E8DA01                  	call init2_movp		; copy payload from payload saving area
  1309                                  
  1310                                  		; dx => source
  1311 0000007D 8B46FA                  	mov ax, [bp + ?current_init1]
  1312 00000080 BB0100                  	mov bx, 1
  1313 00000083 52                      	push dx
  1314 00000084 56                      	push si
  1315 00000085 0E                      	push cs
  1316 00000086 E86000                  	call .transfer
  1317 00000089 5E                      	pop si
  1318 0000008A 5A                      	pop dx
  1319                                  		; Returns here after decompression.
  1320                                  		; CY if error.
  1321 0000008B 730C                    	jnc @F
  1322                                  		; error: this attempt is one below the new lower bound
  1323 0000008D 42                      	inc dx
  1324 0000008E 8956FC                  	mov word [bp + ?lowerbound], dx
  1325                                  %if _TEST_PROGRESS
  1326 00000091 BA[9E01]                	mov dx, init2_msg.progress.fail
  1327 00000094 B90100                  	mov cx, init2_msg.progress.fail.length
  1328                                  %endif
  1329 00000097 EBB1                    	jmp .loop
  1330                                  
  1331                                  @@:
  1332                                  %if _INCLUDE_UNCOMPRESSED
  1333 00000099 E85300                  	call checkdecompressed
  1334 0000009C 7417                    	je @F
  1335                                  
  1336                                  %if _WRITE_WRONG_FILE
  1337                                  	call writefiles
  1338                                  %endif
  1339                                  
  1340                                  %if _TEST_PROGRESS
  1341 0000009E 0E                      	push cs
  1342 0000009F 1F                      	pop ds
  1343 000000A0 BA[A001]                	mov dx, init2_msg.progress.linebreak
  1344 000000A3 B90200                  	mov cx, init2_msg.progress.linebreak.length
  1345 000000A6 BB0200                  	mov bx, 2
  1346 000000A9 B440                    	mov ah, 40h
  1347 000000AB CD21                    	int 21h
  1348                                  %endif
  1349                                  %if _DEBUG0
  1350                                  	mov bx, -2
  1351                                  %endif
  1352 000000AD BA[1A02]                	mov dx, init2_msg.subsequent_error_2
  1353 000000B0 B93700                  	mov cx, init2_msg.subsequent_error_2.length
  1354 000000B3 EB73                    	jmp init2_error
  1355                                  
  1356                                  @@:
  1357                                  %endif
  1358                                  		; success: this attempt is the new upper bound
  1359 000000B5 8956FE                  	mov word [bp + ?upperbound], dx
  1360                                  %if _TEST_PROGRESS
  1361 000000B8 BA[9F01]                	mov dx, init2_msg.progress.success
  1362 000000BB B90100                  	mov cx, init2_msg.progress.success.length
  1363                                  %endif
  1364 000000BE EB8A                    	jmp .loop
  1365                                  
  1366                                  .found:
  1367                                  %if _TEST_PROGRESS
  1368 000000C0 0E                      	push cs
  1369 000000C1 1F                      	pop ds
  1370 000000C2 BA[A001]                	mov dx, init2_msg.progress.linebreak
  1371 000000C5 B90200                  	mov cx, init2_msg.progress.linebreak.length
  1372 000000C8 BB0200                  	mov bx, 2
  1373 000000CB B440                    	mov ah, 40h
  1374 000000CD CD21                    	int 21h
  1375                                  %endif
  1376 000000CF 8B46FE                  	mov ax, word [bp + ?upperbound]
  1377 000000D2 29F0                    	sub ax, si		; = how many paragraphs in buffer before source
  1378 000000D4 05540E                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  1380                                  				; = how many paragraphs needed for process
  1381 000000D7 E87400                  	call init2_disp_ax_dec
  1382 000000DA B00D                    	mov al, 13
  1383 000000DC E86400                  	call init2_disp_al
  1384 000000DF B00A                    	mov al, 10
  1385 000000E1 E85F00                  	call init2_disp_al
  1386 000000E4 B8004C                  	mov ax, 4C00h
  1387 000000E7 CD21                    	int 21h
  1388                                  
  1389                                  	lleave ctx
  1390                                  
  1391                                  
  1392                                  .transfer:
  1393 000000E9 31FF                    	xor di, di
  1394 000000EB 57                      	push di			; dummy ax value on stack
  1395 000000EC 50                      	push ax			; INIT1 segment
  1396 000000ED 57                      	push di			; zero = init1_start
  1397 000000EE CB                      	retf
  1398                                  
  1399                                  
  1400                                  
  1401                                  %if _INCLUDE_UNCOMPRESSED
  1402                                  
  1403                                  
  1404                                  %if _WRITE_WRONG_FILE
  1405                                  writefiles:
  1406                                  	push cs
  1407                                  	pop ds
  1408                                  	mov dx, init2_msg.wrong_file_name
  1409                                  	xor cx, cx
  1410                                  	mov ah, 3Ch
  1411                                  	int 21h
  1412                                  	jc .notfile
  1413                                  
  1414                                  	mov bx, ax
  1415                                  	mov cx, payload_uncompressed_size >> 4
  1416                                  	xor dx, dx
  1417                                  .loopfile:
  1418                                  	mov ds, si
  1419                                  	mov ah, 40h
  1420                                  	push cx
  1421                                  	mov cx, 16
  1422                                  	int 21h
  1423                                  	pop cx
  1424                                  	inc si
  1425                                  	loop .loopfile
  1426                                  
  1427                                  	mov ds, si
  1428                                  	mov cx, payload_uncompressed_size & 15
  1429                                  	mov ah, 40h
  1430                                  	int 21h
  1431                                  
  1432                                  	mov ah, 3Eh
  1433                                  	int 21h
  1434                                  
  1435                                  .notfile:
  1436                                  
  1437                                  	push cs
  1438                                  	pop ds
  1439                                  	mov dx, init2_msg.wrong_file_name2
  1440                                  	xor cx, cx
  1441                                  	mov ah, 3Ch
  1442                                  	int 21h
  1443                                  	jc .notfile2
  1444                                  
  1445                                  	mov bx, ax
  1446                                  	mov cx, payload_uncompressed_size >> 4
  1447                                  	mov si, cs
  1448                                  	add si, (payload_uncompressed - init2_start) >> 4
  1449                                  	xor dx, dx
  1450                                  .loopfile2:
  1451                                  	mov ds, si
  1452                                  	mov ah, 40h
  1453                                  	push cx
  1454                                  	mov cx, 16
  1455                                  	int 21h
  1456                                  	pop cx
  1457                                  	inc si
  1458                                  	loop .loopfile2
  1459                                  
  1460                                  	mov ds, si
  1461                                  	mov cx, payload_uncompressed_size & 15
  1462                                  	mov ah, 40h
  1463                                  	int 21h
  1464                                  
  1465                                  	mov ah, 3Eh
  1466                                  	int 21h
  1467                                  
  1468                                  .notfile2:
  1469                                  	retn
  1470                                  %endif
  1471                                  
  1472                                  		; INP:	si => decompressed image
  1473                                  		; OUT:	ZR if matching
  1474                                  		;	NZ if mismatching
  1475                                  		; CHG:	es, ds, di, bx, cx
  1476                                  		; STT:	UP
  1477                                  checkdecompressed:
  1478 000000EF 50                      	push ax
  1479 000000F0 52                      	push dx
  1480 000000F1 56                      	push si
  1481                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  1482                                  	mov cx, _PAYLOAD_KERNEL_MAX_PARAS
  1483                                  	mov bx, 0
  1484                                  %else
  1485 000000F2 B9C417                  	mov cx, payload_uncompressed_size >> 4
  1486 000000F5 BB0000                  	mov bx, payload_uncompressed_size & 15
  1487                                  %endif
  1488 000000F8 8CCF                    	mov di, cs
  1489 000000FA 83C72F                  	add di, (payload_uncompressed - init2_start) >> 4
  1490 000000FD E319                    	jcxz .end
  1491                                  .loop:
  1492 000000FF 51                      	push cx
  1493 00000100 B90800                  	mov cx, 8
  1494 00000103 8EDE                    	mov ds, si
  1495 00000105 8EC7                    	mov es, di
  1496 00000107 46                      	inc si
  1497 00000108 47                      	inc di
  1498 00000109 56                      	push si
  1499 0000010A 57                      	push di
  1500 0000010B 31F6                    	xor si, si
  1501 0000010D 31FF                    	xor di, di
  1502 0000010F F3A7                    	repe cmpsw
  1503 00000111 5F                      	pop di
  1504 00000112 5E                      	pop si
  1505 00000113 59                      	pop cx
  1506 00000114 750E                    	jne .ret
  1507 00000116 E2E7                    	loop .loop
  1508                                  .end:
  1509 00000118 8EDE                    	mov ds, si
  1510 0000011A 8EC7                    	mov es, di
  1511 0000011C 31F6                    	xor si, si
  1512 0000011E 31FF                    	xor di, di		; (ZR)
  1513 00000120 89D9                    	mov cx, bx
  1514 00000122 F3A6                    	repe cmpsb
  1515                                  .ret:
  1516 00000124 5E                      	pop si
  1517 00000125 5A                      	pop dx
  1518 00000126 58                      	pop ax
  1519 00000127 C3                      	retn
  1520                                  %endif
  1521                                  
  1522                                  
  1523                                  init2_error:
  1524                                  %if _DEBUG0
  1525                                  	push bx
  1526                                  %endif
  1527 00000128 0E                      	push cs
  1528 00000129 1F                      	pop ds
  1529 0000012A BB0200                  	mov bx, 2
  1530 0000012D B440                    	mov ah, 40h
  1531 0000012F CD21                    	int 21h
  1532                                  
  1533                                  %if _DEBUG0
  1534                                  	mov dx, init2_msg.rc
  1535                                  	mov cx, init2_msg.rc.length
  1536                                  	mov bx, 2
  1537                                  	mov ah, 40h
  1538                                  	int 21h
  1539                                  	pop ax
  1540                                  	call init2_error_disp_ax_hex
  1541                                  	mov dx, init2_msg.linebreak
  1542                                  	mov cx, init2_msg.linebreak.length
  1543                                  	mov bx, 2
  1544                                  	mov ah, 40h
  1545                                  	int 21h
  1546                                  %endif
  1547                                  
  1548 00000131 BA[5102]                	mov dx, init2_msg.error_stdout
  1549 00000134 B90600                  	mov cx, init2_msg.error_stdout.length
  1550 00000137 BB0100                  	mov bx, 1
  1551 0000013A B440                    	mov ah, 40h
  1552 0000013C CD21                    	int 21h
  1553                                  
  1554 0000013E B8FF4C                  	mov ax, 4CFFh
  1555 00000141 CD21                    	int 21h
  1556                                  
  1557                                  
  1558                                  %if _DEBUG0
  1559                                  init2_error_disp_ax_hex:	; ax
  1560                                  		xchg al,ah
  1561                                  		call init2_error_disp_al_hex	; display former ah
  1562                                  		xchg al,ah			;  and fall trough for al
  1563                                  init2_error_disp_al_hex:	; al
  1564                                  		push cx
  1565                                  		mov cl,4
  1566                                  		ror al,cl
  1567                                  		call init2_error_disp_al_lownibble_hex
  1568                                  						; display former high-nibble
  1569                                  		rol al,cl
  1570                                  		pop cx
  1571                                  						;  and fall trough for low-nibble
  1572                                  init2_error_disp_al_lownibble_hex:
  1573                                  		push ax			 ; save ax for call return
  1574                                  		and al,00001111b		; high nibble must be zero
  1575                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1576                                  		cmp al,'9'
  1577                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1578                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1579                                   .decimalnum:
  1580                                  		call init2_error_disp_al
  1581                                  		pop ax
  1582                                  		retn
  1583                                  
  1584                                  
  1585                                  init2_error_disp_al:
  1586                                  	push dx
  1587                                  	push cx
  1588                                  	push bx
  1589                                  	push ax
  1590                                  	mov dx, sp
  1591                                  	push ds
  1592                                  	 push ss
  1593                                  	 pop ds
  1594                                  	mov cx, 1
  1595                                  	mov bx, 2
  1596                                  	mov ah, 40h
  1597                                  	int 21h
  1598                                  	pop ds
  1599                                  	pop ax
  1600                                  	pop bx
  1601                                  	pop cx
  1602                                  	pop dx
  1603                                  	retn
  1604                                  %endif
  1605                                  
  1606                                  
  1607                                  init2_disp_al:
  1608 00000143 52                      	push dx
  1609 00000144 50                      	push ax
  1610 00000145 88C2                    	mov dl, al
  1611 00000147 B402                    	mov ah, 2
  1612 00000149 CD21                    	int 21h
  1613 0000014B 58                      	pop ax
  1614 0000014C 5A                      	pop dx
  1615 0000014D C3                      	retn
  1616                                  
  1617                                  
  1618                                  		; Display number in ax decimal
  1619                                  		;
  1620                                  		; INP:	ax = number
  1621                                  		; OUT:	displayed using Int21.02
  1622                                  		; CHG:	none
  1623                                  init2_disp_ax_dec:			; ax (no leading zeros)
  1624 0000014E 53                      		push bx
  1625 0000014F 31DB                    		xor bx, bx
  1626                                  .pushax:
  1627 00000151 52                      		push dx
  1628 00000152 50                      		push ax
  1629 00000153 08DB                    		or bl, bl
  1630 00000155 7405                    		jz .nobl
  1631 00000157 80EB05                  		sub bl, 5
  1632 0000015A F6DB                    		neg bl
  1633                                  .nobl:
  1634 0000015C 51                      		push cx
  1635 0000015D B91027                  		mov cx, 10000
  1636 00000160 E81B00                  		call .divide_out
  1637 00000163 B9E803                  		mov cx, 1000
  1638 00000166 E81500                  		call .divide_out
  1639 00000169 B96400                  		mov cx, 100
  1640 0000016C E80F00                  		call .divide_out
  1641 0000016F B10A                    		mov cl, 10
  1642 00000171 E80A00                  		call .divide_out
  1643                                  							; (Divisor 1 is useless)
  1644 00000174 0430                    		add al, '0'
  1645 00000176 E8CAFF                  		call init2_disp_al
  1646 00000179 59                      		pop cx
  1647 0000017A 58                      		pop ax
  1648 0000017B 5A                      		pop dx
  1649 0000017C 5B                      		pop bx					; Caller's register
  1650 0000017D C3                      		retn
  1651                                  
  1652                                  
  1653                                  		; INP:	ax = number
  1654                                  		;	cx = divisor
  1655                                  		; OUT:	ax = remainder of operation
  1656                                  		;	result displayed
  1657                                  .divide_out:
  1658 0000017E 52                      		push dx
  1659 0000017F 31D2                    		xor dx, dx
  1660 00000181 F7F1                    		div cx				; 0:ax / cx
  1661 00000183 52                      		push dx				; remainder
  1662 00000184 FECB                    		dec bl
  1663 00000186 7503                    		jnz .nobl2
  1664 00000188 80CF01                  		or bh, 1
  1665                                  .nobl2:
  1666 0000018B 08C7                    		or bh, al
  1667 0000018D 7405                    		jz .leadingzero
  1668 0000018F 0430                    		add al, '0'
  1669 00000191 E8AFFF                  		call init2_disp_al		; display result
  1670                                   .leadingzero:
  1671 00000194 58                      		pop ax				; remainder
  1672 00000195 5A                      		pop dx
  1673 00000196 C3                      		retn
  1674                                  
  1675                                  
  1676                                  init2_msg:
  1677                                  %if _TEST_PROGRESS
  1678 00000197 496E666F3A2031          .progress.1:		db "Info: 1"
  1679                                  .progress.1.length: equ $ - .progress.1
  1680 0000019E 46                      .progress.fail:		db "F"
  1681                                  .progress.fail.length: equ $ - .progress.fail
  1682 0000019F 53                      .progress.success:	db "S"
  1683                                  .progress.success.length: equ $ - .progress.success
  1684 000001A0 0D0A                    .progress.linebreak:	db 13,10
  1685                                  .progress.linebreak.length: equ $ - .progress.linebreak
  1686                                  %endif
  1687                                  %if _WRITE_WRONG_FILE
  1688                                  .wrong_file_name:	asciz "WRONG.BIN"
  1689                                  .wrong_file_name2:	asciz "WRONG2.BIN"
  1690                                  %endif
  1691 000001A2 4572726F723A205465-     .initial_error:	db "Error: Test program failed to decompress with full buffer."
  1691 000001AB 73742070726F677261-
  1691 000001B4 6D206661696C656420-
  1691 000001BD 746F206465636F6D70-
  1691 000001C6 726573732077697468-
  1691 000001CF 2066756C6C20627566-
  1691 000001D8 6665722E           
  1692 000001DC 0D0A                    .linebreak:	db 13,10
  1693                                  .initial_error.length: equ $ - .initial_error
  1694                                  .linebreak.length: equ $ - .linebreak
  1695                                  %if _DEBUG0
  1696                                  .rc:	db "Error: Failure code="
  1697                                  .rc.length: equ $ - .rc
  1698                                  %endif
  1699                                  %if _INCLUDE_UNCOMPRESSED
  1700 000001DE 4572726F723A205465-     .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  1700 000001E7 73742070726F677261-
  1700 000001F0 6D206465636F6D7072-
  1700 000001F9 65737365642077726F-
  1700 00000202 6E676C792077697468-
  1700 0000020B 2066756C6C20627566-
  1700 00000214 6665722E0D0A       
  1701                                  .initial_error_2.length: equ $ - .initial_error_2
  1702 0000021A 4572726F723A205465-     .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  1702 00000223 73742070726F677261-
  1702 0000022C 6D206465636F6D7072-
  1702 00000235 65737365642077726F-
  1702 0000023E 6E676C792064757269-
  1702 00000247 6E6720746573742E0D-
  1702 00000250 0A                 
  1703                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  1704                                  %endif
  1705 00000251 39373532                .error_stdout:	_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  1710 00000255 0D0A                    		db 13,10
  1711                                  .error_stdout.length: equ $ - .error_stdout
  1712                                  
  1713                                  
  1714                                  		; Move paragraphs
  1715                                  		;
  1716                                  		; INP:	ax => source
  1717                                  		;	dx => destination
  1718                                  		;	cx = number of paragraphs
  1719                                  		; CHG:	-
  1720                                  		; OUT:	ax and dx unchanged
  1721                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  1722                                  		;	Do not provide a wrapped/HMA source or destination!
  1723                                  init2_movp:
  1724 00000257 51                      	push cx
  1725 00000258 1E                      	push ds
  1726 00000259 56                      	push si
  1727 0000025A 06                      	push es
  1728 0000025B 57                      	push di
  1729                                  
  1730 0000025C 39D0                    	cmp ax, dx		; source above destination ?
  1731 0000025E 770A                    	ja .up			; yes, move up (forwards) -->
  1732 00000260 747B                    	je .return		; same, no need to move -->
  1733 00000262 50                      	push ax
  1734 00000263 01C8                    	add ax, cx		; (expected not to carry)
  1735 00000265 39D0                    	cmp ax, dx		; end of source is above destination ?
  1736 00000267 58                      	pop ax
  1737 00000268 7730                    	ja .down		; yes, move from top down -->
  1738                                  	; Here, the end of source is below-or-equal the destination,
  1739                                  	;  so they do not overlap. In this case we prefer moving up.
  1740                                  
  1741                                  .up:
  1742 0000026A 50                      	push ax
  1743 0000026B 52                      	push dx
  1744                                  .uploop:
  1745 0000026C 8ED8                    	mov ds, ax
  1746 0000026E 8EC2                    	mov es, dx
  1747 00000270 31FF                    	xor di, di
  1748 00000272 31F6                    	xor si, si		; -> start of segment
  1749 00000274 81E90010                	sub cx, 1000h		; 64 KiB left ?
  1750 00000278 7610                    	jbe .uplast		; no -->
  1751 0000027A 51                      	push cx
  1752 0000027B B90080                  	mov cx, 10000h /2
  1753 0000027E F3A5                    	rep movsw		; move 64 KiB
  1754 00000280 59                      	pop cx
  1755 00000281 050010                  	add ax, 1000h
  1756 00000284 81C20010                	add dx, 1000h		; -> next segment
  1757 00000288 EBE2                    	jmp short .uploop	; proceed for more -->
  1758                                  .uplast:
  1759 0000028A 81C10010                	add cx, 1000h		; restore counter
  1760 0000028E D1E1                    	shl cx, 1
  1761 00000290 D1E1                    	shl cx, 1
  1762 00000292 D1E1                    	shl cx, 1		; *8, paragraphs to words
  1763 00000294 F3A5                    	rep movsw		; move last part
  1764 00000296 5A                      	pop dx
  1765 00000297 58                      	pop ax
  1766 00000298 EB43                    	jmp short .return
  1767                                  
  1768                                  .down:
  1769 0000029A FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
  1770                                  .dnloop:
  1771 0000029B 81E90010                	sub cx, 1000h		; 64 KiB left ?
  1772 0000029F 761A                    	jbe .dnlast		; no -->
  1773 000002A1 50                      	push ax
  1774 000002A2 52                      	push dx
  1775 000002A3 01C8                    	add ax, cx
  1776 000002A5 01CA                    	add dx, cx
  1777 000002A7 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
  1778 000002A9 8EC2                    	mov es, dx
  1779 000002AB 5A                      	pop dx
  1780 000002AC 58                      	pop ax
  1781 000002AD BFFEFF                  	mov di, -2
  1782 000002B0 89FE                    	mov si, di		; moved from last word down
  1783 000002B2 51                      	push cx
  1784 000002B3 B90080                  	mov cx, 10000h /2
  1785 000002B6 F3A5                    	rep movsw		; move 64 KiB
  1786 000002B8 59                      	pop cx
  1787 000002B9 EBE0                    	jmp short .dnloop	; proceed for more -->
  1788                                  .dnlast:
  1789 000002BB 81C10010                	add cx, 1000h		; restore counter
  1790 000002BF D1E1                    	shl cx, 1
  1791 000002C1 D1E1                    	shl cx, 1
  1792 000002C3 D1E1                    	shl cx, 1		; *8, paragraphs to words
  1793 000002C5 89CF                    	mov di, cx
  1794 000002C7 4F                      	dec di
  1795 000002C8 D1E7                    	shl di, 1		; words to offset, -> last word
  1796 000002CA 89FE                    	mov si, di
  1797 000002CC 8ED8                    	mov ds, ax
  1798 000002CE 8EC2                    	mov es, dx		; first segment correct
  1799                                  
  1800                                  		; Refer to comment in init0_movp.
  1801                                  %if _AMD_ERRATUM_109_WORKAROUND
  1802 000002D0 E308                    	jcxz @FF
  1803 000002D2 83F914                  	cmp cx, 20
  1804 000002D5 7703                    	ja @FF
  1805                                  @@:
  1806 000002D7 A5                      	movsw
  1807 000002D8 E2FD                    	loop @B
  1808                                  @@:
  1809                                  %endif
  1810 000002DA F3A5                    	rep movsw		; move first part
  1811 000002DC FC                      	cld
  1812                                  .return:
  1813 000002DD 5F                      	pop di
  1814 000002DE 07                      	pop es
  1815 000002DF 5E                      	pop si
  1816 000002E0 1F                      	pop ds
  1817 000002E1 59                      	pop cx
  1818 000002E2 C3                      	retn
  1819                                  
  1820                                  
  1821 000002E3 90<rep Dh>              	align 16
  1822                                  
  1823                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  1824                                  %if _INCLUDE_UNCOMPRESSED
  1825                                  payload_uncompressed:
  1826 000002F0 <bin 17C40h>            	incbin _UNCOMPRESSED_FILE
  1827                                  .end:
  1828 00017F30 26                      	db 38
  1829 00017F31 26<rep Fh>              	align 16, db 38
  1830                                  %endif
  1831                                  init2_end:
  1832                                  %endif
  1833                                  
