     1                                  
     2                                  %if 0
     3                                  
     4                                  lDOS iniload packed payload
     5                                   by C. Masloch, 2018-2020
     6                                  
     7                                  Usage of the works is permitted provided that this
     8                                  instrument is retained with the works, so that any entity
     9                                  that uses the works is notified of this instrument.
    10                                  
    11                                  DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                                  
    13                                  
    14                                  Includes one of several depackers, some of which are under
    15                                  separate usage conditions. Refer to the individual depacker
    16                                  source files for the applicable usage conditions.
    17                                  
    18                                  %endif
    19                                  
    20                                  %include "lmacros3.mac"
     1                              <1> [list -]
    14                              <2> [list -]
    14                              <1> [list -]
    21                                  
    22                                  	struc LOADSTACKVARS, -10h
    23 FFFFFFF0 ????????                lsvFirstCluster:	resd 1
    24 FFFFFFF4 ????????                lsvFATSector:		resd 1
    25 FFFFFFF8 ????                    lsvFATSeg:		resw 1
    26 FFFFFFFA ????                    lsvLoadSeg:		resw 1
    27 FFFFFFFC ????????                lsvDataStart:		resd 1
    28                                  	endstruc
    29                                  
    30                                  	struc LOADDATA, LOADSTACKVARS - 10h
    31 FFFFFFE0 ????                    ldMemoryTop:	resw 1
    32 FFFFFFE2 ????                    ldLoadTop:	resw 1
    33 FFFFFFE4 ????                    ldSectorSeg:	resw 1
    34 FFFFFFE6 ??                      ldFATType:	resb 1
    35 FFFFFFE7 ??                      ldHasLBA:	resb 1
    36 FFFFFFE8 ????                    ldClusterSize:	resw 1
    37 FFFFFFEA ????                    ldParaPerSector:resw 1
    38 FFFFFFEC ????                    ldLoadingSeg:	resw 1
    39 FFFFFFEE ????                    ldLoadUntilSeg:	resw 1
    40                                  	endstruc
    41                                  
    42                                  
    43                                  %ifndef _MAP
    44                                  %elifempty _MAP
    45                                  %else	; defined non-empty, str or non-str
    46                                  	[map all _MAP]
    47                                  %endif
    48                                  
    49                                  	defaulting
    50                                  
    51                                  	numdef DEBUG0		; use errordata to generate an error code
    52                                  	numdef DEBUG1		; dump_stack_frame after an error occurred
    53                                  	numdef DEBUG2		; dump_stack_frame before blz_depack_safe call
    54                                  	numdef DEBUG3		; dump_stack_frame at start of blz_depack_safe
    55                                  
    56                                  	numdef ALLOW_OVERLAPPING,	1	; allow overlapping src and dst
    57                                  	numdef TEST_PROGRAM,		0
    58                                  	numdef TEST_PROGRAM_DECOMPRESSED_SIZE,		0,0
    59                                  %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE
    60                                   %error Test program has to learn of decompressed size.
    61                                  %endif
    62                                  	numdef TEST_PROGRESS,	0
    63                                  
    64                                  	numdef EXEC_OFFSET,	0
    65                                  	numdef EXEC_SEGMENT,	0
    66                                  	numdef IMAGE_EXE,	0
    67                                  %if ! _IMAGE_EXE && _TEST_PROGRAM
    68                                   %error Test program can only be used as EXE.
    69                                  %endif
    70                                  	numdef IMAGE_EXE_CS,	-16	; relative-segment for CS
    71                                  	numdef IMAGE_EXE_IP,	256 +64	; value for IP
    72                                  		; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0.
    73                                  	numdef IMAGE_EXE_SS,	-16	; relative-segment for SS
    74                                  	numdef IMAGE_EXE_SP,	0FFFEh	; value for SP (0 underflows)
    75                                  	numdef IMAGE_EXE_AUTO_STACK,	0, 2048	; use stack behind image
    76                                  		; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of
    77                                  		;  the same name. This one is only used as a flag; if non-zero,
    78                                  		;  keep the stack given to us by iniload; if zero, set up the
    79                                  		;  stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP.
    80                                  	numdef IMAGE_EXE_GET_COM_STACK, 0
    81                                  					; set up stack for flat .COM style entry
    82                                  	numdef DEVICE,			0
    83                                  	gendef DEVICE_NAME,		""
    84                                  	numdef DEVICE_ATTRIBUTE,	8000h
    85                                  	numdef DEVICE_ZERO_ENTRYPOINT,	0
    86                                  	numdef BOOTLDR,		1	; support boot loaded entrypoint
    87                                  
    88                                  	numdef BRIEFLZ,		0
    89                                  	numdef LZ4,		0
    90                                  	numdef SNAPPY,		0
    91                                  	numdef EXODECR,		0
    92                                  	numdef X,		0
    93                                  	numdef HEATSHRINK,	0
    94                                  	numdef LZD,		0
    95                                  	numdef LZO,		0
    96                                  	numdef LZSA2,		0
    97                                  	numdef APL,		0
    98                                  	numdef BZP,		0
    99                                  %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK 	+ !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP) != 1
   101                                   %fatal Exactly one compression method must be selected.
   102                                  %endif
   103                                  %assign ADDITIONAL_MEMORY 0
   104                                  %if _BRIEFLZ
   105                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BLZ"
   106                                  %elif _LZ4
   107                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ4"
   108                                  %elif _SNAPPY
   109                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SZ"
   110                                  %elif _EXODECR
   111                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.EXO"
   112                                  %elif _X
   113                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.X"
   114                                  %elif _HEATSHRINK
   115                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.HS"
   116                                  %elif _LZD
   117                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ"
   118                                  %elif _LZO
   119                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZO"
   120                                  %elif _LZSA2
   121                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SA2"
   122                                  %elif _APL
   123                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.APL"
   124                                  %elif _BZP
   125                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BZP"
   126                                  %endif
   127                                  	numdef PAYLOAD_KERNEL_MAX_PARAS,	0, 0
   128                                  %if _PAYLOAD_KERNEL_MAX_PARAS && ! _IMAGE_EXE
   129                                   %error Kernel mode max paras requires building dual-mode executable
   130                                  %endif
   131                                  	numdef COUNTER,		0, 32
   132                                  %if (_COUNTER - 1) & _COUNTER
   133                                   %error COUNTER must be a power of two
   134                                  %endif
   135                                  
   136                                  	strdef INILOAD_CFG, ""
   137                                  %ifnidn _INILOAD_CFG, ""
   138                                   %include _INILOAD_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> strdef INILOAD_SIGNATURE, "eb"
     3                              <1> %assign _DEVICE 1
     4                              <1> %assign _DEVICE_ZERO_ENTRYPOINT 1
     5                              <1> %assign _DEVICE_ATTRIBUTE 8800h
     6                              <1> %define _DEVICE_NAME "LDEBUG$$"
   139                                  %endif
   140                                  
   141                                  %if _DEVICE
   142                                   %ifidn _DEVICE_NAME, ""
   143                                    %error Device name must be set
   144                                   %endif
   145                                  %endif
   146                                  
   147                                  
   148                                  	cpu 8086
   149                                  	section INIT0 start=0 vstart=0
   150                                  init0_start:
   151                                  %if _DEVICE
   152                                  		; The device header is of a fixed format.
   153                                  		;  For our purposes, the 4-byte code for
   154                                  		;  each the strategy entry and the
   155                                  		;  interrupt entry is part of this format.
   156                                  		; (DOS may read the attributes or entrypoint
   157                                  		;  offsets before calling either, so in the inicomp
   158                                  		;  stage we need to recreate in the entrypoints part
   159                                  		;  exactly what the application has here.)
   160                                  device_header:
   161                                  .next:
   162                                   %if _DEVICE_ZERO_ENTRYPOINT
   163 00000000 EB3E                    	fill 2, -1, jmp strict short j_zero_entrypoint
   164 00000002 FFFF                    	dw -1
   165                                   %else
   166                                  	dd -1				; link to next device
   167                                   %endif
   168                                  .attributes:
   169 00000004 0088                    	dw _DEVICE_ATTRIBUTE		; attributes
   170                                  .strategy:
   171 00000006 [1200]                  	dw .strategy_entry		; -> strategy entry
   172                                  .interrupt:
   173 00000008 [1600]                  	dw .interrupt_entry		; -> interrupt entry
   174                                  .name:
   175 0000000A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME	; character device name,
   176                                  					;  or block device number of units
   177                                  					;  + optional name
   178                                  .strategy_entry:
   179 00000012 EB5190<rep 2h>          	fill 4, 90h, jmp device_entrypoint
   180                                  .interrupt_entry:
   181 00000016 CB90<rep 3h>            	fill 4, 90h, retf
   182                                  %endif
   183                                  
   184                                  
   185                                  %if _IMAGE_EXE || _DEVICE
   186 0000001A 90                      	nop
   187 0000001B 90<rep 5h>              	align 32, nop
   188                                  init0_kernel_entry:
   189                                  		; cs:ip = load seg : 32 here
   190                                  %if ($ - $$) != 32
   191                                   %error Wrong kernel mode entrypoint
   192                                  %endif
   193                                  %if _TEST_PROGRAM
   194                                  @@:
   195                                  	int3
   196                                  	sti
   197                                  	hlt
   198                                  	jmp @B
   199                                  %endif
   200                                  %if _BOOTLDR
   201                                  %if ! _IMAGE_EXE
   202                                  j_zero_entrypoint:
   203                                  %endif
   204 00000020 31DB                    	xor bx, bx		; 0 = kernel mode
   205 00000022 50                      	push ax
   206 00000023 8CC8                    	mov ax, cs
   207 00000025 83C01D                  	add ax, (init0_end - init0_start) >> 4
   208 00000028 8B56E2                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   209 0000002B BE6000                  	mov si, 60h		; => destination
   210 0000002E EB20                    	jmp init0_common
   211                                  %endif
   212                                  
   213                                   %if _IMAGE_EXE
   214 00000030 90<rep 10h>             	align 64, nop
   215                                  j_zero_entrypoint:
   216                                  init0_exe_entry:
   217                                  		; NOTE:	This part is called with ip = 256 + 64, cs = PSP.
   218                                  %if ($ - $$) != 64
   219                                   %error Wrong EXE mode entrypoint
   220                                  %endif
   221                                  %if _IMAGE_EXE_GET_COM_STACK
   222                                  	mov bx, ds		; => PSP
   223                                  	dec bx			; => MCB
   224                                  	mov ds, bx
   225                                  	add bx, word [3]	; add size of memory block
   226                                  	sub bx, -1 + paras(512)	; add one, then subtract enough paragraphs
   227                                  	cli
   228                                  	mov ss, bx
   229                                  	mov sp, 512		; -> new stack
   230                                  	sti
   231                                  %endif
   232 00000040 BB0100                  	mov bx, 1		; EXE mode
   233 00000043 50                      	push ax
   234                                    %if _TEST_PROGRAM
   235                                  	mov si, 81h
   236                                  	xor dx, dx
   237                                  	xor ax, ax
   238                                  cmdline:
   239                                  .:
   240                                  	lodsb
   241                                  	cmp al, 9
   242                                  	je .
   243                                  	cmp al, 32
   244                                  	je .
   245                                  	cmp al, 13
   246                                  	je .end
   247                                  	cmp al, '0'
   248                                  	jb .notdigit
   249                                  	cmp al, '9'
   250                                  	ja .notdigit
   251                                  .digit:
   252                                  	sub al, '0'
   253                                  	mov cx, dx		; times 1
   254                                  	add dx, dx
   255                                  	jc .invalid
   256                                  	add dx, dx		; times 4
   257                                  	jc .invalid
   258                                  	add dx, cx		; times 5
   259                                  	jc .invalid
   260                                  	add dx, dx		; times 10
   261                                  	jc .invalid
   262                                  	add dx, ax		; add in low digit
   263                                  	jc .invalid
   264                                  	jmp .
   265                                  
   266                                  .notdigit:
   267                                  	cmp al, 'A'
   268                                  	je .a
   269                                  	cmp al, 'a'
   270                                  	je .a
   271                                  	cmp al, 'B'
   272                                  	je .b
   273                                  	cmp al, 'b'
   274                                  	je .b
   275                                  .invalid:
   276                                  	mov dx, -1		; invalid
   277                                  	jmp .end
   278                                  
   279                                  .a:
   280                                  	and bh, ~ 80h
   281                                  	jmp .
   282                                  
   283                                  .b:
   284                                  	or bh, 80h
   285                                  	jmp .
   286                                  
   287                                  .end:
   288                                  	push dx
   289                                    %endif
   290 00000044 8CD2                    	mov dx, ss		; => after end of available space
   291 00000046 8CC8                    	mov ax, cs
   292 00000048 83C02D                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   293 0000004B 8CCE                    	mov si, cs
   294 0000004D 83C610                  	add si, 256 >> 4	; => destination
   295                                   %endif
   296                                  
   297                                  init0_common:
   298                                  		; REM:	This part must be position-independent, as it is
   299                                  		;	 called either with ip = init0_common (kernel mode
   300                                  		;	 or device mode)
   301                                  		;	 or ip = init0_common + 256 (application mode).
   302                                  		; INP:	si => depack destination
   303                                  		;	ax => source of payload + INIT1
   304                                  		;	dx => behind available memory
   305                                  		; OUT:	cs:ip -> init1_start:
   306                                  		;	ax => INIT1
   307                                  		;	dx => payload source
   308                                  		;	si => depack destination
   309                                  		;	bx = mode
   310 00000050 FC                      	cld
   311                                  %if _TEST_PROGRAM
   312                                  	sub dx, ( (payload_end - payload) ) >> 4
   313                                  	jc .error
   314                                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   318                                  	sub dx, cx
   319                                  	jc .error
   320                                  	cmp dx, ax
   321                                  	jb .error
   322                                  %else
   323 00000051 B92713                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   326                                  				; cx = amount paragraphs in payload + INIT1
   327 00000054 29CA                    	sub dx, cx		; => destination for payload + INIT1
   328                                  				;  (highest possible spot in available memory)
   329                                  %endif
   330 00000056 56                      	push si			; preserve destination
   331 00000057 E8F300                  	call init0_movp		; move up payload + INIT1
   332 0000005A 5E                      	pop si
   333                                  %else
   334                                  	cld
   335                                  	mov ax, cs
   336                                  	add ax, (init0_end - init0_start) >> 4
   337                                  	mov cx, ( (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   340                                  	mov dx, word [ bp + ldLoadTop ]
   341                                  	sub dx, cx
   342                                  	call init0_movp
   343                                  %endif
   344                                  
   345 0000005B 89D0                    	mov ax, dx		; => payload
   346                                  %if _TEST_PROGRAM
   347                                  	add ax, ( 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4		; => INIT2
   351                                  %else
   352 0000005D 058712                  	add ax, ( 		+ (payload_end - payload) 		) >> 4		; => INIT1
   355                                  %endif
   356 00000060 31C9                    	xor cx, cx
   357 00000062 50                      	push ax
   358 00000063 51                      	push cx
   359 00000064 CB                      	retf			; jump to relocated INIT1:init1_start
   360                                  				;  or INIT2:init2_start
   361                                  
   362                                  
   363                                  %if _TEST_PROGRAM
   364                                  .error:
   365                                  	mov di, bx
   366                                  
   367                                  	push cs
   368                                  	pop ds
   369                                  	mov dx, init0_msg.error_stderr + 256
   370                                  	mov cx, init0_msg.error_stderr.length
   371                                  	mov bx, 2
   372                                  	mov ah, 40h
   373                                  	int 21h
   374                                  
   375                                  	test di, 8000h
   376                                  	jnz @F
   377                                  	mov dx, init0_msg.error_stdout + 256
   378                                  	mov cx, init0_msg.error_stdout.length
   379                                  	mov bx, 1
   380                                  	mov ah, 40h
   381                                  	int 21h
   382                                  @@:
   383                                  	mov ax, 4CFFh
   384                                  	int 21h
   385                                  %endif
   386                                  
   387                                  
   388                                  %if _DEVICE
   389                                  device_entrypoint:
   390                                  %if _TEST_PROGRAM
   391                                  @@:
   392                                  	int3
   393                                  	sti
   394                                  	hlt
   395                                  	jmp @B
   396                                  %endif
   397 00000065 26807F0200              	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   398 0000006A 7407                    	je @F
   399                                  
   400 0000006C 26C747030381            	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   401 00000072 CB                      	retf
   402                                  
   403                                  @@:
   404 00000073 2E830E[0000]FF          	or word [cs:device_header.next], -1
   405 00000079 0E                      	push cs
   406 0000007A 2EFF36[0600]            	push word [cs:device_header.strategy]
   407                                  					; -> far return to payload's strategy
   408 0000007F 55                      	push bp
   409 00000080 1E                      	push ds
   410 00000081 56                      	push si
   411 00000082 57                      	push di
   412 00000083 52                      	push dx
   413 00000084 51                      	push cx
   414 00000085 50                      	push ax
   415 00000086 53                      	push bx
   416 00000087 06                      	push es
   417                                  
   418 00000088 268B4710                	mov ax, word [es:bx + 14 + 2]
   419 0000008C 31D2                    	xor dx, dx
   420 0000008E B90400                  	mov cx, 4
   421                                  @@:
   422 00000091 D1E0                    	shl ax, 1
   423 00000093 D1D2                    	rcl dx, 1
   424 00000095 E2FA                    	loop @B
   425 00000097 2603470E                	add ax, word [es:bx + 14]
   426 0000009B 83D200                  	adc dx, 0		; dx:ax = linear address behind end
   427                                  
   428 0000009E B104                    	mov cl, 4
   429                                  @@:
   430 000000A0 D1EA                    	shr dx, 1
   431 000000A2 D1D8                    	rcr ax, 1
   432 000000A4 E2FA                    	loop @B			; ax => behind end
   433                                  
   434 000000A6 8CCF                    	mov di, cs
   435                                  image_size: equ  ( (init0_end - init0_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   439 000000A8 81C74413                	add di, image_size >> 4		; di => end of image
   440                                  
   441 000000AC 39F8                    	cmp ax, di			; enough memory to hold all of us ?
   442 000000AE 7203E98A00              	jae .have_some_memory		; yes -->
   443                                  
   444 000000B3 0E                      	push cs
   445 000000B4 1F                      	pop ds
   446 000000B5 BA[F400]                	mov dx, .msg_no_memory
   447 000000B8 B409                    	mov ah, 09h
   448 000000BA CD21                    	int 21h
   449                                  
   450 000000BC B80030                  	mov ax, 3000h
   451 000000BF CD21                    	int 21h
   452 000000C1 3C05                    	cmp al, 5
   453 000000C3 7307                    	jae @F
   454 000000C5 BA[1301]                	mov dx, .msg_dos_below_5
   455 000000C8 B409                    	mov ah, 09h
   456 000000CA CD21                    	int 21h
   457                                  @@:
   458                                  
   459 000000CC BA[3A01]                	mov dx, .msg_linebreak
   460 000000CF B409                    	mov ah, 09h
   461 000000D1 CD21                    	int 21h
   462                                  
   463                                  		; tear down the stack frame and modify the request header
   464 000000D3 07                      	pop es
   465 000000D4 5B                      	pop bx
   466 000000D5 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   467 000000DB 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   468 000000E0 268C4F10                	mov word [es:bx + 14 + 2], cs
   469 000000E4 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   470 000000E9 58                      	pop ax
   471 000000EA 59                      	pop cx
   472 000000EB 5A                      	pop dx
   473 000000EC 5F                      	pop di
   474 000000ED 5E                      	pop si
   475 000000EE 1F                      	pop ds
   476 000000EF 5D                      	pop bp
   477 000000F0 83C404                  	add sp, 4		; discard far return to payload's strategy
   478 000000F3 CB                      	retf			; return to DOS
   479                                  
   480 000000F4 4C6F6164206572726F-     .msg_no_memory:		ascic "Load error: Not enough memory."
   480 000000FD 723A204E6F7420656E-
   480 00000106 6F756768206D656D6F-
   480 0000010F 72792E24           
   481 00000113 204E6F74653A20444F-     .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   481 0000011C 53206D757374206265-
   481 00000125 206174206C65617374-
   481 0000012E 2076657273696F6E20-
   481 00000137 352E24             
   482 0000013A 0D0A24                  .msg_linebreak:		ascic 13,10
   483                                  
   484                                  
   485                                  .have_some_memory:
   486 0000013D 89C2                    	mov dx, ax		; => after end of memory
   487 0000013F BB0200                  	mov bx, 2		; device mode
   488 00000142 50                      	push ax
   489 00000143 8CC8                    	mov ax, cs
   490 00000145 83C01D                  	add ax, (init0_end - init0_start) >> 4
   491 00000148 8CCE                    	mov si, cs		; => destination
   492 0000014A E903FF                  	jmp init0_common
   493                                  %endif
   494                                  
   495                                  
   496                                  		; Move paragraphs
   497                                  		;
   498                                  		; INP:	ax => source
   499                                  		;	dx => destination
   500                                  		;	cx = number of paragraphs
   501                                  		; CHG:	cx, ds, si, es, di
   502                                  		; OUT:	ax and dx unchanged
   503                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   504                                  		;	Do not provide a wrapped/HMA source or destination!
   505                                  init0_movp:
   506 0000014D 39D0                    	cmp ax, dx		; source above destination ?
   507 0000014F 770A                    	ja .up			; yes, move up (forwards) -->
   508 00000151 747B                    	je .return		; same, no need to move -->
   509 00000153 50                      	push ax
   510 00000154 01C8                    	add ax, cx		; (expected not to carry)
   511 00000156 39D0                    	cmp ax, dx		; end of source is above destination ?
   512 00000158 58                      	pop ax
   513 00000159 7730                    	ja .down		; yes, move from top down -->
   514                                  	; Here, the end of source is below-or-equal the destination,
   515                                  	;  so they do not overlap. In this case we prefer moving up.
   516                                  
   517                                  .up:
   518 0000015B 50                      	push ax
   519 0000015C 52                      	push dx
   520                                  .uploop:
   521 0000015D 8ED8                    	mov ds, ax
   522 0000015F 8EC2                    	mov es, dx
   523 00000161 31FF                    	xor di, di
   524 00000163 31F6                    	xor si, si		; -> start of segment
   525 00000165 81E90010                	sub cx, 1000h		; 64 KiB left ?
   526 00000169 7610                    	jbe .uplast		; no -->
   527 0000016B 51                      	push cx
   528 0000016C B90080                  	mov cx, 10000h /2
   529 0000016F F3A5                    	rep movsw		; move 64 KiB
   530 00000171 59                      	pop cx
   531 00000172 050010                  	add ax, 1000h
   532 00000175 81C20010                	add dx, 1000h		; -> next segment
   533 00000179 EBE2                    	jmp short .uploop	; proceed for more -->
   534                                  .uplast:
   535 0000017B 81C10010                	add cx, 1000h		; restore counter
   536 0000017F D1E1                    	shl cx, 1
   537 00000181 D1E1                    	shl cx, 1
   538 00000183 D1E1                    	shl cx, 1		; *8, paragraphs to words
   539 00000185 F3A5                    	rep movsw		; move last part
   540 00000187 5A                      	pop dx
   541 00000188 58                      	pop ax
   542 00000189 EB43                    	jmp short .return
   543                                  
   544                                  .down:
   545 0000018B FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   546                                  .dnloop:
   547 0000018C 81E90010                	sub cx, 1000h		; 64 KiB left ?
   548 00000190 761A                    	jbe .dnlast		; no -->
   549 00000192 50                      	push ax
   550 00000193 52                      	push dx
   551 00000194 01C8                    	add ax, cx
   552 00000196 01CA                    	add dx, cx
   553 00000198 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   554 0000019A 8EC2                    	mov es, dx
   555 0000019C 5A                      	pop dx
   556 0000019D 58                      	pop ax
   557 0000019E BFFEFF                  	mov di, -2
   558 000001A1 89FE                    	mov si, di		; moved from last word down
   559 000001A3 51                      	push cx
   560 000001A4 B90080                  	mov cx, 10000h /2
   561 000001A7 F3A5                    	rep movsw		; move 64 KiB
   562 000001A9 59                      	pop cx
   563 000001AA EBE0                    	jmp short .dnloop	; proceed for more -->
   564                                  .dnlast:
   565 000001AC 81C10010                	add cx, 1000h		; restore counter
   566 000001B0 D1E1                    	shl cx, 1
   567 000001B2 D1E1                    	shl cx, 1
   568 000001B4 D1E1                    	shl cx, 1		; *8, paragraphs to words
   569 000001B6 89CF                    	mov di, cx
   570 000001B8 4F                      	dec di
   571 000001B9 D1E7                    	shl di, 1		; words to offset, -> last word
   572 000001BB 89FE                    	mov si, di
   573 000001BD 8ED8                    	mov ds, ax
   574 000001BF 8EC2                    	mov es, dx		; first segment correct
   575                                  
   576                                  
   577                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   578                                  %if 0
   579                                  
   580                                  Jack R. Ellis pointed out this erratum:
   581                                  
   582                                  Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
   583                                  
   584                                  109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
   585                                  
   586                                  Description
   587                                  
   588                                  In certain situations a REP MOVS instruction may lead to
   589                                  incorrect results. An incorrect address size, data size
   590                                  or source operand segment may be used or a succeeding
   591                                  instruction may be skipped. This may occur under the
   592                                  following conditions:
   593                                  
   594                                  * EFLAGS.DF=1 (the string is being moved in the reverse direction).
   595                                  
   596                                  * The number of items being moved (RCX) is between 1 and 20.
   597                                  
   598                                  * The REP MOVS instruction is preceded by some microcoded instruction
   599                                    that has not completely retired by the time the REP MOVS begins
   600                                    execution. The set of such instructions includes BOUND, CLI, LDS,
   601                                    LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
   602                                  
   603                                  Potential Effect on System
   604                                  
   605                                  Incorrect results may be produced or the system may hang.
   606                                  
   607                                  Suggested Workaround
   608                                  
   609                                  Contact your AMD representative for information on a BIOS update.
   610                                  
   611                                  %endif
   612                                  
   613                                  %if _AMD_ERRATUM_109_WORKAROUND
   614 000001C1 E308                    	jcxz @FF
   615 000001C3 83F914                  	cmp cx, 20
   616 000001C6 7703                    	ja @FF
   617                                  @@:
   618 000001C8 A5                      	movsw
   619 000001C9 E2FD                    	loop @B
   620                                  @@:
   621                                  %endif
   622 000001CB F3A5                    	rep movsw		; move first part
   623 000001CD FC                      	cld
   624                                  .return:
   625 000001CE C3                      	retn
   626                                  
   627                                  
   628                                  	section PAYLOAD align=16 follows=INIT0
   629                                  payload:
   630 00000000 <bin 12861h>            	incbin _PAYLOAD_FILE
   631                                  .end:
   632 00012861 26<rep Fh>              	align 16, db 38
   633                                  payload_end:
   634                                  
   635                                  
   636                                  	section INIT1 align=16 follows=PAYLOAD vstart=0
   637                                  init1_start:
   638                                  		; INP:	ax = cs = INIT1
   639                                  		;	dx = cs - (payload_end - payload) >> 4 => source data
   640                                  		;	if kernel mode:
   641                                  		;	 ss:bp -> LOADDATA and LOADSTACKVARS
   642                                  		;	 ss:sp -> valid stack above [bp + ldLoadTop]
   643                                  		;	 60h => destination
   644                                  		;	any mode:
   645                                  		;	 word [ss:sp] = value for ax
   646                                  		;	 bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode
   647                                  		;	 si => destination (60h for kernel mode,
   648                                  		;		after PSP for EXE mode,
   649                                  		;		at device header for device mode)
   650                                  		;		(not set if only kernel mode supported)
   651                                  		;	 if EXE mode:
   652                                  		;	  ss:sp -> valid stack above INIT1
   653                                  		;	  bp = unset
   654                                  		;	 if device mode:
   655                                  		;	  ss:sp -> device entrypoint stack
   656                                  		;	  holds: es, bx, ax, cx, dx, di, si, ds, bp,
   657                                  		;		  far address of payload strategy entrypoint,
   658                                  		;		  far return address to DOS
   659                                  		;	  bp = unset
   660                                  		; STT:	UP
   661                                  		; CHG:	ax, bx, cx, dx, es, ds, si, di
   662                                  %if _IMAGE_EXE || _DEVICE
   663                                  	lframe
   664 00000000 5589E5                  	lenter
   665                                  	lvar word,	exemode		; must be bp - 2!
   666 00000003 53                      	 push bx
   667                                   %if ?exemode != -2
   668                                    %error exemode variable must be directly below bp
   669                                   %endif
   670 00000004 56                      	push si
   671                                  %else
   672                                  	xor bx, bx		; always tell them it is kernel mode
   673                                  %endif
   674                                  
   675                                  %if _IMAGE_EXE
   676 00000005 8EC6                    	mov es, si		; es => destination
   677                                  %else
   678                                  	mov ax, 60h
   679                                  	mov es, ax		; es => destination
   680                                  %endif
   681 00000007 31FF                    	xor di, di		; -> destination
   682                                  
   683 00000009 8EDA                    	mov ds, dx
   684 0000000B 31F6                    	xor si, si		; -> source
   685                                  
   686 0000000D B96128                  	mov cx, (payload.end - payload) & 0FFFFh
   687                                  %if (payload.end - payload) >> 16
   688 00000010 BA0100                  	mov dx, (payload.end - payload) >> 16	; = length of source
   689                                  %else
   690                                  	xor dx, dx
   691                                  %endif
   692                                  %if _PAYLOAD_KERNEL_MAX_PARAS
   693                                  	mov ax, _PAYLOAD_KERNEL_MAX_PARAS
   694                                  	test bx, bx
   695                                  	jz @F
   696                                  %endif
   697 00000013 B8FFFF                  	mov ax, -1
   698                                  @@:
   699                                  		; INP:	ds:si -> source
   700                                  		;	dx:cx = length of source
   701                                  		;	es:di -> destination (below source)
   702                                  		;	bx = EXE mode flag
   703                                  		;	 (1 if EXE mode, 0 if kernel mode)
   704                                  		;	 (always 0 if this is a build without EXE mode)
   705                                  		;	if _PAYLOAD_KERNEL_MAX_PARAS:
   706                                  		;	 ax = maximum amount in paragraphs of destination needed
   707                                  		;	 (-1 if full source should be decompressed)
   708                                  		;	else:
   709                                  		;	 ax = -1
   710                                  		; Note:	The destination reaches up to below the source.
   711 00000016 E82803                  	call depack
   712                                  %ifn _TEST_PROGRAM
   713 00000019 7234                    	jc strict short error
   714                                  %endif
   715                                  %if _IMAGE_EXE
   716 0000001B 5E                      	pop si			; si
   717                                   %if _TEST_PROGRAM
   718                                  	pop ax			; (discard ?exemode, leave bx as returned)
   719                                   %else
   720 0000001C 5B                      	pop bx			; ?exemode
   721                                   %endif
   722 0000001D 5D                      	pop bp			; bp
   723 0000001E 58                      	pop ax			; ax
   724                                  	lleave ctx
   725                                  %endif
   726                                  %if _TEST_PROGRAM
   727                                  	retf
   728                                  	nop
   729                                  %endif
   730                                  
   731                                  %if _DEVICE
   732 0000001F F6C302                  	test bl, 2
   733 00000022 7411                    	jz .jmp_exe_or_kernel_mode
   734                                  
   735                                  .jmp_device_mode:
   736 00000024 8EDE                    	mov ds, si
   737 00000026 830E[0000]FF            	or word [device_header.next], -1
   738 0000002B 07                      	pop es
   739 0000002C 5B                      	pop bx
   740 0000002D 58                      	pop ax
   741 0000002E 59                      	pop cx
   742 0000002F 5A                      	pop dx
   743 00000030 5F                      	pop di
   744 00000031 5E                      	pop si
   745 00000032 1F                      	pop ds
   746 00000033 5D                      	pop bp
   747 00000034 CB                      	retf			; transfer to payload strategy entrypoint
   748                                  				; still on stack: far return address to DOS
   749                                  
   750                                  .jmp_exe_or_kernel_mode:
   751                                  %endif
   752                                  
   753                                  %if _IMAGE_EXE
   754 00000035 F6C301                  	test bl, 1
   755 00000038 7410                    	jz .jmp_kernel_mode
   756                                  
   757                                  .jmp_exe_mode:
   758                                  %if ! _IMAGE_EXE_AUTO_STACK
   759                                  	mov cx, cs
   760                                  	lea dx, [si + _IMAGE_EXE_SS]
   761                                  	push dx			; stack = relocated ss value
   762                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
   763                                  	cmp cx, dx		; INIT1 code is above intended stack ?
   764                                  	jae @F			; yes -->
   765                                  
   766                                  	lframe
   767                                  	lenter
   768                                  	lvar	word, exemode
   769                                  	 push bx
   770                                   %if ?exemode != -2
   771                                    %error exemode variable must be directly below bp
   772                                   %endif
   773                                  	mov bx, -1		; unimplemented, return error
   774                                  	jmp error
   775                                  	lleave ctx
   776                                  @@:
   777                                  	cli
   778                                  	pop ss			; = relocated ss value
   779                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
   780                                  	sti
   781                                  %endif
   782                                  
   783 0000003A 31C9                    	xor cx, cx
   784 0000003C 51                      	push cx			; put zero on top of stack
   785                                  
   786                                  %if _IMAGE_EXE_IP < 256
   787                                  	mov cl, _IMAGE_EXE_IP
   788                                  %elif (_IMAGE_EXE_IP & 255) == 0
   789                                  	mov ch, _IMAGE_EXE_IP >> 8
   790                                  %else
   791 0000003D B94001                  	mov cx, _IMAGE_EXE_IP
   792                                  %endif
   793                                  
   794                                  %if _IMAGE_EXE_CS == -16
   795 00000040 83C6F0                  	add si, -16
   796 00000043 8EDE                    	mov ds, si
   797 00000045 8EC6                    	mov es, si
   798                                  %else
   799                                  	lea dx, [si - 10h]	; => PSP
   800                                  	mov ds, dx
   801                                  	mov es, dx		; ds = es => PSP
   802                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
   803                                  %endif
   804 00000047 56                      	push si
   805 00000048 51                      	push cx
   806 00000049 CB                      	retf			; jump to EXE mode of image
   807                                  
   808                                  %endif
   809                                  .jmp_kernel_mode:
   810 0000004A EA20006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
   811                                  
   812                                  
   813                                  error:
   814 0000004F 0E                      	push cs
   815 00000050 1F                      	pop ds
   816                                  %if _DEBUG0
   817                                  	mov si, msg.error_begin
   818                                  	call disp_error
   819                                  	xchg ax, bx			; ax = error code
   820                                  	call disp_ax_hex
   821                                  	mov si, msg.error_end
   822                                  %else
   823 00000051 BE[F600]                	mov si, msg.error
   824                                  %endif
   825 00000054 E87D00                  	call disp_error
   826                                  
   827                                  %if _DEVICE
   828 00000057 F646FE02                	test byte [bp - 2], 2
   829 0000005B 7435                    	jz .exit_app_or_kernel
   830                                  
   831 0000005D 5E                      	pop si				; => device segment
   832 0000005E 5B                      	pop bx				; mode word
   833 0000005F 5D                      	pop bp
   834 00000060 58                      	pop ax
   835 00000061 8EC6                    	mov es, si
   836 00000063 31FF                    	xor di, di			; -> device header
   837 00000065 0E                      	 push cs
   838 00000066 1F                      	 pop ds
   839 00000067 BE[B000]                	mov si, device_header_copy	; -> to reset header
   840 0000006A B91100                  	mov cx, words(device_header_copy.length)
   841 0000006D F3A5                    	rep movsw		; overwrite device header with default
   842                                  				;  (reset to a valid state after unsuccessful
   843                                  				;  decompression, which may have partially
   844                                  				;  written the header already)
   845 0000006F 06                      	 push es
   846 00000070 1F                      	 pop ds				; -> device segment
   847 00000071 07                      	pop es
   848 00000072 5B                      	pop bx
   849 00000073 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   850 00000079 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   851 0000007E 268C5F10                	mov word [es:bx + 14 + 2], ds
   852 00000082 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   853 00000087 58                      	pop ax
   854 00000088 59                      	pop cx
   855 00000089 5A                      	pop dx
   856 0000008A 5F                      	pop di
   857 0000008B 5E                      	pop si
   858 0000008C 1F                      	pop ds
   859 0000008D 5D                      	pop bp
   860 0000008E 83C404                  	add sp, 4		; discard far return to payload's strategy
   861 00000091 CB                      	retf			; return to DOS
   862                                  
   863                                  
   864                                  .exit_app_or_kernel:
   865                                  %endif
   866                                  
   867                                  %if _IMAGE_EXE
   868                                  %if _BOOTLDR
   869 00000092 F646FE01                	test byte [bp - 2], 1
   870 00000096 7405                    	jz .exit_kernel_mode
   871                                  %endif
   872                                  
   873 00000098 B87F4C                  	mov ax, 4C7Fh
   874 0000009B CD21                    	int 21h
   875                                  
   876                                  .exit_kernel_mode:
   877                                  %endif
   878                                  %if _BOOTLDR
   879 0000009D 31C0                    	xor ax, ax
   880 0000009F CD16                    	int 16h
   881 000000A1 CD19                    	int 19h
   882                                  %endif
   883                                  
   884                                  
   885                                  %if _DEVICE
   886 000000A3 90<rep Dh>              	align 16
   887                                  device_header_copy:
   888                                  .:
   889                                  .next:
   890 000000B0 FFFFFFFF                	dd -1				; already initialised
   891                                  .attributes:
   892 000000B4 0088                    	dw _DEVICE_ATTRIBUTE
   893                                  .strategy:
   894 000000B6 1200                    	dw .strategy_entry - .		; -> strategy entry
   895                                  .interrupt:
   896 000000B8 1600                    	dw .interrupt_entry - .		; -> interrupt entry
   897                                  .name:
   898 000000BA 4C44454255472424        	fill 8, 32, db _DEVICE_NAME
   899                                  .strategy_entry:
   900 000000C2 EB0690<rep 2h>          	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
   901                                  .interrupt_entry:
   902 000000C6 CB90<rep 3h>            	fill 4, 90h, retf
   903                                  
   904                                  .set_error:
   905 000000CA 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   906 000000D0 CB                      	retf
   907                                  .length: equ $ - .
   908                                  %endif
   909                                  
   910                                  
   911                                  disp_error.loop:
   912 000000D1 E80600                  	call disp_al
   913                                  disp_error:
   914 000000D4 AC                      	lodsb
   915 000000D5 84C0                    	test al, al
   916 000000D7 75F8                    	jnz .loop
   917 000000D9 C3                      	retn
   918                                  
   919                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
   920                                  disp_ax_hex:			; ax
   921                                  		xchg al,ah
   922                                  		call disp_al_hex		; display former ah
   923                                  		xchg al,ah			;  and fall trough for al
   924                                  disp_al_hex:			; al
   925                                  		push cx
   926                                  		mov cl,4
   927                                  		ror al,cl
   928                                  		call disp_al_lownibble_hex	; display former high-nibble
   929                                  		rol al,cl
   930                                  		pop cx
   931                                  						;  and fall trough for low-nibble
   932                                  disp_al_lownibble_hex:
   933                                  		push ax			 ; save ax for call return
   934                                  		and al,00001111b		; high nibble must be zero
   935                                  		add al,'0'			; if number is 0-9, now it's the correct character
   936                                  		cmp al,'9'
   937                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
   938                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
   939                                   .decimalnum:
   940                                  		call disp_al
   941                                  		pop ax
   942                                  		retn
   943                                  %endif
   944                                  
   945                                  disp_al:
   946                                  %if _TEST_PROGRAM
   947                                  	retn
   948                                  %else
   949 000000DA 50                      	push ax
   950                                  %endif
   951                                  %if _BOOTLDR
   952 000000DB 53                      	push bx
   953 000000DC 55                      	push bp
   954 000000DD B40E                    	mov ah, 0Eh
   955 000000DF BB0700                  	mov bx, 7
   956                                  %endif
   957                                  %if _IMAGE_EXE || _DEVICE
   958 000000E2 52                      	push dx
   959                                  
   960                                  %if _BOOTLDR
   961 000000E3 F646FE03                	test byte [bp - 2], 1 | 2
   962 000000E7 7406                    	jz .display_kernel_mode
   963                                  %endif
   964                                  
   965 000000E9 92                      	xchg dx, ax				; dl = input al
   966 000000EA B402                    	mov ah, 02h
   967 000000EC CD21                    	int 21h
   968                                  %if _BOOTLDR
   969 000000EE A9                      	db __TEST_IMM16				; (skip int)
   970                                  %endif
   971                                  
   972                                  .display_kernel_mode:
   973                                  %endif
   974                                  %if _BOOTLDR
   975 000000EF CD10                    	int 10h
   976                                  %endif
   977                                  %if _IMAGE_EXE
   978 000000F1 5A                      	pop dx
   979                                  %endif
   980                                  %if _BOOTLDR
   981 000000F2 5D                      	pop bp
   982 000000F3 5B                      	pop bx
   983                                  %endif
   984 000000F4 58                      	pop ax
   985                                  disp_error.ret:
   986 000000F5 C3                      	retn
   987                                  
   988                                  
   989                                  msg:
   990                                  %if _DEBUG0
   991                                  .error_begin:	db "Load error: Decompression failure, code ",0
   992                                  .error_end:	db "h.",13,10,0
   993                                  %else
   994 000000F6 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
   994 000000FF 723A204465636F6D70-
   994 00000108 72657373696F6E2066-
   994 00000111 61696C7572652E0D0A-
   994 0000011A 00                 
   995                                  %endif
   996                                  
   997                                  
   998                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
   999                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
  1000                                  %assign CHECK_POINTERS_VARIABLE_DST 1
  1001                                  
  1002                                  		; Specific depacker's file is included within label msg.
  1003                                  		; In the file, lframe is used and lleave ctx is not used.
  1004                                  
  1005                                  %if _BRIEFLZ
  1006                                  	%include "brieflz.asm"
  1007                                  %endif
  1008                                  
  1009                                  
  1010                                  %if _LZ4
  1011                                  	%include "lz4.asm"
  1012                                  %endif
  1013                                  
  1014                                  
  1015                                  %if _SNAPPY
  1016                                  	%include "snappy.asm"
  1017                                  %endif
  1018                                  
  1019                                  
  1020                                  %if _EXODECR
  1021                                  	%include "exodecr.asm"
  1022                                  %endif
  1023                                  
  1024                                  
  1025                                  %if _X
  1026                                  	%include "x.asm"
  1027                                  %endif
  1028                                  
  1029                                  
  1030                                  %if _HEATSHRINK
  1031                                  	%include "heatshr.asm"
  1032                                  %endif
  1033                                  
  1034                                  
  1035                                  %if _LZD
  1036                                  	%include "lzd.asm"
     1                              <1> 
     2                              <1> %if 0
     3                              <1> 
     4                              <1>     Lzd - Educational decompressor for the lzip format
     5                              <1>     Copyright (C) 2013-2019 Antonio Diaz Diaz.
     6                              <1> 
     7                              <1>     This program is free software. Redistribution and use in source and
     8                              <1>     binary forms, with or without modification, are permitted provided
     9                              <1>     that the following conditions are met:
    10                              <1> 
    11                              <1>     1. Redistributions of source code must retain the above copyright
    12                              <1>     notice, this list of conditions and the following disclaimer.
    13                              <1> 
    14                              <1>     2. Redistributions in binary form must reproduce the above copyright
    15                              <1>     notice, this list of conditions and the following disclaimer in the
    16                              <1>     documentation and/or other materials provided with the distribution.
    17                              <1> 
    18                              <1>     This program is distributed in the hope that it will be useful,
    19                              <1>     but WITHOUT ANY WARRANTY; without even the implied warranty of
    20                              <1>     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    21                              <1> 
    22                              <1> %endif
    23                              <1> 
    24                              <1> 
    25                              <1> 	numdef COUNTER,		0, 128
    26                              <1> %if (_COUNTER - 1) & _COUNTER
    27                              <1>  %error COUNTER must be a power of two
    28                              <1> %endif
    29                              <1> 
    30                              <1> 
    31                              <1> amount_states equ 12
    32                              <1> 
    33                              <1> 		numdef XLATBSEQ, 7
    34                              <1> 		numdef WARNXLATBSEQ, 0
    35                              <1> 
    36                              <1> 
    37                              <1> %if _XLATBSEQ != 7
    38                              <1> next_states.beforealign:
    39                              <1> 	align 2
    40                              <1> next_states:
    41                              <1> .:
    42                              <1> 	times 4 db 0
    43                              <1> 	db 1, 2, 3, 4, 5, 6, 4, 5
    44                              <1> .amount: equ $ - .
    45                              <1>  %if .amount != amount_states
    46                              <1>   %error Invalid next_states array content
    47                              <1>  %endif
    48                              <1>  %assign XLATBTABSIZE $ - .beforealign
    49                              <1> %else
    50                              <1>  %assign XLATBTABSIZE 0
    51                              <1> %endif
    52                              <1> 
    53                              <1> 
    54                              <1> State:
    55                              <1> 		; INP:	ds:bx -> localvariables
    56                              <1> 		;	byte [bx + state.st]
    57                              <1> 		; OUT:	CY if st < 7 (is_char() == true)
    58                              <1> 		;	NC if st >= 7 (is_char() == false)
    59                              <1> 		; CHG:	-
    60                              <1> .is_char:
    61 0000011B 807F2807            <1> 	cmp byte [bx + state.st], 7
    62 0000011F C3                  <1> 	retn
    63                              <1> 
    64                              <1> 
    65                              <1> 		; INP:	ds:bx -> localvariables
    66                              <1> 		;	byte [bx + state.st]
    67                              <1> 		; OUT:	byte [bx + state.st] = al = next state
    68                              <1> 		; CHG:	al, ah (ah only if _XLATBSEQ == 6)
    69                              <1> .set_char:
    70                              <1> 
    71                              <1> .xlatbseq:
    72                              <1> %if 0 == _XLATBSEQ	; 10
    73                              <1> 	push bx
    74                              <1> 	mov al, byte [bx + state.st]
    75                              <1> 	mov bx, next_states
    76                              <1> 	cs xlatb
    77                              <1> 		; Problem: It is reported that prior to the 386
    78                              <1> 		;  a segment override on an xlatb instruction
    79                              <1> 		;  does not have any effect. So this choice is
    80                              <1> 		;  possibly wrong on those machines.
    81                              <1> 	pop bx
    82                              <1> %elif 1 == _XLATBSEQ	; 13
    83                              <1> 	push bx
    84                              <1> 	mov al, byte [bx + state.st]
    85                              <1> 	mov bx, next_states
    86                              <1> 	push ds
    87                              <1> 	 push cs
    88                              <1> 	 pop ds
    89                              <1> 	xlatb
    90                              <1> 	pop ds
    91                              <1> 	pop bx
    92                              <1> %elif 2 == _XLATBSEQ	; 16
    93                              <1> 	push bx
    94                              <1> 	mov al, byte [bx + state.st]
    95                              <1> 	mov bx, next_states
    96                              <1> 	add bl, al
    97                              <1> 	adc bh, 0
    98                              <1> 	mov al, byte [cs:bx]
    99                              <1> 	pop bx
   100                              <1> %elif 3 == _XLATBSEQ	; 14
   101                              <1> 	push bx
   102                              <1> 	mov al, byte [bx + state.st]
   103                              <1> 	xor bx, bx
   104                              <1> 	mov bl, al
   105                              <1> 	mov al, byte [cs:next_states + bx]
   106                              <1> 	pop bx
   107                              <1> %elif 4 == _XLATBSEQ	; 12
   108                              <1> 	push bx
   109                              <1> 	mov bl, byte [bx + state.st]
   110                              <1> 	mov bh, 0
   111                              <1> 	mov al, byte [cs:next_states + bx]
   112                              <1> 	pop bx
   113                              <1> %elif 5 == _XLATBSEQ	; 10
   114                              <1> 	push bx
   115                              <1> 	mov bl, byte [bx + state.st]
   116                              <1> 	; mov bh, 0
   117                              <1> 		; ! because the pointer stored in ?localvariables
   118                              <1> 		;    is normalised bh is already zero here.
   119                              <1> 	mov al, byte [cs:next_states + bx]
   120                              <1> 	pop bx
   121                              <1> %elif 6 == _XLATBSEQ	; 12
   122                              <1> 	xor ax, ax
   123                              <1> 	mov al, byte [bx + state.st]
   124                              <1> 	xchg ax, bx
   125                              <1> 	mov bl, byte [cs:next_states + bx]
   126                              <1> 	xchg ax, bx
   127                              <1> %elif 7 == _XLATBSEQ	; 16, but minus 13 for table
   128 00000120 8A4728              <1> 	mov al, byte [bx + state.st]
   129 00000123 2C03                <1> 	sub al, 3		; below 4 ?
   130 00000125 7607                <1> 	jbe .zero		; yes -->
   131 00000127 3C07                <1> 	cmp al, 10 - 3		; 10 or 11 initially ?
   132 00000129 7202                <1> 	jb .have		; no -->
   133 0000012B 2C03                <1> 	sub al, 3		; convert
   134                              <1> .have:
   135 0000012D A9                  <1> 	db __TEST_IMM16		; (skip mov)
   136                              <1> .zero:
   137 0000012E B000                <1> 	mov al, 0
   138                              <1> %else
   139                              <1>  %error Invalid xlatb sequence specified
   140                              <1> %endif
   141                              <1> %if _WARNXLATBSEQ
   142                              <1> %assign SIZE $ - .xlatbseq
   143                              <1> %warning xlatb sequence takes SIZE bytes plus XLATBTABSIZE table
   144                              <1> %endif
   145                              <1> .end:
   146 00000130 884728              <1> 	mov byte [bx + state.st], al
   147 00000133 C3                  <1> 	retn
   148                              <1> 
   149                              <1> 
   150                              <1> 		; INP:	ds:bx -> localvariables
   151                              <1> 		;	byte [bx + state.st]
   152                              <1> 		;	al = value to use if is_char() == true
   153                              <1> 		;	ah = value to use else
   154                              <1> 		; OUT:	byte [bx + state.st] = al = value to use
   155                              <1> 		; CHG:	al
   156                              <1> .select:
   157 00000134 E8E4FF              <1> 	call .is_char
   158 00000137 72F7                <1> 	jc .end
   159 00000139 88E0                <1> 	mov al, ah
   160 0000013B EBF3                <1> 	jmp .end
   161                              <1> 
   162                              <1> 
   163                              <1>   min_dictionary_size:		equ 1 << 12
   164                              <1>   max_dictionary_size:		equ 1 << 29
   165                              <1>   literal_context_bits:		equ 3
   166                              <1>   literal_pos_state_bits:	equ 0		; not used
   167                              <1>   pos_state_bits:		equ 2
   168                              <1>   pos_states:			equ 1 << pos_state_bits
   169                              <1>   pos_state_mask:		equ pos_states - 1
   170                              <1> 
   171                              <1>   len_states:			equ 4
   172                              <1>   dis_slot_bits:		equ 6
   173                              <1>   start_dis_model:		equ 4
   174                              <1>   end_dis_model:		equ 14
   175                              <1>   modeled_distances:		equ 1 << ( end_dis_model / 2 )		; 128
   176                              <1>   dis_align_bits:		equ 4
   177                              <1>   dis_align_size:		equ 1 << dis_align_bits
   178                              <1> 
   179                              <1>   len_low_bits:			equ 3
   180                              <1>   len_mid_bits:			equ 3
   181                              <1>   len_high_bits:		equ 8
   182                              <1>   len_low_symbols:		equ 1 << len_low_bits
   183                              <1>   len_mid_symbols:		equ 1 << len_mid_bits
   184                              <1>   len_high_symbols:		equ 1 << len_high_bits
   185                              <1>   max_len_symbols:		equ len_low_symbols + len_mid_symbols + len_high_symbols
   186                              <1> 
   187                              <1>   min_match_len:		equ 2		; must be 2
   188                              <1> 
   189                              <1>   bit_model_move_bits:		equ 5
   190                              <1>   bit_model_total_bits:		equ 11
   191                              <1>   bit_model_total:		equ 1 << bit_model_total_bits
   192                              <1> 
   193                              <1> 
   194                              <1> 	struc bit_model
   195 00000000 ????                <1> .probability:	resw 1		; initialise to bit_model_total / 2
   196                              <1> 				; at most bit_model_total (800h)
   197                              <1> 	endstruc
   198                              <1> 
   199                              <1> 	struc len_model
   200 00000000 ????                <1> .choice1:	resb bit_model_size
   201 00000002 ????                <1> .choice2:	resb bit_model_size
   202 00000004 <res 40h>           <1> .bm_low:	resb bit_model_size * pos_states * len_low_symbols
   203 00000044 <res 40h>           <1> .bm_mid:	resb bit_model_size * pos_states * len_mid_symbols
   204 00000084 <res 200h>          <1> .bm_high:	resb bit_model_size * len_high_symbols
   205                              <1> 	endstruc
   206                              <1> 
   207                              <1> 	struc lzip_header
   208 00000000 ????????            <1> .magic:			resd 1
   209 00000004 ??                  <1> .version:		resb 1
   210 00000005 ??                  <1> .coded_dict_size:	resb 1
   211                              <1> 	endstruc
   212                              <1> 
   213                              <1> 	struc lzip_trailer
   214 00000000 ????????            <1> .uncompressed_checksum:	resd 1
   215 00000004 ????????????????    <1> .uncompressed_size:	resq 1
   216 0000000C ????????????????    <1> .member_size:		resq 1
   217                              <1> 	endstruc
   218                              <1> 
   219                              <1> 	struc range_decoder
   220 00000000 ????????            <1> .member_pos:		resd 1
   221 00000004 ????????            <1> .code:			resd 1
   222 00000008 ????????            <1> .range:			resd 1
   223                              <1> 	endstruc
   224                              <1> 
   225                              <1> 		; INP:	ds:bx -> range_decoder structure
   226                              <1> 		;	ss:bp -> depack stack frame
   227                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   228                              <1> 		; CHG:	es, di, ax, cx
   229                              <1> Range_decoder.init:
   230 0000013D 1E                  <1> 	push ds
   231 0000013E 07                  <1> 	pop es
   232 0000013F B80600              <1> 	mov ax, 6
   233 00000142 89DF                <1> 	mov di, bx		; -> .member_pos
   234 00000144 AB                  <1> 	stosw			; low word of .member_pos
   235 00000145 31C0                <1> 	xor ax, ax
   236 00000147 AB                  <1> 	stosw			; high word of .member_pos
   237 00000148 AB                  <1> 	stosw
   238 00000149 AB                  <1> 	stosw			; .code
   239 0000014A 48                  <1> 	dec ax
   240 0000014B AB                  <1> 	stosw
   241 0000014C AB                  <1> 	stosw			; .range
   242 0000014D B90500              <1> 	mov cx, 5
   243                              <1> .loop:
   244 00000150 E81900              <1> 	call getbyteshiftcode
   245 00000153 E2FB                <1> 	loop .loop
   246 00000155 C3                  <1> 	retn
   247                              <1> 
   248                              <1> 
   249                              <1> 		; INP:	ds:bx -> range_decoder structure
   250                              <1> 		;	ss:bp -> depack stack frame
   251                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   252                              <1> 		; CHG:	-
   253                              <1> normaliserange:
   254 00000156 807F0B00            <1> 	cmp byte [bx + range_decoder.range + 3], 0
   255 0000015A 7521                <1> 	jnz @F			; (retn)
   256 0000015C 50                  <1> 	push ax
   257 0000015D 8B4709              <1> 	mov ax, word [bx + range_decoder.range + 1]
   258 00000160 89470A              <1> 	mov word [bx + range_decoder.range + 2], ax
   259 00000163 8A6708              <1> 	mov ah, byte [bx + range_decoder.range]
   260 00000166 B000                <1> 	mov al, 0
   261 00000168 894708              <1> 	mov word [bx + range_decoder.range], ax
   262 0000016B 58                  <1> 	pop ax
   263                              <1> 		; fall through
   264                              <1> 
   265                              <1> 
   266                              <1> 		; INP:	ds:bx -> range_decoder structure
   267                              <1> 		;	ss:bp -> depack stack frame
   268                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   269                              <1> 		; CHG:	-
   270                              <1> getbyteshiftcode:
   271 0000016C 50                  <1> 	push ax
   272 0000016D 8B4705              <1> 	mov ax, word [bx + range_decoder.code + 1]
   273 00000170 894706              <1> 	mov word [bx + range_decoder.code + 2], ax
   274 00000173 8A6704              <1> 	mov ah, byte [bx + range_decoder.code]
   275 00000176 E88606              <1> 	call Range_decoder.get_byte
   276 00000179 894704              <1> 	mov word [bx + range_decoder.code], ax
   277 0000017C 58                  <1> 	pop ax
   278                              <1> @@:
   279 0000017D C3                  <1> 	retn
   280                              <1> 
   281                              <1> 
   282                              <1> 		; INP:	ds:bx -> range_decoder structure
   283                              <1> 		;	cx = num_bits
   284                              <1> 		;	ss:bp -> depack stack frame
   285                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   286                              <1> 		;	If success,
   287                              <1> 		;	 dx:ax = symbol
   288                              <1> 		; CHG:	di, cx
   289                              <1> Range_decoder.decode:
   290 0000017E 31D2                <1> 	xor dx, dx
   291 00000180 31C0                <1> 	xor ax, ax
   292 00000182 E32C                <1> 	jcxz .end
   293                              <1> .loop:
   294 00000184 D16F0A              <1> 	shr word [bx + range_decoder.range + 2], 1
   295 00000187 D15F08              <1> 	rcr word [bx + range_decoder.range], 1
   296 0000018A D1E0                <1> 	shl ax, 1
   297 0000018C D1D2                <1> 	rcl dx, 1
   298 0000018E 8B7F06              <1> 	mov di, word [bx + range_decoder.code + 2]
   299 00000191 3B7F0A              <1> 	cmp di, word [bx + range_decoder.range + 2]
   300 00000194 7506                <1> 	jne @F
   301 00000196 8B7F04              <1> 	mov di, word [bx + range_decoder.code]
   302 00000199 3B7F08              <1> 	cmp di, word [bx + range_decoder.range]
   303                              <1> @@:				; code >= range ?
   304 0000019C 720D                <1> 	jnae @F			; no, skip -->
   305 0000019E 8B7F08              <1> 	mov di, word [bx + range_decoder.range]
   306 000001A1 297F04              <1> 	sub word [bx + range_decoder.code], di
   307 000001A4 8B7F0A              <1> 	mov di, word [bx + range_decoder.range + 2]
   308 000001A7 197F06              <1> 	sbb word [bx + range_decoder.code + 2], di
   309 000001AA 40                  <1> 	inc ax			; symbol |= 1 (lowest bit always was zero)
   310                              <1> @@:
   311 000001AB E8A8FF              <1> 	call normaliserange
   312 000001AE E2D4                <1> 	loop .loop
   313                              <1> .end:
   314 000001B0 C3                  <1> 	retn
   315                              <1> 
   316                              <1> 
   317                              <1> 		; INP:	ds:bx -> range_decoder structure
   318                              <1> 		;	es:di -> bit_model structure
   319                              <1> 		;	ss:bp -> depack stack frame
   320                              <1> 		; OUT:	al = read bit
   321                              <1> 		;	NC if zero read
   322                              <1> 		;	CY if one read
   323                              <1> 		;	! If an error occurs, jumps to depack.error
   324                              <1> 		; CHG:	cx, dx, ax
   325                              <1> Range_decoder.decode_bit:
   326 000001B1 8B570A              <1> 	mov dx, word [bx + range_decoder.range + 2]
   327 000001B4 8B4708              <1> 	mov ax, word [bx + range_decoder.range]
   328 000001B7 B90B00              <1> 	mov cx, bit_model_total_bits
   329                              <1> @@:
   330 000001BA D1EA                <1> 	shr dx, 1
   331 000001BC D1D8                <1> 	rcr ax, 1
   332 000001BE E2FA                <1> 	loop @B
   333                              <1> 
   334 000001C0 89D1                <1> 	mov cx, dx
   335 000001C2 26F725              <1> 	mul word [es:di + bit_model.probability]
   336                              <1> 				; dx:ax = low word + first high word
   337 000001C5 52                  <1> 	 push dx
   338 000001C6 50                  <1> 	 push ax		; on stack = low word + first high word
   339 000001C7 91                  <1> 	xchg ax, cx
   340 000001C8 26F725              <1> 	mul word [es:di + bit_model.probability]
   341                              <1> 				; ax = second high word (dx overflow)
   342 000001CB 91                  <1> 	xchg ax, cx		; cx
   343 000001CC 58                  <1> 	 pop ax
   344 000001CD 5A                  <1> 	 pop dx
   345 000001CE 01CA                <1> 	add dx, cx		; = full uint32_t result
   346 000001D0 B90500              <1> 	mov cx, bit_model_move_bits
   347                              <1> 
   348 000001D3 395706              <1> 	cmp word [bx + range_decoder.code + 2], dx
   349 000001D6 7503                <1> 	jne @F
   350 000001D8 394704              <1> 	cmp word [bx + range_decoder.code], ax
   351                              <1> @@:
   352 000001DB 7317                <1> 	jnb .not_code_below_bound
   353                              <1> 
   354                              <1> .code_below_bound:
   355 000001DD 894708              <1> 	mov word [bx + range_decoder.range], ax
   356 000001E0 89570A              <1> 	mov word [bx + range_decoder.range + 2], dx
   357 000001E3 B80008              <1> 	mov ax, bit_model_total
   358 000001E6 262B05              <1> 	sub ax, word [es:di + bit_model.probability]
   359 000001E9 7228                <1> 	jc .error
   360 000001EB D3E8                <1> 	shr ax, cl
   361 000001ED 260105              <1> 	add word [es:di + bit_model.probability], ax
   362 000001F0 B000                <1> 	mov al, 0
   363 000001F2 EB18                <1> 	jmp .after_if
   364                              <1> 
   365                              <1> .not_code_below_bound:
   366 000001F4 294708              <1> 	sub word [bx + range_decoder.range], ax
   367 000001F7 19570A              <1> 	sbb word [bx + range_decoder.range + 2], dx
   368 000001FA 294704              <1> 	sub word [bx + range_decoder.code], ax
   369 000001FD 195706              <1> 	sbb word [bx + range_decoder.code + 2], dx
   370                              <1> 
   371 00000200 268B05              <1> 	mov ax, word [es:di + bit_model.probability]
   372 00000203 D3E8                <1> 	shr ax, cl
   373 00000205 262905              <1> 	sub word [es:di + bit_model.probability], ax
   374 00000208 7209                <1> 	jc .error
   375 0000020A B001                <1> 	mov al, 1
   376                              <1> 
   377                              <1> .after_if:
   378 0000020C E847FF              <1> 	call normaliserange
   379 0000020F 3C01                <1> 	cmp al, 1		; CY if 0, NC if 1
   380 00000211 F5                  <1> 	cmc			; NC if 0, CY if 1
   381 00000212 C3                  <1> 	retn
   382                              <1> 
   383                              <1> .error:
   384 00000213 E9E405              <1> 	jmp depack.error
   385                              <1> 
   386                              <1> 
   387                              <1> 		; INP:	ds:bx -> range_decoder structure
   388                              <1> 		;	es:di -> bit_model structure array
   389                              <1> 		;	cx = num_bits, <= 15
   390                              <1> 		;	ss:bp -> depack stack frame
   391                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   392                              <1> 		;	If success,
   393                              <1> 		;	 dx:ax = ax = symbol
   394                              <1> 		; CHG:	cx, si
   395                              <1> Range_decoder.decode_tree:
   396 00000216 BE0100              <1> 	mov si, 1		; symbol = 1
   397 00000219 83F90F              <1> 	cmp cx, 15
   398 0000021C 7721                <1> 	ja .error
   399 0000021E 51                  <1> 	push cx
   400 0000021F E312                <1> 	jcxz .end
   401                              <1> .loop:
   402 00000221 57                  <1> 	push di
   403                              <1> 		; Here si (symbol) is at most 1 << 14.
   404                              <1> %if bit_model_size != 2
   405                              <1>  %error Assuming word size for bit_model_size
   406                              <1> %endif
   407 00000222 D1E6                <1> 	shl si, 1		; Note that this shift is both used instead of
   408                              <1> 				;  multiplying symbol (si) by bit_model_size
   409                              <1> 				;  and to actually shift symbol (si) left!
   410 00000224 01F7                <1> 	add di, si		; index into bit_model array
   411 00000226 7217                <1> 	jc .error_pop_2
   412 00000228 51                  <1> 	push cx
   413 00000229 E885FF              <1> 	call Range_decoder.decode_bit
   414 0000022C 59                  <1> 	pop cx
   415 0000022D 83D600              <1> 	adc si, 0		; add in the decoded bit
   416 00000230 5F                  <1> 	pop di
   417 00000231 E2EE                <1> 	loop .loop
   418                              <1> .end:
   419 00000233 59                  <1> 	pop cx
   420 00000234 B80100              <1> 	mov ax, 1
   421 00000237 D3E0                <1> 	shl ax, cl		; = 1 << num_bits
   422 00000239 29C6                <1> 	sub si, ax		; symbol - ( 1 << num_bits )
   423 0000023B 96                  <1> 	xchg ax, si
   424 0000023C 31D2                <1> 	xor dx, dx		; return symbol
   425 0000023E C3                  <1> 	retn
   426                              <1> 
   427                              <1> .error_pop_2:
   428                              <1> .error:
   429 0000023F E9B805              <1> 	jmp depack.error
   430                              <1> 
   431                              <1> 
   432                              <1> 		; INP:	ds:bx -> range_decoder structure
   433                              <1> 		;	es:di -> bit_model structure array
   434                              <1> 		;	cx = num_bits, <= 15
   435                              <1> 		;	ss:bp -> depack stack frame
   436                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   437                              <1> 		;	If success,
   438                              <1> 		;	 dx:ax = ax = reversed_symbol
   439                              <1> 		; CHG:	cx, si
   440                              <1> Range_decoder.decode_tree_reversed:
   441 00000242 51                  <1> 	push cx
   442 00000243 E8D0FF              <1> 	call Range_decoder.decode_tree
   443 00000246 59                  <1> 	pop cx
   444 00000247 92                  <1> 	xchg dx, ax		; dx = symbol
   445 00000248 31C0                <1> 	xor ax, ax		; = reversed_symbol
   446 0000024A E306                <1> 	jcxz .end
   447                              <1> .loop:
   448 0000024C D1EA                <1> 	shr dx, 1
   449 0000024E D1D0                <1> 	rcl ax, 1
   450 00000250 E2FA                <1> 	loop .loop
   451                              <1> .end:
   452 00000252 31D2                <1> 	xor dx, dx
   453 00000254 C3                  <1> 	retn
   454                              <1> 
   455                              <1> 
   456                              <1> 		; INP:	ds:bx -> range_decoder structure
   457                              <1> 		;	es:di -> bit_model structure array
   458                              <1> 		;	al = match_byte
   459                              <1> 		;	ss:bp -> depack stack frame
   460                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   461                              <1> 		;	If success,
   462                              <1> 		;	 al = return value (symbol & 0FFh)
   463                              <1> 		; CHG:	cx, dx, ax
   464                              <1> Range_decoder.decode_matched:
   465 00000255 88C6                <1> 	mov dh, al		; = match_byte
   466                              <1> 
   467 00000257 B80100              <1> 	mov ax, 1		; initialise symbol = 1
   468                              <1> 
   469 0000025A B90800              <1> 	mov cx, 8
   470                              <1> .loop:
   471 0000025D 52                  <1> 	push dx			; preserve dh = match_byte
   472 0000025E 51                  <1> 	push cx			; preserve loop counter
   473 0000025F 49                  <1> 	dec cx
   474 00000260 D2EE                <1> 	shr dh, cl		; match_byte >> i
   475 00000262 81E20001            <1> 	and dx, 100h		; dh &= 1 = match_bit, dl = 0
   476 00000266 52                  <1> 	push dx
   477 00000267 FEC6                <1> 	inc dh			; = (match_bit << 8) + 100h
   478 00000269 01C2                <1> 	add dx, ax		; = symbol + (match_bit << 8) + 100h
   479                              <1> 		; As symbol is below 256, this is at most 255 + 100h + 100h,
   480                              <1> 		;  which is 2FFh. As such, the bm_literal array's
   481                              <1> 		;  entries are arrays of 300h bit_model each.
   482 0000026B 57                  <1> 	push di
   483 0000026C 50                  <1> 	push ax
   484                              <1> %if bit_model_size != 2
   485                              <1>  %error Assuming word size for bit_model_size
   486                              <1> %endif
   487 0000026D 01D2                <1> 	add dx, dx
   488                              <1> 		; As dx was < 300h before this addition, it cannot carry.
   489 0000026F 01D7                <1> 	add di, dx
   490                              <1> 		; We assume that this does not carry.
   491 00000271 E83DFF              <1> 	call Range_decoder.decode_bit
   492 00000274 91                  <1> 	xchg ax, cx		; cl = result (1 or 0)
   493 00000275 58                  <1> 	pop ax			; = symbol
   494 00000276 5F                  <1> 	pop di
   495 00000277 5A                  <1> 	pop dx			; = match_bit << 8
   496 00000278 D1D0                <1> 	rcl ax, 1		; shift symbol, OR in the bit
   497                              <1> 		; As the loop counter is initialised to 8,
   498                              <1> 		;  the symbol variable stays below 256.
   499 0000027A 38F1                <1> 	cmp cl, dh		; if( match_bit != bit ) ...-
   500 0000027C 59                  <1> 	pop cx			; = loop counter
   501 0000027D 5A                  <1> 	pop dx			; = dh = match_byte
   502 0000027E 7519                <1> 	jne .inner_next		; -... do the following -->
   503                              <1> .next:
   504 00000280 E2DB                <1> 	loop .loop
   505                              <1> .end:
   506 00000282 30E4                <1> 	xor ah, ah		; return ax = symbol & 0FFh
   507 00000284 C3                  <1> 	retn
   508                              <1> 
   509                              <1> .error_pop_2:
   510                              <1> .error:
   511 00000285 E97205              <1> 	jmp depack.error
   512                              <1> 
   513                              <1> 
   514                              <1> .inner_loop:
   515 00000288 50                  <1> 	push ax
   516                              <1> %if bit_model_size != 2
   517                              <1>  %error Assuming word size for bit_model_size
   518                              <1> %endif
   519 00000289 01C0                <1> 	add ax, ax
   520 0000028B 57                  <1> 	push di
   521 0000028C 01C7                <1> 	add di, ax
   522 0000028E 72F5                <1> 	jc .error_pop_2
   523 00000290 E81EFF              <1> 	call Range_decoder.decode_bit
   524 00000293 5F                  <1> 	pop di
   525 00000294 58                  <1> 	pop ax
   526 00000295 D1D0                <1> 	rcl ax, 1
   527 00000297 72EC                <1> 	jc .error
   528                              <1> 
   529                              <1> .inner_next:
   530 00000299 3D0001              <1> 	cmp ax, 100h
   531 0000029C 72EA                <1> 	jb .inner_loop
   532 0000029E EBE2                <1> 	jmp .end
   533                              <1> 
   534                              <1> 
   535                              <1> 		; INP:	ds:bx -> range_decoder structure
   536                              <1> 		;	es:di -> len_model structure
   537                              <1> 		;	ax = pos_state
   538                              <1> 		;	ss:bp -> depack stack frame
   539                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   540                              <1> 		;	If success,
   541                              <1> 		;	 dx:ax = return
   542                              <1> 		; CHG:	cx, si
   543                              <1> Range_decoder.decode_len:
   544 000002A0 89C6                <1> 	mov si, ax		; = pos_state
   545 000002A2 57                  <1> 	 push di		; = len_model_struc (on stack)
   546                              <1> 
   547 000002A3 8D3D                <1> 	lea di, [di + len_model.choice1]
   548 000002A5 E809FF              <1> 	call Range_decoder.decode_bit
   549 000002A8 5F                  <1> 	 pop di			; reset to ?len_model_struc
   550 000002A9 57                  <1> 	 push di
   551 000002AA 7218                <1> 	jc .not_decode_bit_choice1_equals_zero
   552                              <1> 
   553 000002AC 8D7D04              <1> 	lea di, [di + len_model.bm_low]
   554 000002AF B81000              <1> 	mov ax, len_low_symbols * bit_model_size
   555 000002B2 F7E6                <1> 	mul si
   556 000002B4 85D2                <1> 	test dx, dx
   557 000002B6 7546                <1> 	jnz .error
   558 000002B8 01C7                <1> 	add di, ax
   559 000002BA 7242                <1> 	jc .error
   560 000002BC B90300              <1> 	mov cx, len_low_bits
   561 000002BF E854FF              <1> 	call Range_decoder.decode_tree
   562 000002C2 EB38                <1> 	jmp .ret
   563                              <1> 
   564                              <1> .not_decode_bit_choice1_equals_zero:
   565 000002C4 8D7D02              <1> 	lea di, [di + len_model.choice2]
   566 000002C7 E8E7FE              <1> 	call Range_decoder.decode_bit
   567 000002CA 5F                  <1> 	 pop di			; reset to ?len_model_struc
   568 000002CB 57                  <1> 	 push di
   569 000002CC 721E                <1> 	jc .not_decode_bit_choice2_equals_zero
   570                              <1> 
   571 000002CE 8D7D44              <1> 	lea di, [di + len_model.bm_mid]
   572 000002D1 B81000              <1> 	mov ax, len_mid_symbols * bit_model_size
   573 000002D4 F7E6                <1> 	mul si
   574 000002D6 85D2                <1> 	test dx, dx
   575 000002D8 7524                <1> 	jnz .error
   576 000002DA 01C7                <1> 	add di, ax
   577 000002DC 7220                <1> 	jc .error
   578 000002DE B90300              <1> 	mov cx, len_mid_bits
   579 000002E1 E832FF              <1> 	call Range_decoder.decode_tree
   580 000002E4 83C008              <1> 	add ax, len_low_symbols & 0FFFFh
   581 000002E7 83D200              <1> 	adc dx, len_low_symbols >> 16
   582 000002EA EB10                <1> 	jmp .ret
   583                              <1> 
   584                              <1> .not_decode_bit_choice2_equals_zero:
   585 000002EC 8DBD8400            <1> 	lea di, [di + len_model.bm_high]
   586 000002F0 B90800              <1> 	mov cx, len_high_bits
   587 000002F3 E820FF              <1> 	call Range_decoder.decode_tree
   588 000002F6 83C010              <1> 	add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh
   589 000002F9 83D200              <1> 	adc dx, (len_low_symbols + len_mid_symbols) >> 16
   590                              <1> .ret:
   591 000002FC 5F                  <1> 	 pop di
   592 000002FD C3                  <1> 	retn
   593                              <1> 
   594                              <1> .error:
   595 000002FE E9F904              <1> 	jmp depack.error
   596                              <1> 
   597                              <1> 
   598                              <1> 	struc lz_decoder
   599 00000000 <res Ch>            <1> .range_decoder:		resb range_decoder_size
   600 0000000C ????????            <1> 			alignb 8
   601 00000010 ????????            <1> .dictionary_size:	resd 1
   602 00000014 ????????            <1> .pos:			resd 1
   603                              <1> 	endstruc
   604                              <1> 
   605                              <1> 
   606                              <1> 		; INP:	ds:bx -> lz_decoder structure, localvariables structure
   607                              <1> 		;	dx:ax = distance
   608                              <1> 		; OUT:	al = ax = byte from buffer
   609                              <1> 		; CHG:	dx, cx, di, si, es
   610                              <1> LZ_decoder.peek:
   611 00000301 395716              <1> 	cmp word [bx + lz_decoder.pos + 2], dx
   612 00000304 7503                <1> 	jne @F
   613 00000306 394714              <1> 	cmp word [bx + lz_decoder.pos], ax
   614                              <1> @@:
   615 00000309 760A                <1> 	jna .not_pos_above_distance
   616                              <1> 
   617 0000030B E80A00              <1> 	call calculate_peek_pointer_disi
   618                              <1> 
   619 0000030E 8EC7                <1> 	mov es, di			; es:si -> peek address
   620 00000310 31C0                <1> 	xor ax, ax
   621 00000312 26AC                <1> 	es lodsb
   622 00000314 C3                  <1> 	retn
   623                              <1> 
   624                              <1> .not_pos_above_distance:
   625 00000315 31C0                <1> 	xor ax, ax
   626 00000317 C3                  <1> 	retn
   627                              <1> 
   628                              <1> 
   629                              <1> 		; INP:	dx:ax = peek distance
   630                              <1> 		;	ds:bx -> local variables
   631                              <1> 		; OUT:	di:si -> peek address
   632                              <1> 		; CHG:	cx, dx, ax
   633                              <1> calculate_peek_pointer_disi:
   634 00000318 53                  <1> 	push bx
   635 00000319 FF772E              <1> 	 push word [bx + destinationbuffer_constant + 2]
   636 0000031C FF772C              <1> 	 push word [bx + destinationbuffer_constant]
   637                              <1> 
   638 0000031F F7DA                <1> 	neg dx
   639 00000321 F7D8                <1> 	neg ax
   640 00000323 83DA00              <1> 	sbb dx, byte 0			; neg dx:ax = - distance
   641 00000326 83E801              <1> 	sub ax, 1
   642 00000329 83DA00              <1> 	sbb dx, 0			; - 1
   643 0000032C 034714              <1> 	add ax, word [bx + lz_decoder.pos]
   644 0000032F 135716              <1> 	adc dx, word [bx + lz_decoder.pos + 2]
   645                              <1> 					; + pos
   646 00000332 91                  <1> 	xchg cx, ax
   647 00000333 87DA                <1> 	xchg bx, dx
   648                              <1> 
   649 00000335 E86E06              <1> 	call normalise_pointer_with_displacement_bxcx
   650 00000338 5E                  <1> 	 pop si
   651 00000339 5F                  <1> 	 pop di				; di:si -> source
   652 0000033A 5B                  <1> 	pop bx
   653 0000033B C3                  <1> 	retn
   654                              <1> 
   655                              <1> 
   656                              <1> 		; INP:	ss:bp -> depack stack frame
   657                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
   658                              <1> 		;	If success,
   659                              <1> 		;	 al = byte
   660                              <1> 		; CHG:	-
   661                              <1> LZ_decoder.get_byte: equ Range_decoder.get_byte
   662                              <1> 
   663                              <1> 
   664                              <1> 	struc localvariables
   665                              <1> lz_decoder_struc:
   666 00000000 <res 18h>           <1> 		resb lz_decoder_size
   667                              <1> 		alignb 4
   668                              <1> zeros_start:
   669 00000018 ????????            <1> rep0:		resd 1
   670 0000001C ????????            <1> rep1:		resd 1
   671 00000020 ????????            <1> rep2:		resd 1
   672 00000024 ????????            <1> rep3:		resd 1
   673 00000028 ????                <1> state.st:	resw 1		; initialise to zero
   674 0000002A ????                <1> 		alignb 4
   675                              <1> zeros_end:
   676 0000002C ????????            <1> destinationbuffer_constant:	resd 1		; stays constant
   677                              <1> 		alignb 16
   678                              <1> bit_models_start:
   679 00000030 <res 60h>           <1> bm_match:	resb bit_model_size * amount_states * pos_states
   680 00000090 <res 18h>           <1> bm_rep:		resb bit_model_size * amount_states
   681 000000A8 <res 18h>           <1> bm_rep0:	resb bit_model_size * amount_states
   682 000000C0 <res 18h>           <1> bm_rep1:	resb bit_model_size * amount_states
   683 000000D8 <res 18h>           <1> bm_rep2:	resb bit_model_size * amount_states
   684 000000F0 <res 3000h>         <1> bm_literal:	resb bit_model_size * (1 << literal_context_bits) * 300h
   685 000030F0 <res 60h>           <1> bm_len:		resb bit_model_size * amount_states * pos_states
   686 00003150 <res 200h>          <1> bm_dis_slot:	resb bit_model_size * len_states * (1 << dis_slot_bits)
   687 00003350 <res E6h>           <1> bm_dis:		resb bit_model_size * (modeled_distances - end_dis_model + 1)
   688 00003436 <res 20h>           <1> bm_align:	resb bit_model_size * dis_align_size
   689 00003456 <res 284h>          <1> match_len_model:resb len_model_size
   690 000036DA <res 284h>          <1> rep_len_model:	resb len_model_size
   691                              <1> bit_models_end:
   692 0000395E ????                <1> 		alignb 16
   693                              <1> 	endstruc
   694                              <1> %if lz_decoder_struc != 0
   695                              <1>  %error Expecting lz_decoder structure at start of localvariables structure
   696                              <1> %endif
   697                              <1> %assign STRUCSIZE localvariables_size
   698                              <1> %warning localvariables has STRUCSIZE bytes
   698          ******************  <1>  warning: localvariables has 14688 bytes [-w+user]
   699                              <1> 
   700                              <1> 
   701                              <1> 	align 4
   702                              <1> lzip_header_bytes:
   703                              <1> .:
   704 0000033C 4C5A495001          <1> 	db "LZIP",1
   705                              <1> .length: equ $ - .
   706                              <1> 
   707                              <1> 
   708                              <1> 		; INP:	ds:si -> source
   709                              <1> 		;	dx:cx = length of source
   710                              <1> 		;	es:di -> destination (below source)
   711                              <1> 		;	if _IMAGE_EXE:
   712                              <1> 		;	 bx = EXE mode flag (bit 0)
   713                              <1> 		;	else:
   714                              <1> 		;	 bx = 0
   715                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
   716                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
   717                              <1> 		;	 (-1 if full source should be decompressed)
   718                              <1> 		;	else:
   719                              <1> 		;	 ax = -1
   720                              <1> 		; OUT:	NC if success
   721                              <1> 		;	CY if error,
   722                              <1> 		;	 bx = ?errordata (if _DEBUG0)
   723                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
   724                              <1> 		; STT:	UP
   725                              <1> 		;
   726                              <1> 		; Note:	The destination reaches up to below the source.
   727                              <1> 		; Note:	The input pointers need not be normalised yet.
   728                              <1> 		;	 Normalised means that the offset part is below 16.
   729                              <1> depack:
   730                              <1> 	lframe near
   731                              <1> %if _IMAGE_EXE || _COUNTER || _DEBUG0
   732 00000341 5589E5              <1> 	lenter early
   733                              <1>  %if _IMAGE_EXE
   734                              <1> 	lvar word,	exemode	; must be bp - 2!
   735 00000344 53                  <1> 	 push bx
   736                              <1>   %if ?exemode != -2
   737                              <1>    %error exemode variable must be directly below bp
   738                              <1>   %endif
   739                              <1>  %endif
   740                              <1>  %if _COUNTER || _DEBUG0
   741                              <1> 	xor bx, bx
   742                              <1>  %endif
   743                              <1> %endif
   744                              <1> %if _COUNTER
   745                              <1> 	lvar word,	counter
   746                              <1> 	 push bx		; initialise counter to zero
   747                              <1> %endif
   748                              <1> d0	lvar word,	errordata
   749                              <1> d0	 push bx
   750                              <1> 	lvar dword,	distance
   751                              <1> 	lvar dword,	len
   752                              <1> 	lvar dword,	dis_slot
   753                              <1> 	lvar word,	len_state
   754                              <1> 	lvar word,	pos_state
   755 00000345 8D66EE              <1> 	lenter
   756                              <1> 
   757 00000348 E82A06              <1> 	call normalise_both_pointers
   758                              <1> 
   759                              <1> 		; ! di < 16, so dih == 0
   760                              <1> 	lvar dword,	src
   761 0000034B 1E                  <1> 	 push ds
   762 0000034C 56                  <1> 	 push si
   763                              <1> 	lvar dword,	final_dst
   764 0000034D 06                  <1> 	 push es
   765 0000034E 57                  <1> 	 push di
   766                              <1> 	lequ ?final_dst,	localvariables
   767                              <1> 		; ! offset of ?localvariables is always < 16
   768                              <1> 		;  required for State.set_char with _XLATBSEQ == 5
   769                              <1> 	lvar dword,	length_of_source
   770 0000034F 52                  <1> 	 push dx
   771 00000350 51                  <1> 	 push cx
   772                              <1> 
   773                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
   774                              <1> 	cmp ax, -1		; no maximum specified ?
   775                              <1> 	je @FF			; retain -1 in ax -->
   776                              <1> 	test di, di		; do we need an additional paragraph ?
   777                              <1> 	jz @F			; no -->
   778                              <1> 	inc ax			; es + ax => paragraph after necessary part
   779                              <1> @@:
   780                              <1> 	mov dx, es
   781                              <1> 	add ax, dx		; => paragraph after necessary part
   782                              <1> 		; If the normalised destination pointer's segment grows
   783                              <1> 		;  to this segment then enough has been decompressed.
   784                              <1> d0	mov byte [bp + ?errordata], 40h
   785                              <1> 	jc .error_CY_a1		; should not carry
   786                              <1> @@:
   787                              <1> 	lvar word,	dst_max_segment
   788                              <1> 	 push ax
   789                              <1> %endif
   790                              <1> 
   791 00000351 1E                  <1> 	 push ds
   792 00000352 56                  <1> 	 push si
   793 00000353 E87F06              <1> 	call pointer_to_linear
   794                              <1> 
   795 00000356 87DA                <1> 	xchg bx, dx
   796 00000358 91                  <1> 	xchg cx, ax		; bx:cx = source linear, clobber dx:ax
   797                              <1> 
   798 00000359 06                  <1> 	 push es
   799 0000035A 57                  <1> 	 push di
   800 0000035B E87706              <1> 	call pointer_to_linear
   801                              <1> 
   802                              <1> %if _ALLOW_OVERLAPPING
   803 0000035E 034EE2              <1> 	add cx, word [bp + ?length_of_source]
   804 00000361 135EE4              <1> 	adc bx, word [bp + ?length_of_source + 2]
   805                              <1> 		; In case of allowing overlapping source and destination,
   806                              <1> 		;  the ?length_of_destination variable is set to
   807                              <1> 		;  ?src + ?length_of_source - ?dst, allowing to write to
   808                              <1> 		;  all of the source buffer (with the checks already in place
   809                              <1> 		;  from the default handling). Additional checks are done by
   810                              <1> 		;  calling check_pointers_not_overlapping. This is done after
   811                              <1> 		;  every change of ?dst to verify that the write pointer stays
   812                              <1> 		;  below-or-equal the read pointer.
   813                              <1> 		; This means the remaining source data may be corrupted by a
   814                              <1> 		;  write, but nothing after the source data is written to,
   815                              <1> 		;  so the error handling (in INIT1 after the data) still works.
   816                              <1> %endif
   817                              <1> 
   818 00000364 29C1                <1> 	sub cx, ax
   819 00000366 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   820                              <1> 
   821 00000368 81E96039            <1> 	sub cx, localvariables_size & 0FFFFh
   822 0000036C 83DB00              <1> 	sbb bx, localvariables_size >> 16
   823 0000036F 7703E98604          <1> 	jbe .error		; make variables buffer available
   824                              <1> 
   825                              <1> 	lvar dword,	length_of_destination
   826 00000374 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   827 00000375 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   828                              <1> 
   829 00000376 06                  <1> 	push es
   830 00000377 57                  <1> 	push di
   831                              <1> %if localvariables_size >> 16
   832                              <1> 	mov bx, localvariables_size >> 16
   833                              <1> %else
   834 00000378 31DB                <1> 	xor bx, bx
   835                              <1> %endif
   836 0000037A B96039              <1> 	mov cx, localvariables_size & 0FFFFh
   837 0000037D E82606              <1> 	call normalise_pointer_with_displacement_bxcx
   838 00000380 5F                  <1> 	pop di
   839 00000381 07                  <1> 	pop es
   840                              <1> 
   841                              <1> 	lvar dword,	original_dst
   842 00000382 06                  <1> 	 push es
   843 00000383 57                  <1> 	 push di
   844                              <1> 	lvar dword,	dst
   845 00000384 06                  <1> 	 push es
   846 00000385 57                  <1> 	 push di
   847                              <1> 
   848                              <1> %if _ALLOW_OVERLAPPING
   849 00000386 E8D005              <1> 	call check_pointers_not_overlapping
   850                              <1> 		; Note:	We initially check here that the write pointer is
   851                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   852                              <1> 		;	Unlike the other decompressors, this check is done
   853                              <1> 		;	 after any copied match or literal too, because
   854                              <1> 		;	 literals can presumably be encoded with less than
   855                              <1> 		;	 one byte of source data to the range decoder.
   856                              <1> d0	mov byte [bp + ?errordata], 1Bh
   857                              <1> .error_CY_a1:
   858 00000389 7243                <1> 	jc short .error_CY_a
   859                              <1> %else
   860                              <1>  .error_CY_a1 equ .error_CY_a
   861                              <1> %endif
   862                              <1> 
   863                              <1> 
   864                              <1> member_min_size equ lzip_header_size + lzip_trailer_size
   865                              <1> 
   866                              <1> .loop_member:
   867 0000038B 837EE400            <1> 	cmp word [bp + ?length_of_source + 2], 0
   868 0000038F 7504                <1> 	jne @F
   869 00000391 837EE21A            <1> 	cmp word [bp + ?length_of_source], member_min_size
   870                              <1> @@:
   871 00000395 770F                <1> 	ja .got_member
   872                              <1> 
   873 00000397 837EE400            <1> 	cmp word [bp + ?length_of_source + 2], 0
   874 0000039B 7504                <1> 	jne @F
   875 0000039D 837EE20F            <1> 	cmp word [bp + ?length_of_source], 15
   876                              <1> @@:
   877 000003A1 7710                <1> 	ja short .error_NZ_a		; (NZ if jumping)
   878 000003A3 E92004              <1> 	jmp .end
   879                              <1> 
   880                              <1> .got_member:
   881 000003A6 C576EA              <1> 	lds si, [bp + ?src]		; ds:si -> lzip_header.magic, .version
   882 000003A9 0E                  <1> 	push cs
   883 000003AA 07                  <1> 	pop es
   884 000003AB BF[3C03]            <1> 	mov di, lzip_header_bytes
   885 000003AE B90500              <1> 	mov cx, lzip_header_bytes.length
   886 000003B1 F3A6                <1> 	repe cmpsb
   887                              <1> .error_NZ_a:
   888 000003B3 7403E94204          <1> 	jne .error
   889                              <1> %if _COUNTER
   890                              <1> 	mov al, '#'
   891                              <1> 	call disp_al
   892                              <1> %endif
   893 000003B8 31C0                <1> 	xor ax, ax
   894 000003BA AC                  <1> 	lodsb				; ax = lzip_header.coded_dict_size
   895                              <1> 
   896 000003BB 1E                  <1> 	 push ds
   897 000003BC 56                  <1> 	 push si
   898 000003BD E8C405              <1> 	call normalise_pointer
   899 000003C0 8F46EA              <1> 	 pop word [bp + ?src]
   900 000003C3 8F46EC              <1> 	 pop word [bp + ?src + 2]
   901 000003C6 836EE206            <1> 	sub word [bp + ?length_of_source], 6
   902 000003CA 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
   903                              <1> .error_CY_a:
   904 000003CE 7235                <1> 	jc short .error_CY_b
   905                              <1> 
   906 000003D0 50                  <1> 	push ax
   907 000003D1 241F                <1> 	and al, 1Fh
   908 000003D3 91                  <1> 	xchg cx, ax			; cx = coded dict size & 1Fh, clobber ax
   909 000003D4 B80100              <1> 	mov ax, 1
   910 000003D7 31D2                <1> 	xor dx, dx
   911                              <1> @@:
   912 000003D9 D1E0                <1> 	shl ax, 1
   913 000003DB D1D2                <1> 	rcl dx, 1
   914 000003DD E2FA                <1> 	loop @B
   915                              <1> 
   916 000003DF 89D3                <1> 	mov bx, dx
   917 000003E1 89C7                <1> 	mov di, ax			; bx:di = dict_size
   918 000003E3 B104                <1> 	mov cl, 4
   919                              <1> @@:
   920 000003E5 D1EB                <1> 	shr bx, 1
   921 000003E7 D1DF                <1> 	rcr di, 1
   922 000003E9 E2FA                <1> 	loop @B				; bx:di = dict_size / 16
   923 000003EB 59                  <1> 	pop cx
   924 000003EC 88CD                <1> 	mov ch, cl
   925 000003EE B105                <1> 	mov cl, 5
   926 000003F0 D2ED                <1> 	shr ch, cl
   927 000003F2 88E9                <1> 	mov cl, ch
   928 000003F4 B500                <1> 	mov ch, 0
   929 000003F6 E331                <1> 	jcxz @FF
   930                              <1> 
   931 000003F8 52                  <1> 	push dx
   932 000003F9 50                  <1> 	push ax
   933                              <1> 
   934 000003FA 89F8                <1> 	mov ax, di			; ax = low word of input
   935 000003FC F7E1                <1> 	mul cx
   936 000003FE 93                  <1> 	xchg ax, bx			; ax = high word of input
   937 000003FF 89D7                <1> 	mov di, dx			; di:bx = low word + first high word
   938 00000401 F7E1                <1> 	mul cx				; = high word
   939 00000403 01C7                <1> 	add di, ax			; add into sum
   940                              <1> .error_CY_b:
   941 00000405 7217                <1> 	jc short .error_CY_c
   942 00000407 85D2                <1> 	test dx, dx			; overflows ?
   943 00000409 7403E9EC03          <1> 	jnz .error
   944                              <1> 					; bx:di = dict_size / 16 * fraction
   945 0000040E 58                  <1> 	pop ax
   946 0000040F 5A                  <1> 	pop dx
   947 00000410 29D8                <1> 	sub ax, bx
   948 00000412 19FA                <1> 	sbb dx, di
   949 00000414 7208                <1> 	jc short .error_CY_c
   950                              <1> 
   951 00000416 83FA00              <1> 	cmp dx, min_dictionary_size >> 16
   952 00000419 7503                <1> 	jne @F
   953 0000041B 3D0010              <1> 	cmp ax, min_dictionary_size & 0FFFFh
   954                              <1> @@:
   955                              <1> .error_CY_c:
   956 0000041E 7265                <1> 	jb short .error_CY_d
   957                              <1> 
   958 00000420 81FA0020            <1> 	cmp dx, max_dictionary_size >> 16
   959 00000424 7503                <1> 	jne @F
   960 00000426 83F800              <1> 	cmp ax, max_dictionary_size & 0FFFFh
   961                              <1> @@:
   962 00000429 7603E9CC03          <1> 	ja .error
   963                              <1> 
   964 0000042E C55EE6              <1> 	lds bx, [bp + ?final_dst]
   965 00000431 FF76D8              <1> 	push word [bp + ?dst + 2]
   966 00000434 FF76D6              <1> 	push word [bp + ?dst]
   967 00000437 8F472C              <1> 	pop word [bx + destinationbuffer_constant]
   968 0000043A 8F472E              <1> 	pop word [bx + destinationbuffer_constant + 2]
   969                              <1> 
   970                              <1> 
   971                              <1> 		; decode_member start (inlined)
   972                              <1> 		; INP:	?localvariables = ds:bx -> localvariables structure,
   973                              <1> 		;	 destinationbuffer_constant pre-initialised
   974                              <1> 		;	dx:ax = dictionary size
   975                              <1> 		;	Following variables of depack frame initialised:
   976                              <1> 		;	 dword [ss:bp + ?src] -> source buffer
   977                              <1> 		;	 dword [ss:bp + ?length_of_source] = remaining length
   978                              <1> 		;	 dword [ss:bp + ?dst] -> destination buffer
   979                              <1> 		;	 dword [ss:bp + ?length_of_destination] = remaining
   980                              <1> 		; OUT:	NC if success
   981                              <1> 		;	CY if error
   982                              <1> 		; CHG:	all
   983                              <1> ; LZ_decoder.decode_member:
   984                              <1> 
   985 0000043D 52                  <1> 	 push dx
   986 0000043E 50                  <1> 	 push ax			; preserve dictionary size
   987 0000043F 1E                  <1> 	push ds
   988 00000440 07                  <1> 	pop es
   989 00000441 89DF                <1> 	mov di, bx
   990 00000443 B90C00              <1> 	mov cx, fromdwords(dwords(lz_decoder_size)) / 2
   991 00000446 31C0                <1> 	xor ax, ax
   992 00000448 F3AB                <1> 	rep stosw			; initialise lz_decoder structure
   993                              <1> 
   994 0000044A E8F0FC              <1> 	call Range_decoder.init		; initialise embedded range_decoder
   995                              <1> 
   996 0000044D 8F4710              <1> 	 pop word [bx + lz_decoder.dictionary_size]
   997 00000450 8F4712              <1> 	 pop word [bx + lz_decoder.dictionary_size + 2]
   998                              <1> 					; set dictionary size
   999                              <1> 
  1000 00000453 8D7F30              <1> 	lea di, [bx + bit_models_start]
  1001 00000456 B9971C              <1> 	mov cx, (bit_models_end - bit_models_start) / bit_model_size
  1002 00000459 B80004              <1> 	mov ax, bit_model_total / 2	; initial value for bit_model
  1003                              <1> %if bit_model_size != 2
  1004                              <1>  %error Assuming word size for bit_model_size
  1005                              <1> %endif
  1006 0000045C F3AB                <1> 	rep stosw			; initialise this bit_model
  1007                              <1> 					; loop for all bit_model and len_model
  1008                              <1> 
  1009 0000045E 8D7F18              <1> 	lea di, [bx + zeros_start]
  1010 00000461 31C0                <1> 	xor ax, ax
  1011 00000463 B10A                <1> 	mov cl, (zeros_end - zeros_start) / 2
  1012 00000465 F3AB                <1> 	rep stosw
  1013                              <1> 
  1014                              <1> .loop:
  1015                              <1> %if _COUNTER
  1016                              <1> 	inc byte [bp + ?counter]
  1017                              <1> 	test byte [bp + ?counter], _COUNTER - 1
  1018                              <1> 	jnz @F
  1019                              <1> 	mov al, '.'
  1020                              <1> 	call disp_al
  1021                              <1> @@:
  1022                              <1> %endif
  1023 00000467 8B5EE6              <1> 	mov bx, word [bp + ?localvariables]
  1024 0000046A 8B4714              <1> 	mov ax, word [bx + lz_decoder.pos]
  1025 0000046D 83E003              <1> 	and ax, pos_state_mask
  1026 00000470 91                  <1> 	xchg cx, ax			; cx = pos_state, ax clobbered
  1027 00000471 894EEE              <1> 	mov word [bp + ?pos_state], cx
  1028                              <1> 
  1029 00000474 1E                  <1> 	push ds
  1030 00000475 07                  <1> 	pop es
  1031 00000476 8D7F30              <1> 	lea di, [bx + bm_match]		; es:di -> bm_match 2D array
  1032 00000479 B80800              <1> 	mov ax, bit_model_size * pos_states
  1033 0000047C F76728              <1> 	mul word [bx + state.st]	; dx:ax = first index is state
  1034                              <1> 		; bit_model_size = 2
  1035                              <1> 		; pos_states = 4
  1036                              <1> 		; state.st < 12
  1037                              <1> 		; multiplication 2 * 4 * 11 = 88
  1038                              <1> %if bit_model_size != 2
  1039                              <1>  %error Assuming word size for bit_model_size
  1040                              <1> %endif
  1041 0000047F 01C9                <1> 	add cx, cx			; = second index (from pos_state)
  1042                              <1> 		; pos_state < 4
  1043                              <1> 		; cx < 8
  1044                              <1> 		; ax <= 88
  1045 00000481 01C8                <1> 	add ax, cx			; = second index is pos_state
  1046 00000483 01C7                <1> 	add di, ax			; es:di -> bm_match[state()][pos_state]
  1047                              <1> .error_CY_d:
  1048 00000485 7222                <1> 	jc short .error_CY_1
  1049 00000487 E827FD              <1> 	call Range_decoder.decode_bit
  1050 0000048A 7244                <1> 	jc .1st_bit_not_zero
  1051                              <1> 
  1052                              <1> .1st_bit_zero:			; literal byte
  1053 0000048C 31C0                <1> 	xor ax, ax
  1054 0000048E 31D2                <1> 	xor dx, dx
  1055 00000490 E86EFE              <1> 	call LZ_decoder.peek		; al = prev_byte
  1056                              <1> 
  1057 00000493 B105                <1> 	mov cl, 8 - literal_context_bits
  1058 00000495 D2E8                <1> 	shr al, cl			; = literal_state
  1059 00000497 1E                  <1> 	push ds
  1060 00000498 07                  <1> 	pop es
  1061 00000499 8DBFF000            <1> 	lea di, [bx + bm_literal]	; -> 2D array bm_literal
  1062 0000049D B90006              <1> 	mov cx, bit_model_size * 300h
  1063 000004A0 F7E1                <1> 	mul cx				; first index is literal_state
  1064 000004A2 85D2                <1> 	test dx, dx
  1065 000004A4 F9                  <1> 	stc
  1066 000004A5 7502                <1> 	jnz short .error_CY_1
  1067 000004A7 01C7                <1> 	add di, ax			; es:di -> bm_literal[literal_state]
  1068                              <1> .error_CY_1:
  1069 000004A9 7232                <1> 	jc short .error_CY_2
  1070                              <1> 
  1071 000004AB E86DFC              <1> 	call State.is_char
  1072 000004AE 7308                <1> 	jnc .not_is_char
  1073                              <1> .is_char:
  1074 000004B0 B90800              <1> 	mov cx, 8
  1075 000004B3 E860FD              <1> 	call Range_decoder.decode_tree
  1076 000004B6 EB10                <1> 	jmp @F
  1077                              <1> 
  1078                              <1> .not_is_char:
  1079 000004B8 8B4718              <1> 	mov ax, word [bx + rep0]
  1080 000004BB 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1081 000004BE 06                  <1> 	push es
  1082 000004BF 57                  <1> 	push di
  1083 000004C0 E83EFE              <1> 	call LZ_decoder.peek
  1084 000004C3 5F                  <1> 	pop di
  1085 000004C4 07                  <1> 	pop es
  1086 000004C5 E88DFD              <1> 	call Range_decoder.decode_matched
  1087                              <1> @@:
  1088 000004C8 E85B03              <1> 	call LZ_decoder.put_byte
  1089 000004CB E852FC              <1> 	call State.set_char
  1090 000004CE EB97                <1> 	jmp .loop
  1091                              <1> 
  1092                              <1> 
  1093                              <1> .1st_bit_not_zero:		; match or repeated match
  1094 000004D0 1E                  <1> 	push ds
  1095 000004D1 07                  <1> 	pop es
  1096 000004D2 8DBF9000            <1> 	lea di, [bx + bm_rep]		; es:di -> bm_rep array
  1097                              <1> %if bit_model_size != 2
  1098                              <1>  %error Assuming word size for bit_model_size
  1099                              <1> %endif
  1100 000004D6 8B4728              <1> 	mov ax, word [bx + state.st]
  1101 000004D9 01C0                <1> 	add ax, ax			; ax = index is state
  1102                              <1> 	; jc short .error_CY_2	; (state.st is always < 12)
  1103 000004DB 01C7                <1> 	add di, ax			; es:di -> bm_rep[state()]
  1104                              <1> .error_CY_2:
  1105 000004DD 7230                <1> 	jc short .error_CY_3
  1106 000004DF E8CFFC              <1> 	call Range_decoder.decode_bit
  1107 000004E2 7203E9EA00          <1> 	jnc .2nd_bit_zero
  1108                              <1> 
  1109                              <1> .2nd_bit_not_zero:
  1110 000004E7 1E                  <1> 	push ds
  1111 000004E8 07                  <1> 	pop es
  1112 000004E9 8DBFA800            <1> 	lea di, [bx + bm_rep0]		; es:di -> bm_rep0 array
  1113                              <1> %if bit_model_size != 2
  1114                              <1>  %error Assuming word size for bit_model_size
  1115                              <1> %endif
  1116 000004ED 8B4728              <1> 	mov ax, word [bx + state.st]
  1117 000004F0 01C0                <1> 	add ax, ax			; ax = index is state
  1118                              <1> 	; jc short .error_CY_3	; (state.st is always < 12)
  1119 000004F2 01C7                <1> 	add di, ax			; es:di -> bm_rep0[state()]
  1120 000004F4 7219                <1> 	jc short .error_CY_3
  1121 000004F6 E8B8FC              <1> 	call Range_decoder.decode_bit
  1122 000004F9 7233                <1> 	jc .3rd_bit_not_zero
  1123                              <1> 
  1124                              <1> .3rd_bit_zero:
  1125 000004FB 1E                  <1> 	push ds
  1126 000004FC 07                  <1> 	pop es
  1127 000004FD 8DBFF030            <1> 	lea di, [bx + bm_len]		; es:di -> bm_len 2D array
  1128 00000501 B80800              <1> 	mov ax, bit_model_size * pos_states
  1129                              <1> 				; (2 * 4 = 8)
  1130 00000504 F76728              <1> 	mul word [bx + state.st]; (< 12)
  1131                              <1> 					; dx:ax = first index is state
  1132                              <1> 	; test dx, dx
  1133                              <1> 	; stc
  1134                              <1> 	; jnz short .error_CY_3	; (dx:ax is always < 12 * 8)
  1135                              <1> %if bit_model_size != 2
  1136                              <1>  %error Assuming word size for bit_model_size
  1137                              <1> %endif
  1138                              <1> %rep bit_model_size
  1139                              <1> 	add ax, word [bp + ?pos_state]
  1140                              <1> 	; jc short .error_CY_3	; (pos_state is always < 4
  1141                              <1> 				;  and state_st is always < 12
  1142                              <1> 				;  and ax is < 12 * 8 prior to adding)
  1143                              <1> %endrep
  1139 00000507 0346EE              <2>  add ax, word [bp + ?pos_state]
  1140                              <2> 
  1141                              <2> 
  1142                              <2> 
  1139 0000050A 0346EE              <2>  add ax, word [bp + ?pos_state]
  1140                              <2> 
  1141                              <2> 
  1142                              <2> 
  1144 0000050D 01C7                <1> 	add di, ax			; es:di -> bm_len[state()]
  1145                              <1> .error_CY_3:
  1146 0000050F 722A                <1> 	jc short .error_CY_4
  1147 00000511 E89DFC              <1> 	call Range_decoder.decode_bit
  1148 00000514 7303E99500          <1> 	jc .4th_bit_not_zero
  1149                              <1> 
  1150                              <1> .4th_bit_zero:
  1151                              <1> ; State.set_short_rep
  1152 00000519 B8090B              <1> 	mov ax, 9 | (11 << 8)
  1153 0000051C E815FC              <1> 	call State.select
  1154                              <1> 
  1155 0000051F 8B4718              <1> 	mov ax, word [bx + rep0]
  1156 00000522 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1157 00000525 E8D9FD              <1> 	call LZ_decoder.peek
  1158 00000528 E8FB02              <1> 	call LZ_decoder.put_byte
  1159 0000052B E939FF              <1> 	jmp .loop
  1160                              <1> 
  1161                              <1> .3rd_bit_not_zero:
  1162 0000052E 1E                  <1> 	push ds
  1163 0000052F 07                  <1> 	pop es
  1164 00000530 8DBFC000            <1> 	lea di, [bx + bm_rep1]		; es:di -> bm_rep1 array
  1165                              <1> %if bit_model_size != 2
  1166                              <1>  %error Assuming word size for bit_model_size
  1167                              <1> %endif
  1168 00000534 8B4728              <1> 	mov ax, word [bx + state.st]
  1169 00000537 01C0                <1> 	add ax, ax			; ax = index is state
  1170                              <1> 	; jc short .error_CY_4	; (state.st is always < 12)
  1171 00000539 01C7                <1> 	add di, ax			; es:di -> bm_rep1[state()]
  1172                              <1> .error_CY_4:
  1173 0000053B 7220                <1> 	jc short .error_CY_4a
  1174 0000053D E871FC              <1> 	call Range_decoder.decode_bit
  1175 00000540 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero
  1176                              <1> 
  1177                              <1> .3rd_bit_not_zero.4th_bit_zero:
  1178 00000542 FF771E              <1> 	push word [bx + rep1 + 2]
  1179 00000545 FF771C              <1> 	push word [bx + rep1]
  1180 00000548 8F46FA              <1> 	pop word [bp + ?distance]
  1181 0000054B 8F46FC              <1> 	pop word [bp + ?distance + 2]
  1182 0000054E EB46                <1> 	jmp .3rd_bit_not_zero.common
  1183                              <1> 
  1184                              <1> .3rd_bit_not_zero.4th_bit_not_zero:
  1185 00000550 1E                  <1> 	push ds
  1186 00000551 07                  <1> 	pop es
  1187 00000552 8DBFD800            <1> 	lea di, [bx + bm_rep2]		; es:di -> bm_rep2 array
  1188                              <1> %if bit_model_size != 2
  1189                              <1>  %error Assuming word size for bit_model_size
  1190                              <1> %endif
  1191 00000556 8B4728              <1> 	mov ax, word [bx + state.st]
  1192 00000559 01C0                <1> 	add ax, ax			; ax = index is state
  1193                              <1> 	; jc short .error_CY_5	; (state.st is always < 12)
  1194 0000055B 01C7                <1> 	add di, ax			; es:di -> bm_rep2[state()]
  1195                              <1> .error_CY_4a:
  1196 0000055D 7267                <1> 	jc short .error_CY_5
  1197 0000055F E84FFC              <1> 	call Range_decoder.decode_bit
  1198 00000562 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero
  1199                              <1> 
  1200                              <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_zero:
  1201 00000564 FF7722              <1> 	push word [bx + rep2 + 2]
  1202 00000567 FF7720              <1> 	push word [bx + rep2]
  1203 0000056A 8F46FA              <1> 	pop word [bp + ?distance]
  1204 0000056D 8F46FC              <1> 	pop word [bp + ?distance + 2]
  1205 00000570 EB18                <1> 	jmp .3rd_bit_not_zero.4th_bit_not_zero.common
  1206                              <1> 
  1207                              <1> .3rd_bit_not_zero.4th_bit_not_zero.5th_bit_not_zero:
  1208 00000572 FF7726              <1> 	push word [bx + rep3 + 2]
  1209 00000575 FF7724              <1> 	push word [bx + rep3]
  1210 00000578 8F46FA              <1> 	pop word [bp + ?distance]
  1211 0000057B 8F46FC              <1> 	pop word [bp + ?distance + 2]	; distance = rep3
  1212 0000057E FF7722              <1> 	push word [bx + rep2 + 2]
  1213 00000581 FF7720              <1> 	push word [bx + rep2]
  1214 00000584 8F4724              <1> 	pop word [bx + rep3]
  1215 00000587 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  1216                              <1> 
  1217                              <1> .3rd_bit_not_zero.4th_bit_not_zero.common:
  1218 0000058A FF771E              <1> 	push word [bx + rep1 + 2]
  1219 0000058D FF771C              <1> 	push word [bx + rep1]
  1220 00000590 8F4720              <1> 	pop word [bx + rep2]
  1221 00000593 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  1222                              <1> 
  1223                              <1> .3rd_bit_not_zero.common:
  1224 00000596 FF771A              <1> 	push word [bx + rep0 + 2]
  1225 00000599 FF7718              <1> 	push word [bx + rep0]
  1226 0000059C 8F471C              <1> 	pop word [bx + rep1]
  1227 0000059F 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  1228 000005A2 FF76FC              <1> 	push word [bp + ?distance + 2]
  1229 000005A5 FF76FA              <1> 	push word [bp + ?distance]
  1230 000005A8 8F4718              <1> 	pop word [bx + rep0]
  1231 000005AB 8F471A              <1> 	pop word [bx + rep0 + 2]	; rep0 = distance
  1232                              <1> 
  1233                              <1> .4th_bit_not_zero:
  1234                              <1> ; State.set_rep
  1235 000005AE B8080B              <1> 	mov ax, 8 | (11 << 8)
  1236 000005B1 E880FB              <1> 	call State.select
  1237                              <1> 
  1238 000005B4 8B46EE              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  1239 000005B7 1E                  <1> 	push ds
  1240 000005B8 07                  <1> 	pop es
  1241 000005B9 8DBFDA36            <1> 	lea di, [bx + rep_len_model]	; -> len_model to use
  1242 000005BD E8E0FC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  1243 000005C0 83C002              <1> 	add ax, min_match_len
  1244 000005C3 83D200              <1> 	adc dx, 0
  1245                              <1> .error_CY_5:
  1246 000005C6 7250                <1> 	jc short .error_CY_6
  1247 000005C8 8946F6              <1> 	mov word [bp + ?len], ax
  1248 000005CB 8956F8              <1> 	mov word [bp + ?len + 2], dx
  1249 000005CE E93001              <1> 	jmp .handle_match
  1250                              <1> 
  1251                              <1> .2nd_bit_zero:			; match
  1252 000005D1 FF7722              <1> 	push word [bx + rep2 + 2]
  1253 000005D4 FF7720              <1> 	push word [bx + rep2]
  1254 000005D7 8F4724              <1> 	pop word [bx + rep3]
  1255 000005DA 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  1256                              <1> 
  1257 000005DD FF771E              <1> 	push word [bx + rep1 + 2]
  1258 000005E0 FF771C              <1> 	push word [bx + rep1]
  1259 000005E3 8F4720              <1> 	pop word [bx + rep2]
  1260 000005E6 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  1261                              <1> 
  1262 000005E9 FF771A              <1> 	push word [bx + rep0 + 2]
  1263 000005EC FF7718              <1> 	push word [bx + rep0]
  1264 000005EF 8F471C              <1> 	pop word [bx + rep1]
  1265 000005F2 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  1266                              <1> 
  1267 000005F5 8B46EE              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  1268 000005F8 1E                  <1> 	push ds
  1269 000005F9 07                  <1> 	pop es
  1270 000005FA 8DBF5634            <1> 	lea di, [bx + match_len_model]	; -> len_model to use
  1271 000005FE E89FFC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  1272                              <1> 
  1273 00000601 8946F0              <1> 	mov word [bp + ?len_state], ax
  1274 00000604 85D2                <1> 	test dx, dx
  1275 00000606 7505                <1> 	jnz @F
  1276 00000608 83F803              <1> 	cmp ax, len_states - 1
  1277 0000060B 7205                <1> 	jb @FF
  1278                              <1> @@:
  1279 0000060D C746F00300          <1> 	mov word [bp + ?len_state], len_states - 1
  1280                              <1> @@:
  1281                              <1> 
  1282 00000612 83C002              <1> 	add ax, min_match_len
  1283 00000615 83D200              <1> 	adc dx, 0
  1284                              <1> .error_CY_6:
  1285 00000618 723C                <1> 	jc short .error_CY_7
  1286                              <1> 
  1287 0000061A 8946F6              <1> 	mov word [bp + ?len], ax
  1288 0000061D 8956F8              <1> 	mov word [bp + ?len + 2], dx
  1289                              <1> 
  1290 00000620 1E                  <1> 	push ds
  1291 00000621 07                  <1> 	pop es
  1292 00000622 8DBF5031            <1> 	lea di, [bx + bm_dis_slot]	; -> 2D array bm_dis_slot
  1293                              <1> 
  1294 00000626 B88000              <1> 	mov ax, bit_model_size * (1 << dis_slot_bits)
  1295 00000629 F766F0              <1> 	mul word [bp + ?len_state]	; first index is len_state
  1296                              <1> 		; bit_model_size = 2
  1297                              <1> 		; 1 << dis_slot_bits = 1 << 6 = 64
  1298                              <1> 		; ?len_state < 4
  1299                              <1> 		; multiplication 2 * 64 * 3 = 384
  1300                              <1> 					; dx:ax = first index into array
  1301 0000062C 01C7                <1> 	add di, ax			; -> 1D array at bm_dis_slot[len_state]
  1302 0000062E B90600              <1> 	mov cx, dis_slot_bits
  1303 00000631 E8E2FB              <1> 	call Range_decoder.decode_tree
  1304 00000634 894718              <1> 	mov word [bx + rep0], ax
  1305 00000637 89571A              <1> 	mov word [bx + rep0 + 2], dx
  1306                              <1> 
  1307 0000063A 85D2                <1> 	test dx, dx			; (same flags as cmp dx, 0)
  1308 0000063C 7503                <1> 	jne @F
  1309 0000063E 83F804              <1> 	cmp ax, start_dis_model
  1310                              <1> @@:
  1311 00000641 7303E99B00          <1> 	jnae .not_rep0_ae_start_dis_model
  1312                              <1> 
  1313                              <1> .rep0_ae_start_dis_model:
  1314 00000646 8946F2              <1> 	mov word [bp + ?dis_slot], ax
  1315 00000649 8956F4              <1> 	mov word [bp + ?dis_slot + 2], dx
  1316                              <1> 
  1317 0000064C D1EA                <1> 	shr dx, 1
  1318 0000064E D1D8                <1> 	rcr ax, 1			; dis_slot >> 1
  1319 00000650 83E801              <1> 	sub ax, 1
  1320 00000653 83DA00              <1> 	sbb dx, 0			; - 1
  1321                              <1> .error_CY_7:
  1322                              <1> .error_CY_8:
  1323 00000656 7230                <1> 	jc short .error_CY_9
  1324 00000658 F9                  <1> 	stc
  1325 00000659 752D                <1> 	jnz short .error_CY_9
  1326 0000065B 91                  <1> 	xchg cx, ax			; cx = direct_bits, clobber ax
  1327 0000065C 31D2                <1> 	xor dx, dx
  1328 0000065E B80100              <1> 	mov ax, 1
  1329 00000661 2246F2              <1> 	and al, byte [bp + ?dis_slot]
  1330 00000664 0C02                <1> 	or al, 2
  1331 00000666 51                  <1> 	push cx
  1332 00000667 E306                <1> 	jcxz @FF
  1333                              <1> @@:
  1334 00000669 D1E0                <1> 	shl ax, 1
  1335 0000066B D1D2                <1> 	rcl dx, 1
  1336 0000066D E2FA                <1> 	loop @B
  1337                              <1> @@:
  1338 0000066F 59                  <1> 	pop cx
  1339 00000670 894718              <1> 	mov word [bx + rep0], ax
  1340 00000673 89571A              <1> 	mov word [bx + rep0 + 2], dx
  1341                              <1> 
  1342 00000676 837EF400            <1> 	cmp word [bp + ?dis_slot + 2], 0
  1343 0000067A 7504                <1> 	jne @F
  1344 0000067C 837EF20E            <1> 	cmp word [bp + ?dis_slot], end_dis_model
  1345                              <1> @@:
  1346 00000680 7328                <1> 	jnb .not_dis_slot_below_end_dis_model
  1347                              <1> 
  1348                              <1> .dis_slot_below_end_dis_model:
  1349 00000682 2B46F2              <1> 	sub ax, word [bp + ?dis_slot]
  1350 00000685 1B56F4              <1> 	sbb dx, word [bp + ?dis_slot + 2]
  1351                              <1> 					; dx:ax = index into bm_dis array
  1352                              <1> 					;  = rep0 - dis_slot
  1353                              <1> .error_CY_9:
  1354 00000688 722D                <1> 	jc short .error_CY_10
  1355                              <1> 
  1356                              <1> %if bit_model_size != 2
  1357                              <1>  %error Assuming word size for bit_model_size
  1358                              <1> %endif
  1359 0000068A 01C0                <1> 	add ax, ax
  1360 0000068C 11D2                <1> 	adc dx, dx			; dx:ax *= 2
  1361 0000068E 7227                <1> 	jc short .error_CY_10
  1362 00000690 F9                  <1> 	stc
  1363 00000691 7524                <1> 	jnz short .error_CY_10		; if dx != 0 -->
  1364 00000693 1E                  <1> 	push ds
  1365 00000694 07                  <1> 	pop es
  1366 00000695 8DBF5033            <1> 	lea di, [bx + bm_dis]		; es:di -> bm_dis array
  1367 00000699 01C7                <1> 	add di, ax			; index into the array
  1368 0000069B 721A                <1> 	jc short .error_CY_10
  1369 0000069D E8A2FB              <1> 	call Range_decoder.decode_tree_reversed
  1370 000006A0 014718              <1> 	add word [bx + rep0], ax
  1371 000006A3 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1372 000006A6 720F                <1> 	jc short .error_CY_10
  1373 000006A8 EB37                <1> 	jmp .after_dis_slot_below
  1374                              <1> 
  1375                              <1> .not_dis_slot_below_end_dis_model:
  1376 000006AA 83E904              <1> 	sub cx, dis_align_bits
  1377 000006AD E8CEFA              <1> 	call Range_decoder.decode
  1378 000006B0 B90400              <1> 	mov cx, dis_align_bits
  1379                              <1> @@:
  1380 000006B3 D1E0                <1> 	shl ax, 1
  1381 000006B5 D1D2                <1> 	rcl dx, 1
  1382                              <1> .error_CY_10:
  1383 000006B7 721A                <1> 	jc short .error_CY_11
  1384 000006B9 E2F8                <1> 	loop @B
  1385 000006BB 014718              <1> 	add word [bx + rep0], ax
  1386 000006BE 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1387                              <1> 
  1388 000006C1 B90400              <1> 	mov cx, dis_align_bits
  1389 000006C4 1E                  <1> 	push ds
  1390 000006C5 07                  <1> 	pop es
  1391 000006C6 8DBF3634            <1> 	lea di, [bx + bm_align]
  1392 000006CA E875FB              <1> 	call Range_decoder.decode_tree_reversed
  1393 000006CD 014718              <1> 	add word [bx + rep0], ax
  1394 000006D0 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1395                              <1> .error_CY_11:
  1396 000006D3 727D                <1> 	jc .error_CY_12
  1397                              <1> 
  1398 000006D5 837F1AFF            <1> 	cmp word [bx + rep0 + 2], -1	; rep0 = 0FFFF_FFFFh ?
  1399 000006D9 7504                <1> 	jne @F
  1400 000006DB 837F18FF            <1> 	cmp word [bx + rep0], -1
  1401                              <1> @@:
  1402 000006DF 7479                <1> 	je .end_member			; yes, end (marker found) -->
  1403                              <1> 
  1404                              <1> .after_dis_slot_below:
  1405                              <1> 
  1406                              <1> .not_rep0_ae_start_dis_model:
  1407                              <1> 
  1408                              <1> ; State.set_match
  1409 000006E1 B8070A              <1> 	mov ax, 7 | (10 << 8)
  1410 000006E4 E84DFA              <1> 	call State.select
  1411                              <1> 
  1412 000006E7 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1413 000006EA 8B4718              <1> 	mov ax, word [bx + rep0]
  1414                              <1> 
  1415 000006ED 3B5712              <1> 	cmp dx, word [bx + lz_decoder.dictionary_size + 2]
  1416 000006F0 7503                <1> 	jne @F
  1417 000006F2 3B4710              <1> 	cmp ax, word [bx + lz_decoder.dictionary_size]
  1418                              <1> @@:
  1419 000006F5 7308                <1> 	jae short .error_AE_1
  1420                              <1> 
  1421                              <1> 		; check for (rep0 >= pos && !pos_wrapped)
  1422                              <1> 		;  (pos_wrapped is always false for us)
  1423 000006F7 3B5716              <1> 	cmp dx, word [bx + lz_decoder.pos + 2]
  1424 000006FA 7503                <1> 	jne @F
  1425 000006FC 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  1426                              <1> @@:
  1427                              <1> .error_AE_1:
  1428 000006FF 7356                <1> 	jae short .error_1
  1429                              <1> 
  1430                              <1> .handle_match:
  1431 00000701 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1432 00000704 8B4718              <1> 	mov ax, word [bx + rep0]
  1433                              <1> 
  1434 00000707 E80EFC              <1> 	call calculate_peek_pointer_disi
  1435                              <1> 
  1436 0000070A 8B46F6              <1> 	mov ax, word [bp + ?len]
  1437 0000070D 8B56F8              <1> 	mov dx, word [bp + ?len + 2]	; dx:ax = length
  1438                              <1> 
  1439                              <1> 
  1440                              <1> 		; INP:	dx:ax = length of match
  1441                              <1> 		;	di:si -> source (normalised)
  1442                              <1> 		;	ds:bx -> local variables structure
  1443                              <1> 		;	ss:bp -> depack stack frame,
  1444                              <1> 		;		with ?length_of_destination, ?dst
  1445                              <1> 		; OUT:	NC if success,
  1446                              <1> 		;	 ?length_of_destination and ?dst updated
  1447                              <1> 		;	CY if error
  1448                              <1> 		;	 (destination buffer too small or overlap error)
  1449                              <1> 		;	! may jump to depack.end if ?dst_max_segment reached
  1450                              <1> 		; CHG:	ax, cx, dx, di, si, es
  1451                              <1> ; handle_match:
  1452 00000710 014714              <1> 	add word [bx + lz_decoder.pos], ax
  1453 00000713 115716              <1> 	adc word [bx + lz_decoder.pos + 2], dx
  1454 00000716 723A                <1> 	jc short .error_CY_12		; (CY) -->
  1455                              <1> 
  1456 00000718 2946DE              <1> 	sub word [bp + ?length_of_destination], ax
  1457 0000071B 1956E0              <1> 	sbb word [bp + ?length_of_destination + 2], dx
  1458                              <1> 					; enough space left ?
  1459 0000071E 7232                <1> 	jb short .error_CY_12		; no --> (below == CY)
  1460                              <1> 
  1461 00000720 1E                  <1> 	push ds
  1462                              <1> 
  1463 00000721 8EDF                <1> 	mov ds, di			; ds:si -> source
  1464 00000723 C47ED6              <1> 	les di, [bp + ?dst]		; es:di -> destination
  1465                              <1> .hm_loop:
  1466 00000726 B9F0FF              <1> 	mov cx, 64 * 1024 - 16		; block size
  1467                              <1> 		; If both pointers are normalised, moving 0FFF0h bytes is
  1468                              <1> 		;  valid and results in a maximum offset of 0FFFFh in either.
  1469                              <1> 
  1470 00000729 85D2                <1> 	test dx, dx			; >= 1_0000h ?
  1471 0000072B 7508                <1> 	jnz @F				; yes, full block -->
  1472 0000072D 85C0                <1> 	test ax, ax			; == 0 ?
  1473 0000072F 7415                <1> 	jz .hm_end			; yes, done -->
  1474 00000731 39C8                <1> 	cmp ax, cx			; can move in one (last) block ?
  1475 00000733 7607                <1> 	jbe .hm_last			; yes -->
  1476                              <1> @@:
  1477                              <1> 					; no, move one block and continue
  1478 00000735 29C8                <1> 	sub ax, cx
  1479 00000737 83DA00              <1> 	sbb dx, 0			; left over remaining
  1480 0000073A EB03                <1> 	jmp .hm_copy
  1481                              <1> 
  1482                              <1> .hm_last:
  1483 0000073C 91                  <1> 	xchg cx, ax			; cx = remaining length
  1484 0000073D 31C0                <1> 	xor ax, ax			; no more remaining
  1485                              <1> 
  1486                              <1> .hm_copy:
  1487 0000073F F3A4                <1> 	rep movsb			; move one block (full or partial)
  1488                              <1> 
  1489 00000741 E83102              <1> 	call normalise_both_pointers
  1490 00000744 EBE0                <1> 	jmp .hm_loop
  1491                              <1> 
  1492                              <1> .hm_end:
  1493 00000746 897ED6              <1> 	mov word [bp + ?dst], di
  1494 00000749 8C46D8              <1> 	mov word [bp + ?dst + 2], es
  1495                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
  1496                              <1> 	mov ax, es
  1497                              <1> 	cmp ax, word [bp + ?dst_max_segment]
  1498                              <1> 	jae depack.end
  1499                              <1> 		; note that we have the depack stack frame pointed to by
  1500                              <1> 		;  ss:bp here, which is needed for running depack.end
  1501                              <1> %endif
  1502 0000074C 1F                  <1> 	pop ds
  1503                              <1> %if _ALLOW_OVERLAPPING
  1504 0000074D 53                  <1> 	push bx
  1505 0000074E E80802              <1> 	call check_pointers_not_overlapping
  1506 00000751 5B                  <1> 	pop bx				; returns CF
  1507                              <1> .error_CY_12:
  1508 00000752 7203                <1> 	jc short .error_1
  1509                              <1> %endif
  1510 00000754 E910FD              <1> 	jmp .loop
  1511                              <1> 
  1512                              <1> %if ! _ALLOW_OVERLAPPING
  1513                              <1> .error_CY_12:
  1514                              <1> %endif
  1515                              <1> .error_1:
  1516 00000757 E9A000              <1> 	jmp .error
  1517                              <1> 
  1518                              <1> 
  1519                              <1> .end_member:			; End Of Stream marker
  1520 0000075A 837EF800            <1> 	cmp word [bp + ?len + 2], min_match_len >> 16
  1521 0000075E 7504                <1> 	jne @F
  1522 00000760 837EF602            <1> 	cmp word [bp + ?len], min_match_len & 0FFFFh
  1523                              <1> @@:
  1524 00000764 75F1                <1> 	jne short .error_1
  1525                              <1> 
  1526                              <1> 		; decode_member succeeded
  1527                              <1> 
  1528 00000766 C55EE6              <1> 	lds bx, [bp + ?final_dst]	; -> localvariables
  1529                              <1> 
  1530 00000769 836EE214            <1> 	sub word [bp + ?length_of_source], lzip_trailer_size
  1531 0000076D 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1532 00000771 7303E98400          <1> 	jc .error
  1533                              <1> 
  1534 00000776 C476EA              <1> 	les si, [bp + ?src]	; es:si -> lzip_trailer.uncompressed_checksum
  1535 00000779 83C604              <1> 	add si, 4			; skip CRC
  1536                              <1> 
  1537                              <1> 				; es:si -> lzip_trailer.uncompressed_size
  1538 0000077C 26AD                <1> 	es lodsw			; does the destination length match ?
  1539 0000077E 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  1540 00000781 7577                <1> 	jne .error
  1541 00000783 26AD                <1> 	es lodsw
  1542 00000785 3B4716              <1> 	cmp ax, word [bx + lz_decoder.pos + 2]
  1543 00000788 7570                <1> 	jne .error			; if no -->
  1544 0000078A 26AD                <1> 	es lodsw
  1545 0000078C 85C0                <1> 	test ax, ax
  1546 0000078E 756A                <1> 	jnz .error
  1547 00000790 26AD                <1> 	es lodsw
  1548 00000792 85C0                <1> 	test ax, ax
  1549 00000794 7564                <1> 	jnz .error
  1550                              <1> 
  1551 00000796 830714              <1> 	add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size
  1552 00000799 83570200            <1> 	adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0
  1553 0000079D 725B                <1> 	jc .error
  1554                              <1> 
  1555                              <1> 				; es:si -> lzip_trailer.member_size
  1556 0000079F 26AD                <1> 	es lodsw			; does the source length match ?
  1557 000007A1 3B07                <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos]
  1558 000007A3 7555                <1> 	jne .error
  1559 000007A5 26AD                <1> 	es lodsw
  1560 000007A7 3B4702              <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2]
  1561 000007AA 754E                <1> 	jne .error
  1562 000007AC 26AD                <1> 	es lodsw
  1563 000007AE 85C0                <1> 	test ax, ax
  1564 000007B0 7548                <1> 	jnz .error
  1565 000007B2 26AD                <1> 	es lodsw
  1566 000007B4 85C0                <1> 	test ax, ax
  1567 000007B6 7542                <1> 	jnz .error
  1568                              <1> 
  1569                              <1> 				; es:si -> behind lzip_trailer
  1570 000007B8 06                  <1> 	 push es
  1571 000007B9 56                  <1> 	 push si
  1572 000007BA E8C701              <1> 	call normalise_pointer
  1573 000007BD 8F46EA              <1> 	 pop word [bp + ?src]
  1574 000007C0 8F46EC              <1> 	 pop word [bp + ?src + 2]
  1575                              <1> 
  1576 000007C3 E9C5FB              <1> 	jmp .loop_member
  1577                              <1> 
  1578                              <1> .end:
  1579                              <1> 
  1580                              <1> .final:
  1581                              <1> %if _COUNTER
  1582                              <1> 	mov al, '%'
  1583                              <1> 	call disp_al
  1584                              <1> %endif
  1585 000007C6 C47EE6              <1> 	les di, [bp + ?final_dst]
  1586                              <1> 				; -> destination
  1587 000007C9 C576DA              <1> 	lds si, [bp + ?original_dst]
  1588                              <1> 				; -> source
  1589 000007CC 1E                  <1> 	 push ds
  1590 000007CD 56                  <1> 	 push si
  1591 000007CE E80402              <1> 	call pointer_to_linear	; dx:ax = linear ?original_dst
  1592 000007D1 91                  <1> 	xchg cx, ax
  1593 000007D2 87DA                <1> 	xchg bx, dx		; bx:cx = linear ?original_dst, clobber dx:ax
  1594 000007D4 FF76D8              <1> 	 push word [bp + ?dst + 2]
  1595 000007D7 FF76D6              <1> 	 push word [bp + ?dst]
  1596 000007DA E8F801              <1> 	call pointer_to_linear
  1597 000007DD 29C8                <1> 	sub ax, cx
  1598 000007DF 19DA                <1> 	sbb dx, bx		; = linear dst minus linear original_dst
  1599                              <1> 
  1600 000007E1 B90400              <1> 	mov cx, 4
  1601 000007E4 83C00F              <1> 	add ax, 15
  1602 000007E7 83D200              <1> 	adc dx, 0
  1603                              <1> @@:
  1604 000007EA D1EA                <1> 	shr dx, 1
  1605 000007EC D1D8                <1> 	rcr ax, 1
  1606 000007EE E2FA                <1> 	loop @B
  1607 000007F0 89C1                <1> 	mov cx, ax
  1608 000007F2 85D2                <1> 	test dx, dx
  1609                              <1> d0	mov byte [bp + ?errordata], 84h
  1610 000007F4 7504                <1> 	jnz .error
  1611                              <1> 
  1612 000007F6 E8C800              <1> 	call x_mov_p
  1613                              <1> 
  1614 000007F9 A8                  <1> 	db __TEST_IMM8			; (NC)
  1615                              <1> .error:
  1616 000007FA F9                  <1> 	stc
  1617                              <1> 
  1618                              <1> %if _COUNTER
  1619                              <1> 	lahf
  1620                              <1> 	mov al, 13
  1621                              <1> 	call disp_al
  1622                              <1> 	mov al, 10
  1623                              <1> 	call disp_al
  1624                              <1> 	sahf
  1625                              <1> %endif
  1626                              <1> d0	mov bx, word [bp + ?errordata]
  1627 000007FB 89EC5D              <1> 	lleave code
  1628 000007FE C3                  <1> 	lret
  1629                              <1> 
  1630                              <1> 
  1631                              <1> 		; INP:	ds:bx -> range_decoder structure
  1632                              <1> 		;	ss:bp -> depack stack frame
  1633                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1634                              <1> 		;	If success,
  1635                              <1> 		;	 al = byte read
  1636                              <1> 		; CHG:	-
  1637                              <1> Range_decoder.get_byte:
  1638 000007FF 830701              <1> 	add word [bx + range_decoder.member_pos], 1
  1639 00000802 83570200            <1> 	adc word [bx + range_decoder.member_pos + 2], 0
  1640 00000806 72F2                <1> 	jc short .error
  1641                              <1> 
  1642                              <1> 		; INP:	ds:bx -> range_decoder structure
  1643                              <1> 		;	ss:bp -> depack stack frame
  1644                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1645                              <1> 		;	If success,
  1646                              <1> 		;	 al = value read
  1647                              <1> 		; CHG:	-
  1648                              <1> ; get_byte:
  1649 00000808 1E                  <1> 	push ds
  1650 00000809 56                  <1> 	push si
  1651                              <1> 
  1652 0000080A 836EE201            <1> 	sub word [bp + ?length_of_source], 1
  1653 0000080E 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1654 00000812 72E6                <1> 	jc short .error
  1655                              <1> 
  1656 00000814 C576EA              <1> 	lds si, [bp + ?src]
  1657 00000817 AC                  <1> 	lodsb
  1658 00000818 1E                  <1> 	 push ds
  1659 00000819 56                  <1> 	 push si
  1660 0000081A E86701              <1> 	call normalise_pointer
  1661 0000081D 8F46EA              <1> 	 pop word [bp + ?src]
  1662 00000820 8F46EC              <1> 	 pop word [bp + ?src + 2]
  1663 00000823 5E                  <1> 	pop si
  1664 00000824 1F                  <1> 	pop ds
  1665 00000825 C3                  <1> 	retn
  1666                              <1> 
  1667                              <1> .error: equ depack.error
  1668                              <1> 
  1669                              <1> 
  1670                              <1> 		; INP:	ds:bx -> lz_decoder structure
  1671                              <1> 		;	al = byte to write to buffer
  1672                              <1> 		;	ss:bp -> depack stack frame
  1673                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1674                              <1> 		; CHG:	cx, dx, ax, di, es
  1675                              <1> LZ_decoder.put_byte:
  1676 00000826 C47ED6              <1> 	les di, [bp + ?dst]
  1677                              <1> 
  1678 00000829 83471401            <1> 	add word [bx + lz_decoder.pos], 1
  1679 0000082D 83571600            <1> 	adc word [bx + lz_decoder.pos + 2], 0
  1680 00000831 72C7                <1> 	jc short .error
  1681                              <1> 
  1682 00000833 836EDE01            <1> 	sub word [bp + ?length_of_destination], 1
  1683 00000837 835EE000            <1> 	sbb word [bp + ?length_of_destination + 2], 0
  1684 0000083B 72BD                <1> 	jb short .error
  1685                              <1> 
  1686 0000083D AA                  <1> 	stosb
  1687 0000083E 06                  <1> 	 push es
  1688 0000083F 57                  <1> 	 push di
  1689 00000840 E84101              <1> 	call normalise_pointer
  1690 00000843 8F46D6              <1> 	 pop word [bp + ?dst]
  1691 00000846 8F46D8              <1> 	 pop word [bp + ?dst + 2]
  1692                              <1> 
  1693                              <1> %if _ALLOW_OVERLAPPING
  1694 00000849 53                  <1> 	push bx
  1695 0000084A E80C01              <1> 	call check_pointers_not_overlapping
  1696 0000084D 5B                  <1> 	pop bx			; returns CF
  1697 0000084E 72AA                <1> 	jc short .error
  1698                              <1> %endif
  1699 00000850 C3                  <1> 	retn
  1700                              <1> 
  1701                              <1> .error: equ depack.error
  1702                              <1> 
  1703                              <1> 
  1704                              <1> 		; INP:	ds:si = pointer
  1705                              <1> 		;	es:di = pointer
  1706                              <1> 		; OUT:	ds:si anti normalised
  1707                              <1> 		;	es:di anti normalised
  1708                              <1> anti_normalise_both_pointers:
  1709 00000851 1E                  <1> 	 push ds
  1710 00000852 56                  <1> 	 push si
  1711 00000853 E80A00              <1> 	call anti_normalise_pointer
  1712 00000856 5E                  <1> 	 pop si
  1713 00000857 1F                  <1> 	 pop ds
  1714                              <1> 
  1715 00000858 06                  <1> 	 push es
  1716 00000859 57                  <1> 	 push di
  1717 0000085A E80300              <1> 	call anti_normalise_pointer
  1718 0000085D 5F                  <1> 	 pop di
  1719 0000085E 07                  <1> 	 pop es
  1720 0000085F C3                  <1> 	retn
  1721                              <1> 
  1722                              <1> 
  1723                              <1> 		; INP:	word [ss:sp + 2] = segment
  1724                              <1> 		;	word [ss:sp] = offset
  1725                              <1> 		;
  1726                              <1> 		; Note:	Does not work correctly with pointers that point to
  1727                              <1> 		;	 a HMA location. Do not use then!
  1728                              <1> anti_normalise_pointer:
  1729                              <1> 	lframe near, nested
  1730                              <1> 	lpar word,	segment
  1731                              <1> 	lpar word,	offset
  1732                              <1> 	lpar_return
  1733 00000860 5589E5              <1> 	lenter
  1734 00000863 53                  <1> 	push bx
  1735 00000864 51                  <1> 	push cx
  1736                              <1> 
  1737 00000865 31DB                <1> 	xor bx, bx
  1738 00000867 31C9                <1> 	xor cx, cx
  1739 00000869 FF7606              <1> 	 push word [bp + ?segment]
  1740 0000086C FF7604              <1> 	 push word [bp + ?offset]
  1741 0000086F E80A00              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1742 00000872 8F4604              <1> 	 pop word [bp + ?offset]
  1743 00000875 8F4606              <1> 	 pop word [bp + ?segment]
  1744                              <1> 
  1745 00000878 59                  <1> 	pop cx
  1746 00000879 5B                  <1> 	pop bx
  1747 0000087A 5D                  <1> 	lleave
  1748 0000087B C3                  <1> 	lret
  1749                              <1> 
  1750                              <1> 
  1751                              <1> 		; INP:	word [ss:sp + 2] = segment
  1752                              <1> 		;	word [ss:sp] = offset
  1753                              <1> 		;	bx:cx = add/sub displacement
  1754                              <1> 		; OUT:	dword [ss:sp] = anti-normalised address
  1755                              <1> 		;
  1756                              <1> 		; An anti-normalised pointer has an offset as high as possible,
  1757                              <1> 		;  which is in the range 0FFF0h to 0FFFFh unless the pointed-to
  1758                              <1> 		;  location is in the first 64 KiB of memory.
  1759                              <1> anti_normalise_pointer_with_displacement_bxcx:
  1760                              <1> 	lframe near, nested
  1761                              <1> 	lpar word,	segment
  1762                              <1> 	lpar word,	offset
  1763                              <1> 	lpar_return
  1764 0000087C 5589E5              <1> 	lenter
  1765 0000087F 50                  <1> 	push ax
  1766 00000880 52                  <1> 	push dx
  1767                              <1> 
  1768 00000881 FF7606              <1> 	 push word [bp + ?segment]
  1769 00000884 FF7604              <1> 	 push word [bp + ?offset]
  1770 00000887 E84B01              <1> 	call pointer_to_linear
  1771                              <1> 
  1772 0000088A 01C8                <1> 	add ax, cx
  1773 0000088C 11DA                <1> 	adc dx, bx			; dx:ax += bx:cx
  1774                              <1> 
  1775 0000088E 83FA01              <1> 	cmp dx, 1
  1776 00000891 7223                <1> 	jb @F
  1777                              <1> 
  1778 00000893 50                  <1> 	push ax
  1779 00000894 83C8F0              <1> 	or ax, 0FFF0h
  1780 00000897 894604              <1> 	mov word [bp + ?offset], ax
  1781 0000089A 58                  <1> 	pop ax
  1782                              <1> 
  1783 0000089B 83E8F0              <1> 	sub ax, 0FFF0h
  1784 0000089E 83DA00              <1> 	sbb dx, 0
  1785                              <1> 
  1786                              <1> %rep 4
  1787                              <1> 	shr dx, 1
  1788                              <1> 	rcr ax, 1
  1789                              <1> %endrep
  1787 000008A1 D1EA                <2>  shr dx, 1
  1788 000008A3 D1D8                <2>  rcr ax, 1
  1787 000008A5 D1EA                <2>  shr dx, 1
  1788 000008A7 D1D8                <2>  rcr ax, 1
  1787 000008A9 D1EA                <2>  shr dx, 1
  1788 000008AB D1D8                <2>  rcr ax, 1
  1787 000008AD D1EA                <2>  shr dx, 1
  1788 000008AF D1D8                <2>  rcr ax, 1
  1790 000008B1 894606              <1> 	mov word [bp + ?segment], ax
  1791                              <1> 
  1792 000008B4 EB07                <1> 	jmp .return
  1793                              <1> 
  1794                              <1> 		; dx:ax = 0000:offset
  1795                              <1> @@:
  1796 000008B6 894604              <1> 	mov word [bp + ?offset], ax
  1797 000008B9 83660600            <1> 	and word [bp + ?segment], 0
  1798                              <1> 
  1799                              <1> .return:
  1800 000008BD 5A                  <1> 	pop dx
  1801 000008BE 58                  <1> 	pop ax
  1802 000008BF 5D                  <1> 	lleave
  1803 000008C0 C3                  <1> 	lret
  1804                              <1> 
  1805                              <1> 
  1806                              <1> 		; Move paragraphs
  1807                              <1> 		;
  1808                              <1> 		; INP:	ds:si -> source
  1809                              <1> 		;	es:di -> destination
  1810                              <1> 		;	cx = number of paragraphs
  1811                              <1> 		; CHG:	ax, bx, cx, dx
  1812                              <1> 		; OUT:	ds:si -> after source (normalised)
  1813                              <1> 		;	es:di -> after destination (normalised)
  1814                              <1> 		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  1815                              <1> 		;	Do not provide a wrapped/HMA source or destination!
  1816                              <1> x_mov_p:
  1817 000008C1 E8B100              <1> 	call normalise_both_pointers
  1818 000008C4 8CD8                <1> 	mov ax, ds
  1819 000008C6 8CC2                <1> 	mov dx, es
  1820                              <1> 
  1821 000008C8 85C9                <1> 	test cx, cx
  1822 000008CA 7503E98800          <1> 	jz .return
  1823                              <1> 
  1824 000008CF 39D0                <1> 	cmp ax, dx		; source above destination ?
  1825 000008D1 7716                <1> 	ja .up			; yes, move up (forwards) -->
  1826 000008D3 7206                <1> 	jb .check_down
  1827                              <1> 
  1828 000008D5 39FE                <1> 	cmp si, di
  1829 000008D7 7710                <1> 	ja .up
  1830 000008D9 747C                <1> 	je .return		; pointers are the same, no need to move -->
  1831                              <1> .check_down:
  1832 000008DB 50                  <1> 	push ax
  1833 000008DC 01C8                <1> 	add ax, cx		; (expected not to carry)
  1834 000008DE 39D0                <1> 	cmp ax, dx		; end of source is above destination ?
  1835 000008E0 58                  <1> 	pop ax
  1836 000008E1 7726                <1> 	ja .down		; yes, move from top down -->
  1837 000008E3 7204                <1> 	jb .up
  1838 000008E5 39FE                <1> 	cmp si, di
  1839 000008E7 7720                <1> 	ja .down
  1840                              <1> 
  1841                              <1> 	; Here, the end of source is below-or-equal the destination,
  1842                              <1> 	;  so they do not overlap. In this case we prefer moving up.
  1843                              <1> .up:
  1844                              <1> .uploop:
  1845 000008E9 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  1846 000008ED 760C                <1> 	jbe .uplast		; no -->
  1847 000008EF 51                  <1> 	push cx
  1848 000008F0 B9F87F              <1> 	mov cx, 0FFF0h /2
  1849 000008F3 F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  1850 000008F5 59                  <1> 	pop cx
  1851 000008F6 E87C00              <1> 	call normalise_both_pointers
  1852 000008F9 EBEE                <1> 	jmp short .uploop	; proceed for more -->
  1853                              <1> .uplast:
  1854 000008FB 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  1855 000008FF D1E1                <1> 	shl cx, 1
  1856 00000901 D1E1                <1> 	shl cx, 1
  1857 00000903 D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  1858 00000905 F3A5                <1> 	rep movsw		; move last part
  1859 00000907 EB4E                <1> 	jmp short .return
  1860                              <1> 
  1861                              <1> .down:
  1862 00000909 FD                  <1> 	std			; _AMD_ERRATUM_109_WORKAROUND as below
  1863                              <1> 
  1864 0000090A 89C8                <1> 	mov ax, cx
  1865 0000090C 31DB                <1> 	xor bx, bx
  1866 0000090E 51                  <1> 	push cx
  1867 0000090F B90400              <1> 	mov cx, 4
  1868                              <1> @@:
  1869 00000912 D1E0                <1> 	shl ax, 1
  1870 00000914 D1D3                <1> 	rcl bx, 1
  1871 00000916 E2FA                <1> 	loop @B
  1872 00000918 83E802              <1> 	sub ax, 2
  1873 0000091B 83DB00              <1> 	sbb bx, 0		; -> point at last word
  1874                              <1> 		; (Cannot borrow here because we checked that cx
  1875                              <1> 		;  was nonzero at the intro to this function, so
  1876                              <1> 		;  bx:ax is at least 16 prior to this subtraction.)
  1877 0000091E 91                  <1> 	xchg ax, cx		; bx:cx = displacement to point to last word
  1878 0000091F 1E                  <1> 	 push ds
  1879 00000920 56                  <1> 	 push si
  1880 00000921 E858FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1881 00000924 5E                  <1> 	 pop si
  1882 00000925 1F                  <1> 	 pop ds			; -> last word of source
  1883 00000926 06                  <1> 	 push es
  1884 00000927 57                  <1> 	 push di
  1885 00000928 E851FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1886 0000092B 5F                  <1> 	 pop di
  1887 0000092C 07                  <1> 	 pop es			; -> last word of destination
  1888 0000092D 59                  <1> 	pop cx
  1889                              <1> 
  1890                              <1> .dnloop:
  1891 0000092E 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  1892 00000932 760C                <1> 	jbe .dnlast		; no -->
  1893 00000934 51                  <1> 	push cx
  1894 00000935 B9F87F              <1> 	mov cx, 0FFF0h /2
  1895 00000938 F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  1896 0000093A 59                  <1> 	pop cx
  1897 0000093B E813FF              <1> 	call anti_normalise_both_pointers
  1898 0000093E EBEE                <1> 	jmp short .dnloop	; proceed for more -->
  1899                              <1> .dnlast:
  1900 00000940 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  1901 00000944 D1E1                <1> 	shl cx, 1
  1902 00000946 D1E1                <1> 	shl cx, 1
  1903 00000948 D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  1904                              <1> 
  1905                              <1> 
  1906                              <1> 	numdef AMD_ERRATUM_109_WORKAROUND, 1
  1907                              <1> %if 0
  1908                              <1> 
  1909                              <1> Jack R. Ellis pointed out this erratum:
  1910                              <1> 
  1911                              <1> Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
  1912                              <1> 
  1913                              <1> 109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
  1914                              <1> 
  1915                              <1> Description
  1916                              <1> 
  1917                              <1> In certain situations a REP MOVS instruction may lead to
  1918                              <1> incorrect results. An incorrect address size, data size
  1919                              <1> or source operand segment may be used or a succeeding
  1920                              <1> instruction may be skipped. This may occur under the
  1921                              <1> following conditions:
  1922                              <1> 
  1923                              <1> * EFLAGS.DF=1 (the string is being moved in the reverse direction).
  1924                              <1> 
  1925                              <1> * The number of items being moved (RCX) is between 1 and 20.
  1926                              <1> 
  1927                              <1> * The REP MOVS instruction is preceded by some microcoded instruction
  1928                              <1>   that has not completely retired by the time the REP MOVS begins
  1929                              <1>   execution. The set of such instructions includes BOUND, CLI, LDS,
  1930                              <1>   LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
  1931                              <1> 
  1932                              <1> Potential Effect on System
  1933                              <1> 
  1934                              <1> Incorrect results may be produced or the system may hang.
  1935                              <1> 
  1936                              <1> Suggested Workaround
  1937                              <1> 
  1938                              <1> Contact your AMD representative for information on a BIOS update.
  1939                              <1> 
  1940                              <1> %endif
  1941                              <1> 
  1942                              <1> %if _AMD_ERRATUM_109_WORKAROUND
  1943 0000094A E308                <1> 	jcxz @FF
  1944 0000094C 83F914              <1> 	cmp cx, 20
  1945 0000094F 7703                <1> 	ja @FF
  1946                              <1> @@:
  1947 00000951 A5                  <1> 	movsw
  1948 00000952 E2FD                <1> 	loop @B
  1949                              <1> @@:
  1950                              <1> %endif
  1951 00000954 F3A5                <1> 	rep movsw		; move first part
  1952 00000956 FC                  <1> 	cld
  1953                              <1> .return:
  1954 00000957 EB1C                <1> 	jmp normalise_both_pointers
  1037                                  %endif
  1038                                  
  1039                                  
  1040                                  %if _LZO
  1041                                  	%include "lzo.asm"
  1042                                  %endif
  1043                                  
  1044                                  
  1045                                  %if _LZSA2
  1046                                  	%include "lzsa2.asm"
  1047                                  %endif
  1048                                  
  1049                                  
  1050                                  %if _APL
  1051                                  	%include "apl.asm"
  1052                                  %endif
  1053                                  
  1054                                  
  1055                                  %if _BZP
  1056                                  	%include "bzp.asm"
  1057                                  %endif
  1058                                  
  1059                                  
  1060                                  %if _ALLOW_OVERLAPPING
  1061                                  		; INP:	?src, ?dst
  1062                                  		; OUT:	CY if error (?src < ?dst)
  1063                                  		;	NC if success
  1064                                  		; CHG:	ax, bx, cx, dx
  1065                                  check_pointers_not_overlapping:
  1066                                  %if CHECK_POINTERS_VARIABLE_DST
  1067 00000959 FF76D8                  	 push word [bp + ?dst + 2]
  1068 0000095C FF76D6                  	 push word [bp + ?dst]
  1069                                  %else
  1070                                  	 push es
  1071                                  	 push di
  1072                                  %endif
  1073 0000095F E87300                  	call pointer_to_linear
  1074                                  
  1075 00000962 91                      	xchg cx, ax
  1076 00000963 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1077                                  
  1078                                  %if CHECK_POINTERS_VARIABLE_SRC
  1079 00000965 FF76EC                  	 push word [bp + ?src + 2]
  1080 00000968 FF76EA                  	 push word [bp + ?src]
  1081                                  %else
  1082                                  	 push ds
  1083                                  	 push si
  1084                                  %endif
  1085 0000096B E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1086                                  
  1087 0000096E 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1088 00000970 7502                    	jne @F
  1089 00000972 39C8                    	cmp ax, cx
  1090                                  @@:
  1091                                  					; (CY) if error (src < dst)
  1092                                  					; (NC) if no error
  1093 00000974 C3                      	retn
  1094                                  %endif
  1095                                  
  1096                                  	; This leaves the lframe context created within the
  1097                                  	;  specific depacker's file. The above function
  1098                                  	;  check_pointers_not_overlapping uses the frame.
  1099                                  	lleave ctx
  1100                                  
  1101                                  
  1102                                  		; INP:	ds:si = pointer
  1103                                  		;	es:di = pointer
  1104                                  		; OUT:	ds:si normalised
  1105                                  		;	es:di normalised
  1106                                  normalise_both_pointers:
  1107 00000975 06                      	 push es
  1108 00000976 57                      	 push di
  1109 00000977 E80A00                  	call normalise_pointer
  1110 0000097A 5F                      	 pop di
  1111 0000097B 07                      	 pop es
  1112                                  
  1113                                  normalise_dssi_pointer:
  1114 0000097C 1E                      	 push ds
  1115 0000097D 56                      	 push si
  1116 0000097E E80300                  	call normalise_pointer
  1117 00000981 5E                      	 pop si
  1118 00000982 1F                      	 pop ds
  1119 00000983 C3                      	retn
  1120                                  
  1121                                  
  1122                                  		; INP:	word [ss:sp + 2] = segment
  1123                                  		;	word [ss:sp] = offset
  1124                                  		;
  1125                                  		; Note:	Does not work correctly with pointers that point to
  1126                                  		;	 a HMA location. Do not use then!
  1127                                  normalise_pointer:
  1128                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1129                                  	lframe near
  1130                                  	lpar word,	segment
  1131                                  	lpar word,	offset
  1132                                  	lpar_return
  1133 00000984 5589E5                  	lenter
  1134                                  
  1135 00000987 837E040F                	cmp word [bp + ?offset], 15
  1136 0000098B 7617                    	jbe .ret
  1137                                  
  1138 0000098D 53                      	push bx
  1139 0000098E 51                      	push cx
  1140                                  
  1141 0000098F 31DB                    	xor bx, bx
  1142 00000991 31C9                    	xor cx, cx
  1143 00000993 FF7606                  	 push word [bp + ?segment]
  1144 00000996 FF7604                  	 push word [bp + ?offset]
  1145 00000999 E80A00                  	call normalise_pointer_with_displacement_bxcx
  1146 0000099C 8F4604                  	 pop word [bp + ?offset]
  1147 0000099F 8F4606                  	 pop word [bp + ?segment]
  1148                                  
  1149 000009A2 59                      	pop cx
  1150 000009A3 5B                      	pop bx
  1151                                  .ret:
  1152 000009A4 5D                      	lleave
  1153 000009A5 C3                      	lret
  1154                                  
  1155                                  
  1156                                  		; INP:	word [ss:sp + 2] = segment
  1157                                  		;	word [ss:sp] = offset
  1158                                  		;	bx:cx = add/sub displacement
  1159                                  		; OUT:	CY if the displacement carries
  1160                                  		;	NC if not
  1161                                  normalise_pointer_with_displacement_bxcx:
  1162                                  %endif
  1163                                  	lframe near
  1164                                  	lpar word,	segment
  1165                                  	lpar word,	offset
  1166                                  	lpar_return
  1167 000009A6 5589E5                  	lenter
  1168                                  
  1169                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1170                                  	cmp word [bp + ?offset], 15
  1171                                  	jbe .ret
  1172                                  %endif
  1173                                  
  1174 000009A9 50                      	push ax
  1175 000009AA 51                      	push cx
  1176 000009AB 52                      	push dx
  1177                                  
  1178 000009AC FF7606                  	 push word [bp + ?segment]
  1179 000009AF FF7604                  	 push word [bp + ?offset]
  1180 000009B2 E82000                  	call pointer_to_linear
  1181                                  
  1182                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1183                                  	; push bx
  1184                                  	; 				; sign-extend cx into bx:cx
  1185                                  	; cmp cx, 8000h			; CY if < 8000h (NC if negative)
  1186                                  	; cmc				; NC if positive
  1187                                  	; sbb bx, bx			; 0 if was NC, -1 if was CY
  1188                                  
  1189 000009B5 01C1                    	add cx, ax
  1190 000009B7 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1191                                  	; pop bx
  1192 000009B9 9F                      	lahf				; ah = flags
  1193                                  %else
  1194                                  	xchg ax, cx
  1195                                  %endif
  1196                                  
  1197                                  %if 0
  1198                                  		; Adds in HMA support for this function. Not currently used.
  1199                                  	cmp dx, 10h			; dx:ax >= 10_0000h ?
  1200                                  	jb @F				; no, linear-to-pointer normally -->
  1201                                  	; ja .error
  1202                                  
  1203                                  	add cx, 10h
  1204                                  	; jc .error
  1205                                  	mov word [bp + ?offset], cx
  1206                                  	or word [bp + ?segment], -1
  1207                                  	jmp .return
  1208                                  @@:
  1209                                  %endif
  1210                                  
  1211 000009BA 53                      	push bx
  1212 000009BB 89CB                    	mov bx, cx
  1213 000009BD 83E10F                  	and cx, 15
  1214 000009C0 894E04                  	mov word [bp + ?offset], cx
  1215                                  
  1216 000009C3 B104                    	mov cl, 4
  1217                                  @@:
  1218 000009C5 D1EA                    	shr dx, 1
  1219 000009C7 D1DB                    	rcr bx, 1
  1220 000009C9 E2FA                    	loop @B
  1221                                  
  1222 000009CB 895E06                  	mov word [bp + ?segment], bx
  1223 000009CE 5B                      	pop bx
  1224                                  
  1225                                  	; test dx, dx
  1226                                  	; jnz .error
  1227                                  
  1228                                  .return:
  1229                                  
  1230                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1231 000009CF 9E                      	sahf				; restore flags from ah
  1232                                  %endif
  1233 000009D0 5A                      	pop dx
  1234 000009D1 59                      	pop cx
  1235 000009D2 58                      	pop ax
  1236                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1237                                  .ret:
  1238                                  %endif
  1239 000009D3 5D                      	lleave
  1240 000009D4 C3                      	lret
  1241                                  
  1242                                  
  1243                                  		; INP:	word [ss:sp + 2] = segment
  1244                                  		;	word [ss:sp] = offset
  1245                                  		; OUT:	dx:ax = linear address
  1246                                  pointer_to_linear:
  1247                                  	lframe near
  1248                                  	lpar word,	segment
  1249                                  	lpar word,	offset
  1250 000009D5 5589E5                  	lenter
  1251                                  
  1252 000009D8 8B4606                  	mov ax, word [bp + ?segment]
  1253 000009DB 31D2                    	xor dx, dx
  1254 000009DD 51                      	push cx
  1255 000009DE B90400                  	mov cx, 4
  1256                                  @@:
  1257 000009E1 D1E0                    	shl ax, 1
  1258 000009E3 D1D2                    	rcl dx, 1
  1259 000009E5 E2FA                    	loop @B
  1260                                  
  1261 000009E7 034604                  	add ax, word [bp + ?offset]
  1262 000009EA 11CA                    	adc dx, cx			; cx = 0 here
  1263 000009EC 59                      	pop cx
  1264                                  
  1265 000009ED 5D                      	lleave
  1266 000009EE C20400                  	lret
  1267                                  
  1268                                  
  1269 000009F1 90<rep Fh>              	align 16
  1270                                  init1_end:
  1271                                  
  1272                                  
  1273                                  	section INIT0
  1274                                  %if _TEST_PROGRAM
  1275                                  init0_msg:
  1276                                  .error_stderr:	db "Error: Not enough memory allocated.",13,10
  1277                                  .error_stderr.length: equ $ - .error_stderr
  1278                                  .error_stdout:	_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  1283                                  		db 13,10
  1284                                  .error_stdout.length: equ $ - .error_stdout
  1285                                  
  1286                                  	align 1024
  1287                                  %if ($ - $$) != 1024
  1288                                   %error Wrong INIT0 size
  1289                                  %endif
  1290                                  %endif
  1291                                  
  1292 000001CF 90                      	align 16
  1293                                  init0_end:
  1294                                  
  1295                                  
  1296                                  %assign num (init1_end - init1_start) + (init0_end - init0_start)
  1297                                  %if _BRIEFLZ
  1298                                  %define which iniblz
  1299                                  %elif _LZ4
  1300                                  %define which inilz4
  1301                                  %elif _SNAPPY
  1302                                  %define which inisz
  1303                                  %elif _EXODECR
  1304                                  %define which iniexo
  1305                                  %elif _X
  1306                                  %define which inix
  1307                                  %elif _HEATSHRINK
  1308                                  %define which inihs
  1309                                  %elif _LZD
  1310                                  %define which inilz
  1311                                  %elif _LZO
  1312                                  %define which inilzo
  1313                                  %elif _LZSA2
  1314                                  %define which inilzsa2
  1315                                  %elif _APL
  1316                                  %define which iniapl
  1317                                  %elif _BZP
  1318                                  %define which inibzp
  1319                                  %endif
  1320                                  %warning which: num bytes used for depacker
  1320          ******************       warning: inilz: 3024 bytes used for depacker [-w+user]
  1321                                  
  1322                                  
  1323                                  %if _TEST_PROGRAM
  1324                                  	section INIT2 align=16 follows=INIT1 vstart=0
  1325                                  init2_start:
  1326                                  		; si => after PSP
  1327                                  		; cs => INIT2
  1328                                  		; psp, free, payload, init1, init2, payload space, stack
  1329                                  		;
  1330                                  		; The correct allocation for the test program
  1331                                  		;  is image size (init0, payload, init1, init2)
  1332                                  		;  minus init0 plus compressed payload size
  1333                                  		;  plus decompressed size plus stack. For
  1334                                  		;  simplicity, init0 subtraction may be skipped.
  1335                                  
  1336                                  		; ss:sp -> word amount repetitions, word ax
  1337                                  		; bx = 1 if A test, 8001h if B test
  1338                                  	push bx
  1339                                  
  1340                                  	lframe 0
  1341                                  	lpar word,	repetitions
  1342                                  	lpar word,	whichtest
  1343                                  	lenter
  1344                                  
  1345                                  	mov dx, word [bp + ?repetitions]
  1346                                  	cmp dx, -1
  1347                                  	jne @F
  1348                                  
  1349                                  .cmdline_error:
  1350                                  %if _DEBUG0
  1351                                  	mov bx, -1
  1352                                  %endif
  1353                                  	mov dx, init2_msg.cmdline_error
  1354                                  	mov cx, init2_msg.cmdline_error.length
  1355                                  	jmp init2_error
  1356                                  
  1357                                  
  1358                                  @@:
  1359                                  	testopt [bp + ?whichtest], 8000h
  1360                                  	jz .a
  1361                                  .b:
  1362                                  	test dx, dx
  1363                                  	jz .cmdline_error
  1364                                  	jmp @F
  1365                                  
  1366                                  .a:
  1367                                  	test dx, dx
  1368                                  	jnz .cmdline_error
  1369                                  @@:
  1370                                  
  1371                                  	mov dx, cs
  1372                                  	add dx, (init2_end - init2_start) >> 4
  1373                                  				; => payload saving area
  1374                                  	mov ax, cs
  1375                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  1378                                  	mov cx, (payload_end - payload) >> 4
  1379                                  	call init2_movp		; copy payload to payload saving area
  1380                                  		; We save away the payload here because a failure
  1381                                  		;  to decompress generally overwrites part of that
  1382                                  		;  payload which was used as source.
  1383                                  
  1384                                  	mov dx, ax		; dx => payload source to use
  1385                                  	mov ax, cs
  1386                                  	sub ax, (init1_end - init1_start) >> 4
  1387                                  				; ax => INIT1
  1388                                  	mov bx, 1		; say we're in EXE mode
  1389                                  	push dx
  1390                                  	push ax
  1391                                  	push si			; si => target
  1392                                  	 push cs
  1393                                  	 call .transfer		; call decompression
  1394                                  	pop si
  1395                                  	pop ax
  1396                                  	pop dx
  1397                                  		; Returns here after decompression.
  1398                                  		; CY if error.
  1399                                  	jnc @F
  1400                                  
  1401                                  	mov dx, init2_msg.initial_error
  1402                                  	mov cx, init2_msg.initial_error.length
  1403                                  	jmp init2_error
  1404                                  
  1405                                  @@:
  1406                                  	numdef INCLUDE_UNCOMPRESSED
  1407                                  	numdef WRITE_WRONG_FILE
  1408                                  %if _INCLUDE_UNCOMPRESSED
  1409                                  payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed
  1410                                  
  1411                                  	call checkdecompressed
  1412                                  	je @F
  1413                                  
  1414                                  %if _WRITE_WRONG_FILE
  1415                                  	call writefiles
  1416                                  %endif
  1417                                  
  1418                                  %if _DEBUG0
  1419                                  	mov bx, -1
  1420                                  %endif
  1421                                  	mov dx, init2_msg.initial_error_2
  1422                                  	mov cx, init2_msg.initial_error_2.length
  1423                                  	jmp init2_error
  1424                                  
  1425                                  @@:
  1426                                  %endif
  1427                                  
  1428                                  	lvar word,	upperbound
  1429                                  	 push dx
  1430                                  	lvar word,	lowerbound
  1431                                  	 push si
  1432                                  	lvar word,	current_init1
  1433                                  	 push ax
  1434                                  
  1435                                  %if _TEST_PROGRESS
  1436                                  	mov dx, init2_msg.progress.1
  1437                                  	mov cx, init2_msg.progress.1.length
  1438                                  .loop:
  1439                                  	push cs
  1440                                  	pop ds
  1441                                  	mov bx, 2
  1442                                  	mov ah, 40h
  1443                                  	int 21h
  1444                                  %else
  1445                                  .loop:
  1446                                  %endif
  1447                                  
  1448                                  	mov dx, [bp + ?upperbound]
  1449                                  
  1450                                  	testopt [bp + ?whichtest], 8000h
  1451                                  	jz @F
  1452                                  
  1453                                  	dec word [bp + ?repetitions]
  1454                                  	jnz .test_b_skip_bound
  1455                                  
  1456                                  %if _TEST_PROGRESS
  1457                                  	push cs
  1458                                  	pop ds
  1459                                  	mov dx, init2_msg.progress.linebreak
  1460                                  	mov cx, init2_msg.progress.linebreak.length
  1461                                  	mov bx, 2
  1462                                  	mov ah, 40h
  1463                                  	int 21h
  1464                                  %endif
  1465                                  	mov ax, 4C00h
  1466                                  	int 21h
  1467                                  
  1468                                  
  1469                                  @@:
  1470                                  	sub dx, [bp + ?lowerbound]
  1471                                  	jz .found
  1472                                  	shr dx, 1
  1473                                  		; Rounding down, so that we never retry upper bound.
  1474                                  		;  The upper bound is known to be working.
  1475                                  	add dx, [bp + ?lowerbound]
  1476                                  
  1477                                  .test_b_skip_bound:
  1478                                  	push dx
  1479                                  	add dx, (payload_end - payload) >> 4
  1480                                  	mov ax, [bp + ?current_init1]
  1481                                  	mov cx, (init1_end - init1_start) >> 4
  1482                                  	call init2_movp
  1483                                  	mov [bp + ?current_init1], dx
  1484                                  	pop dx
  1485                                  
  1486                                  	mov ax, cs
  1487                                  	add ax, (init2_end - init2_start) >> 4
  1488                                  				; => payload in saving area
  1489                                  	mov cx, (payload_end - payload) >> 4
  1490                                  	call init2_movp		; copy payload from payload saving area
  1491                                  
  1492                                  		; dx => source
  1493                                  	mov ax, [bp + ?current_init1]
  1494                                  	mov bx, 1
  1495                                  	push dx
  1496                                  	push si
  1497                                  	 push cs
  1498                                  	 call .transfer
  1499                                  	pop si
  1500                                  	pop dx
  1501                                  		; Returns here after decompression.
  1502                                  		; CY if error.
  1503                                  	jnc @F
  1504                                  
  1505                                  	testopt [bp + ?whichtest], 8000h
  1506                                  	jnz .test_b_fail
  1507                                  
  1508                                  		; error: this attempt is one below the new lower bound
  1509                                  	inc dx
  1510                                  	mov word [bp + ?lowerbound], dx
  1511                                  
  1512                                  %if _TEST_PROGRESS
  1513                                  	mov dx, init2_msg.progress.fail
  1514                                  	mov cx, init2_msg.progress.fail.length
  1515                                  %endif
  1516                                  	jmp .loop
  1517                                  
  1518                                  @@:
  1519                                  %if _INCLUDE_UNCOMPRESSED
  1520                                  	call checkdecompressed
  1521                                  	je @F
  1522                                  
  1523                                  %if _WRITE_WRONG_FILE
  1524                                  	call writefiles
  1525                                  %endif
  1526                                  
  1527                                  .test_b_fail:
  1528                                  %if _TEST_PROGRESS
  1529                                  	push cs
  1530                                  	pop ds
  1531                                  	mov dx, init2_msg.progress.linebreak
  1532                                  	mov cx, init2_msg.progress.linebreak.length
  1533                                  	mov bx, 2
  1534                                  	mov ah, 40h
  1535                                  	int 21h
  1536                                  %endif
  1537                                  %if _DEBUG0
  1538                                  	mov bx, -2
  1539                                  %endif
  1540                                  	mov dx, init2_msg.subsequent_error_2
  1541                                  	mov cx, init2_msg.subsequent_error_2.length
  1542                                  	jmp init2_error
  1543                                  
  1544                                  @@:
  1545                                  %endif
  1546                                  		; success: this attempt is the new upper bound
  1547                                  	mov word [bp + ?upperbound], dx
  1548                                  %if _TEST_PROGRESS
  1549                                  	mov dx, init2_msg.progress.success
  1550                                  	mov cx, init2_msg.progress.success.length
  1551                                  %endif
  1552                                  	jmp .loop
  1553                                  
  1554                                  .found:
  1555                                  %if _TEST_PROGRESS
  1556                                  	push cs
  1557                                  	pop ds
  1558                                  	mov dx, init2_msg.progress.linebreak
  1559                                  	mov cx, init2_msg.progress.linebreak.length
  1560                                  	mov bx, 2
  1561                                  	mov ah, 40h
  1562                                  	int 21h
  1563                                  %endif
  1564                                  	mov ax, word [bp + ?upperbound]
  1565                                  	sub ax, si		; = how many paragraphs in buffer before source
  1566                                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  1568                                  				; = how many paragraphs needed for process
  1569                                  	call init2_disp_ax_dec
  1570                                  	mov al, 13
  1571                                  	call init2_disp_al
  1572                                  	mov al, 10
  1573                                  	call init2_disp_al
  1574                                  	mov ax, 4C00h
  1575                                  	int 21h
  1576                                  
  1577                                  
  1578                                  .transfer:
  1579                                  	xor di, di
  1580                                  	push di			; dummy ax value on stack
  1581                                  	push ax			; INIT1 segment
  1582                                  	push di			; zero = init1_start
  1583                                  	retf
  1584                                  
  1585                                  
  1586                                  
  1587                                  %if _INCLUDE_UNCOMPRESSED
  1588                                  
  1589                                  
  1590                                  %if _WRITE_WRONG_FILE
  1591                                  writefiles:
  1592                                  	push cs
  1593                                  	pop ds
  1594                                  	mov dx, init2_msg.wrong_file_name
  1595                                  	xor cx, cx
  1596                                  	mov ah, 3Ch
  1597                                  	int 21h
  1598                                  	jc .notfile
  1599                                  
  1600                                  	mov bx, ax
  1601                                  	mov cx, payload_uncompressed_size >> 4
  1602                                  	xor dx, dx
  1603                                  .loopfile:
  1604                                  	mov ds, si
  1605                                  	mov ah, 40h
  1606                                  	push cx
  1607                                  	mov cx, 16
  1608                                  	int 21h
  1609                                  	pop cx
  1610                                  	inc si
  1611                                  	loop .loopfile
  1612                                  
  1613                                  	mov ds, si
  1614                                  	mov cx, payload_uncompressed_size & 15
  1615                                  	mov ah, 40h
  1616                                  	int 21h
  1617                                  
  1618                                  	mov ah, 3Eh
  1619                                  	int 21h
  1620                                  
  1621                                  .notfile:
  1622                                  
  1623                                  	push cs
  1624                                  	pop ds
  1625                                  	mov dx, init2_msg.wrong_file_name2
  1626                                  	xor cx, cx
  1627                                  	mov ah, 3Ch
  1628                                  	int 21h
  1629                                  	jc .notfile2
  1630                                  
  1631                                  	mov bx, ax
  1632                                  	mov cx, payload_uncompressed_size >> 4
  1633                                  	mov si, cs
  1634                                  	add si, (payload_uncompressed - init2_start) >> 4
  1635                                  	xor dx, dx
  1636                                  .loopfile2:
  1637                                  	mov ds, si
  1638                                  	mov ah, 40h
  1639                                  	push cx
  1640                                  	mov cx, 16
  1641                                  	int 21h
  1642                                  	pop cx
  1643                                  	inc si
  1644                                  	loop .loopfile2
  1645                                  
  1646                                  	mov ds, si
  1647                                  	mov cx, payload_uncompressed_size & 15
  1648                                  	mov ah, 40h
  1649                                  	int 21h
  1650                                  
  1651                                  	mov ah, 3Eh
  1652                                  	int 21h
  1653                                  
  1654                                  .notfile2:
  1655                                  	retn
  1656                                  %endif
  1657                                  
  1658                                  		; INP:	si => decompressed image
  1659                                  		; OUT:	ZR if matching
  1660                                  		;	NZ if mismatching
  1661                                  		; CHG:	es, ds, di, bx, cx
  1662                                  		; STT:	UP
  1663                                  checkdecompressed:
  1664                                  	push ax
  1665                                  	push dx
  1666                                  	push si
  1667                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  1668                                  	mov cx, _PAYLOAD_KERNEL_MAX_PARAS
  1669                                  	mov bx, 0
  1670                                  %else
  1671                                  	mov cx, payload_uncompressed_size >> 4
  1672                                  	mov bx, payload_uncompressed_size & 15
  1673                                  %endif
  1674                                  	mov di, cs
  1675                                  	add di, (payload_uncompressed - init2_start) >> 4
  1676                                  	jcxz .end
  1677                                  .loop:
  1678                                  	push cx
  1679                                  	mov cx, 8
  1680                                  	mov ds, si
  1681                                  	mov es, di
  1682                                  	inc si
  1683                                  	inc di
  1684                                  	push si
  1685                                  	push di
  1686                                  	xor si, si
  1687                                  	xor di, di
  1688                                  	repe cmpsw
  1689                                  	pop di
  1690                                  	pop si
  1691                                  	pop cx
  1692                                  	jne .ret
  1693                                  	loop .loop
  1694                                  .end:
  1695                                  	mov ds, si
  1696                                  	mov es, di
  1697                                  	xor si, si
  1698                                  	xor di, di		; (ZR)
  1699                                  	mov cx, bx
  1700                                  	repe cmpsb
  1701                                  .ret:
  1702                                  	pop si
  1703                                  	pop dx
  1704                                  	pop ax
  1705                                  	retn
  1706                                  %endif
  1707                                  
  1708                                  
  1709                                  init2_error:
  1710                                  %if _DEBUG0
  1711                                  	push bx
  1712                                  %endif
  1713                                  	push cs
  1714                                  	pop ds
  1715                                  	mov bx, 2
  1716                                  	mov ah, 40h
  1717                                  	int 21h
  1718                                  
  1719                                  %if _DEBUG0
  1720                                  	mov dx, init2_msg.rc
  1721                                  	mov cx, init2_msg.rc.length
  1722                                  	mov bx, 2
  1723                                  	mov ah, 40h
  1724                                  	int 21h
  1725                                  	pop ax
  1726                                  	call init2_error_disp_ax_hex
  1727                                  	mov dx, init2_msg.linebreak
  1728                                  	mov cx, init2_msg.linebreak.length
  1729                                  	mov bx, 2
  1730                                  	mov ah, 40h
  1731                                  	int 21h
  1732                                  %endif
  1733                                  
  1734                                  	testopt [bp + ?whichtest], 8000h
  1735                                  	jnz @F
  1736                                  
  1737                                  	mov dx, init2_msg.error_stdout
  1738                                  	mov cx, init2_msg.error_stdout.length
  1739                                  	mov bx, 1
  1740                                  	mov ah, 40h
  1741                                  	int 21h
  1742                                  @@:
  1743                                  	mov ax, 4CFFh
  1744                                  	int 21h
  1745                                  
  1746                                  	lleave ctx
  1747                                  
  1748                                  
  1749                                  %if _DEBUG0
  1750                                  init2_error_disp_ax_hex:	; ax
  1751                                  		xchg al,ah
  1752                                  		call init2_error_disp_al_hex	; display former ah
  1753                                  		xchg al,ah			;  and fall trough for al
  1754                                  init2_error_disp_al_hex:	; al
  1755                                  		push cx
  1756                                  		mov cl,4
  1757                                  		ror al,cl
  1758                                  		call init2_error_disp_al_lownibble_hex
  1759                                  						; display former high-nibble
  1760                                  		rol al,cl
  1761                                  		pop cx
  1762                                  						;  and fall trough for low-nibble
  1763                                  init2_error_disp_al_lownibble_hex:
  1764                                  		push ax			 ; save ax for call return
  1765                                  		and al,00001111b		; high nibble must be zero
  1766                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1767                                  		cmp al,'9'
  1768                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1769                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1770                                   .decimalnum:
  1771                                  		call init2_error_disp_al
  1772                                  		pop ax
  1773                                  		retn
  1774                                  
  1775                                  
  1776                                  init2_error_disp_al:
  1777                                  	push dx
  1778                                  	push cx
  1779                                  	push bx
  1780                                  	push ax
  1781                                  	mov dx, sp
  1782                                  	push ds
  1783                                  	 push ss
  1784                                  	 pop ds
  1785                                  	mov cx, 1
  1786                                  	mov bx, 2
  1787                                  	mov ah, 40h
  1788                                  	int 21h
  1789                                  	pop ds
  1790                                  	pop ax
  1791                                  	pop bx
  1792                                  	pop cx
  1793                                  	pop dx
  1794                                  	retn
  1795                                  %endif
  1796                                  
  1797                                  
  1798                                  init2_disp_al:
  1799                                  	push dx
  1800                                  	push ax
  1801                                  	mov dl, al
  1802                                  	mov ah, 2
  1803                                  	int 21h
  1804                                  	pop ax
  1805                                  	pop dx
  1806                                  	retn
  1807                                  
  1808                                  
  1809                                  		; Display number in ax decimal
  1810                                  		;
  1811                                  		; INP:	ax = number
  1812                                  		; OUT:	displayed using Int21.02
  1813                                  		; CHG:	none
  1814                                  init2_disp_ax_dec:			; ax (no leading zeros)
  1815                                  		push bx
  1816                                  		xor bx, bx
  1817                                  .pushax:
  1818                                  		push dx
  1819                                  		push ax
  1820                                  		or bl, bl
  1821                                  		jz .nobl
  1822                                  		sub bl, 5
  1823                                  		neg bl
  1824                                  .nobl:
  1825                                  		push cx
  1826                                  		mov cx, 10000
  1827                                  		call .divide_out
  1828                                  		mov cx, 1000
  1829                                  		call .divide_out
  1830                                  		mov cx, 100
  1831                                  		call .divide_out
  1832                                  		mov cl, 10
  1833                                  		call .divide_out
  1834                                  							; (Divisor 1 is useless)
  1835                                  		add al, '0'
  1836                                  		call init2_disp_al
  1837                                  		pop cx
  1838                                  		pop ax
  1839                                  		pop dx
  1840                                  		pop bx					; Caller's register
  1841                                  		retn
  1842                                  
  1843                                  
  1844                                  		; INP:	ax = number
  1845                                  		;	cx = divisor
  1846                                  		; OUT:	ax = remainder of operation
  1847                                  		;	result displayed
  1848                                  .divide_out:
  1849                                  		push dx
  1850                                  		xor dx, dx
  1851                                  		div cx				; 0:ax / cx
  1852                                  		push dx				; remainder
  1853                                  		dec bl
  1854                                  		jnz .nobl2
  1855                                  		or bh, 1
  1856                                  .nobl2:
  1857                                  		or bh, al
  1858                                  		jz .leadingzero
  1859                                  		add al, '0'
  1860                                  		call init2_disp_al		; display result
  1861                                   .leadingzero:
  1862                                  		pop ax				; remainder
  1863                                  		pop dx
  1864                                  		retn
  1865                                  
  1866                                  
  1867                                  init2_msg:
  1868                                  %if _TEST_PROGRESS
  1869                                  .progress.1:		db "Info: 1"
  1870                                  .progress.1.length: equ $ - .progress.1
  1871                                  .progress.fail:		db "F"
  1872                                  .progress.fail.length: equ $ - .progress.fail
  1873                                  .progress.success:	db "S"
  1874                                  .progress.success.length: equ $ - .progress.success
  1875                                  .progress.linebreak:	db 13,10
  1876                                  .progress.linebreak.length: equ $ - .progress.linebreak
  1877                                  %endif
  1878                                  %if _WRITE_WRONG_FILE
  1879                                  .wrong_file_name:	asciz "WRONG.BIN"
  1880                                  .wrong_file_name2:	asciz "WRONG2.BIN"
  1881                                  %endif
  1882                                  .initial_error:	db "Error: Test program failed to decompress with full buffer."
  1883                                  .linebreak:	db 13,10
  1884                                  .initial_error.length: equ $ - .initial_error
  1885                                  .linebreak.length: equ $ - .linebreak
  1886                                  %if _DEBUG0
  1887                                  .rc:	db "Error: Failure code="
  1888                                  .rc.length: equ $ - .rc
  1889                                  %endif
  1890                                  %if _INCLUDE_UNCOMPRESSED
  1891                                  .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  1892                                  .initial_error_2.length: equ $ - .initial_error_2
  1893                                  .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  1894                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  1895                                  %endif
  1896                                  .cmdline_error:	db "Error: Invalid command line input.",13,10
  1897                                  .cmdline_error.length: equ $ - .cmdline_error
  1898                                  .error_stdout:	_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  1903                                  		db 13,10
  1904                                  .error_stdout.length: equ $ - .error_stdout
  1905                                  
  1906                                  
  1907                                  		; Move paragraphs
  1908                                  		;
  1909                                  		; INP:	ax => source
  1910                                  		;	dx => destination
  1911                                  		;	cx = number of paragraphs
  1912                                  		; CHG:	-
  1913                                  		; OUT:	ax and dx unchanged
  1914                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  1915                                  		;	Do not provide a wrapped/HMA source or destination!
  1916                                  init2_movp:
  1917                                  	push cx
  1918                                  	push ds
  1919                                  	push si
  1920                                  	push es
  1921                                  	push di
  1922                                  
  1923                                  	cmp ax, dx		; source above destination ?
  1924                                  	ja .up			; yes, move up (forwards) -->
  1925                                  	je .return		; same, no need to move -->
  1926                                  	push ax
  1927                                  	add ax, cx		; (expected not to carry)
  1928                                  	cmp ax, dx		; end of source is above destination ?
  1929                                  	pop ax
  1930                                  	ja .down		; yes, move from top down -->
  1931                                  	; Here, the end of source is below-or-equal the destination,
  1932                                  	;  so they do not overlap. In this case we prefer moving up.
  1933                                  
  1934                                  .up:
  1935                                  	push ax
  1936                                  	push dx
  1937                                  .uploop:
  1938                                  	mov ds, ax
  1939                                  	mov es, dx
  1940                                  	xor di, di
  1941                                  	xor si, si		; -> start of segment
  1942                                  	sub cx, 1000h		; 64 KiB left ?
  1943                                  	jbe .uplast		; no -->
  1944                                  	push cx
  1945                                  	mov cx, 10000h /2
  1946                                  	rep movsw		; move 64 KiB
  1947                                  	pop cx
  1948                                  	add ax, 1000h
  1949                                  	add dx, 1000h		; -> next segment
  1950                                  	jmp short .uploop	; proceed for more -->
  1951                                  .uplast:
  1952                                  	add cx, 1000h		; restore counter
  1953                                  	shl cx, 1
  1954                                  	shl cx, 1
  1955                                  	shl cx, 1		; *8, paragraphs to words
  1956                                  	rep movsw		; move last part
  1957                                  	pop dx
  1958                                  	pop ax
  1959                                  	jmp short .return
  1960                                  
  1961                                  .down:
  1962                                  	std			; _AMD_ERRATUM_109_WORKAROUND as below
  1963                                  .dnloop:
  1964                                  	sub cx, 1000h		; 64 KiB left ?
  1965                                  	jbe .dnlast		; no -->
  1966                                  	push ax
  1967                                  	push dx
  1968                                  	add ax, cx
  1969                                  	add dx, cx
  1970                                  	mov ds, ax		; -> 64 KiB not yet moved
  1971                                  	mov es, dx
  1972                                  	pop dx
  1973                                  	pop ax
  1974                                  	mov di, -2
  1975                                  	mov si, di		; moved from last word down
  1976                                  	push cx
  1977                                  	mov cx, 10000h /2
  1978                                  	rep movsw		; move 64 KiB
  1979                                  	pop cx
  1980                                  	jmp short .dnloop	; proceed for more -->
  1981                                  .dnlast:
  1982                                  	add cx, 1000h		; restore counter
  1983                                  	shl cx, 1
  1984                                  	shl cx, 1
  1985                                  	shl cx, 1		; *8, paragraphs to words
  1986                                  	mov di, cx
  1987                                  	dec di
  1988                                  	shl di, 1		; words to offset, -> last word
  1989                                  	mov si, di
  1990                                  	mov ds, ax
  1991                                  	mov es, dx		; first segment correct
  1992                                  
  1993                                  		; Refer to comment in init0_movp.
  1994                                  %if _AMD_ERRATUM_109_WORKAROUND
  1995                                  	jcxz @FF
  1996                                  	cmp cx, 20
  1997                                  	ja @FF
  1998                                  @@:
  1999                                  	movsw
  2000                                  	loop @B
  2001                                  @@:
  2002                                  %endif
  2003                                  	rep movsw		; move first part
  2004                                  	cld
  2005                                  .return:
  2006                                  	pop di
  2007                                  	pop es
  2008                                  	pop si
  2009                                  	pop ds
  2010                                  	pop cx
  2011                                  	retn
  2012                                  
  2013                                  
  2014                                  	align 16
  2015                                  
  2016                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  2017                                  %if _INCLUDE_UNCOMPRESSED
  2018                                  payload_uncompressed:
  2019                                  	incbin _UNCOMPRESSED_FILE
  2020                                  .end:
  2021                                  	db 38
  2022                                  	align 16, db 38
  2023                                  %endif
  2024                                  init2_end:
  2025                                  %endif
  2026                                  
