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