     1                                  
     2                                  %if 0
     3                                  
     4                                  lDOS iniload packed payload
     5                                   by E. C. Masloch, 2018-2020
     6                                  
     7                                  Usage of the works is permitted provided that this
     8                                  instrument is retained with the works, so that any entity
     9                                  that uses the works is notified of this instrument.
    10                                  
    11                                  DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                                  
    13                                  
    14                                  Includes one of several depackers, some of which are under
    15                                  separate usage conditions. Refer to the individual depacker
    16                                  source files for the applicable usage conditions.
    17                                  
    18                                  %endif
    19                                  
    20                                  %include "lmacros3.mac"
     1                              <1> [list -]
    14                              <2> [list -]
    14                              <1> [list -]
    21                                  
    22                                  	struc LOADSTACKVARS, -10h
    23 FFFFFFF0 ????????                lsvFirstCluster:	resd 1
    24 FFFFFFF4 ????????                lsvFATSector:		resd 1
    25 FFFFFFF8 ????                    lsvFATSeg:		resw 1
    26 FFFFFFFA ????                    lsvLoadSeg:		resw 1
    27 FFFFFFFC ????????                lsvDataStart:		resd 1
    28                                  	endstruc
    29                                  
    30                                  	struc LOADDATA, LOADSTACKVARS - 10h
    31 FFFFFFE0 ????                    ldMemoryTop:	resw 1
    32 FFFFFFE2 ????                    ldLoadTop:	resw 1
    33 FFFFFFE4 ????                    ldSectorSeg:	resw 1
    34 FFFFFFE6 ??                      ldFATType:	resb 1
    35 FFFFFFE7 ??                      ldHasLBA:	resb 1
    36 FFFFFFE8 ????                    ldClusterSize:	resw 1
    37 FFFFFFEA ????                    ldParaPerSector:resw 1
    38 FFFFFFEC ????                    ldLoadingSeg:	resw 1
    39 FFFFFFEE ????                    ldLoadUntilSeg:	resw 1
    40                                  	endstruc
    41                                  
    42                                  
    43                                  %ifndef _MAP
    44                                  %elifempty _MAP
    45                                  %else	; defined non-empty, str or non-str
    46                                  	[map all _MAP]
    47                                  %endif
    48                                  
    49                                  	defaulting
    50                                  
    51                                  	numdef DEBUG0		; use errordata to generate an error code
    52                                  	numdef DEBUG1		; dump_stack_frame after an error occurred
    53                                  	numdef DEBUG2		; dump_stack_frame before blz_depack_safe call
    54                                  	numdef DEBUG3		; dump_stack_frame at start of blz_depack_safe
    55                                  
    56                                  	numdef OPTIMISE_INPUT_SMALL,	0
    57                                  	numdef OPTIMISE_OUYPUT_SMALL,	0
    58                                  	numdef ALLOW_OVERLAPPING,	1	; allow overlapping src and dst
    59                                  	numdef TEST_PROGRAM,		0
    60                                  	numdef TEST_PROGRAM_DECOMPRESSED_SIZE,		0,0
    61                                  %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE
    62                                   %error Test program has to learn of decompressed size.
    63                                  %endif
    64                                  	numdef TEST_PROGRESS,	0
    65                                  
    66                                  	numdef EXEC_OFFSET,	0
    67                                  	numdef EXEC_SEGMENT,	0
    68                                  	numdef IMAGE_EXE,	0
    69                                  %if ! _IMAGE_EXE && _TEST_PROGRAM
    70                                   %error Test program can only be used as EXE.
    71                                  %endif
    72                                  	numdef IMAGE_EXE_CS,	-16	; relative-segment for CS
    73                                  	numdef IMAGE_EXE_IP,	256 +64	; value for IP
    74                                  		; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0.
    75                                  	numdef IMAGE_EXE_SS,	-16	; relative-segment for SS
    76                                  	numdef IMAGE_EXE_SP,	0FFFEh	; value for SP (0 underflows)
    77                                  	numdef IMAGE_EXE_AUTO_STACK,	0, 2048	; use stack behind image
    78                                  		; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of
    79                                  		;  the same name. This one is only used as a flag; if non-zero,
    80                                  		;  keep the stack given to us by iniload; if zero, set up the
    81                                  		;  stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP.
    82                                  	numdef IMAGE_EXE_GET_COM_STACK, 0
    83                                  					; set up stack for flat .COM style entry
    84                                  	numdef DEVICE,			0
    85                                  	gendef DEVICE_NAME,		""
    86                                  	numdef DEVICE_ATTRIBUTE,	8000h
    87                                  	numdef DEVICE_ZERO_ENTRYPOINT,	0
    88                                  	numdef BOOTLDR,		1	; support boot loaded entrypoint
    89                                  
    90                                  	numdef BRIEFLZ,		0
    91                                  	numdef LZ4,		0
    92                                  	numdef SNAPPY,		0
    93                                  	numdef EXODECR,		0
    94                                  	numdef X,		0
    95                                  	numdef HEATSHRINK,	0
    96                                  	numdef LZD,		0
    97                                  	numdef LZO,		0
    98                                  	numdef LZSA2,		0
    99                                  	numdef APL,		0
   100                                  	numdef BZP,		0
   101                                  	numdef ZEROCOMP,	0
   102                                  	numdef MVCOMP,		0
   103                                  	numdef LZEXEDAT,	0
   104                                  %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK 	+ !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP 	+ !!_MVCOMP + !!_LZEXEDAT) != 1
   107                                   %fatal Exactly one compression method must be selected.
   108                                  %endif
   109                                  %assign ADDITIONAL_MEMORY 0
   110                                  %if _BRIEFLZ
   111                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BLZ"
   112                                  %elif _LZ4
   113                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ4"
   114                                  %elif _SNAPPY
   115                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SZ"
   116                                  %elif _EXODECR
   117                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.EXO"
   118                                  %elif _X
   119                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.X"
   120                                  %elif _HEATSHRINK
   121                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.HS"
   122                                  %elif _LZD
   123                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZ"
   124                                  %elif _LZO
   125                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZO"
   126                                  %elif _LZSA2
   127                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.SA2"
   128                                  %elif _APL
   129                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.APL"
   130                                  %elif _BZP
   131                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.BZP"
   132                                  %elif _ZEROCOMP
   133                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.ZER"
   134                                  %elif _MVCOMP
   135                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.MV"
   136                                  %elif _LZEXEDAT
   137                                  	strdef PAYLOAD_FILE,	"lDOSLOAD.LZE"
   138                                  %endif
   139                                  	numdef PAYLOAD_KERNEL_MAX_PARAS,	0, 0
   140                                  %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE)
   141                                   %error Kernel mode max paras requires building dual-mode or triple-mode executable
   142                                  %endif
   143                                  	numdef COUNTER,		0, 32
   144                                  %if (_COUNTER - 1) & _COUNTER
   145                                   %error COUNTER must be a power of two
   146                                  %endif
   147                                  	numdef PROGRESS,	0, 1
   148                                  	numdef PROGRESSAMOUNT,	0, 0
   149                                  	numdef PROGRESSMULTI,	1
   150                                  	numdef PROGRESSVAR,	1
   151                                  	numdef PROGRESSVARNAME, ""
   152                                  	numdef PROGRESSDEFAULT,	0
   153                                  	numdef PROGRESSDEFAULTAPP,	_PROGRESSDEFAULT
   154                                  	numdef PROGRESSDEFAULTDEVICE,	_PROGRESSDEFAULT
   155                                  	numdef PROGRESSDEFAULTBOOT,1
   156                                  	numdef PASSLCFG, 0
   157                                  	numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG
   158                                  
   159                                  
   160                                  %define MODULE inicomp
   161                                  	strdef INILOAD_CFG, ""
   162                                  %ifnidn _INILOAD_CFG, ""
   163                                   %include _INILOAD_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> strdef INILOAD_SIGNATURE, "OS"
     3                              <1> %assign _DEVICE 0
     4                              <1> %ifidni module, lkernpl
     5                              <1>  %define _PAYLOAD_FILE "msbio.bin"
     6                              <1> %endif
     7                              <1> %define _PAYLOAD_BIO_FILE "msbio.bin"
     8                              <1> %define _PAYLOAD_DOS_FILE "empty.bin"
     9                              <1> %ifn _TEST_PROGRAM
    10                              <1>  numdef SECOND_PAYLOAD_EXE, 1
    11                              <1>  strdef SECOND_PAYLOAD_FILE, "tmp/payload2.bin"
    12                              <1>  numdef SECOND_PAYLOAD_EXE_IP, 256
    13                              <1>  numdef SECOND_PAYLOAD_EXE_AUTO_STACK, 2048, 2048
    14                              <1>  numdef SECOND_PAYLOAD_EXE_MIN, 68048
    15                              <1> 
    16                              <1>  numdef SECOND_PAYLOAD_EXE_MAX, 0
    17                              <1>  strdef EXE_TRAIL_INCBIN, "tmp/trail.bin"
    18                              <1> %endif
   164                                  %endif
   165                                  	strdef LCFG_CFG, ""
   166                                  
   167                                  %if _DEVICE
   168                                   %ifidn _DEVICE_NAME, ""
   169                                    %error Device name must be set
   170                                   %endif
   171                                  %endif
   172                                  
   173                                  
   174                                  	cpu 8086
   175                                  	addsection INIT0, start=0 vstart=0
   176                                  init0_start:
   177                                  %if _DEVICE
   178                                  		; The device header is of a fixed format.
   179                                  		;  For our purposes, the 4-byte code for
   180                                  		;  each the strategy entry and the
   181                                  		;  interrupt entry is part of this format.
   182                                  		; (DOS may read the attributes or entrypoint
   183                                  		;  offsets before calling either, so in the inicomp
   184                                  		;  stage we need to recreate in the entrypoints part
   185                                  		;  exactly what the application has here.)
   186                                  		; _PASSLCFG: The lCFG block is passed in the dword
   187                                  		;  behind the interrupt entry.
   188                                  device_header:
   189                                  .next:
   190                                   %if _DEVICE_ZERO_ENTRYPOINT
   191                                  	fill 2, -1, jmp strict short j_zero_entrypoint
   192                                  	dw -1
   193                                   %else
   194                                  	dd -1				; link to next device
   195                                   %endif
   196                                  .attributes:
   197                                  	dw _DEVICE_ATTRIBUTE		; attributes
   198                                  .strategy:
   199                                  	dw .strategy_entry		; -> strategy entry
   200                                  .interrupt:
   201                                  	dw .interrupt_entry		; -> interrupt entry
   202                                  .name:
   203                                  	fill 8, 32, db _DEVICE_NAME	; character device name,
   204                                  					;  or block device number of units
   205                                  					;  + optional name
   206                                  .strategy_entry:
   207                                  	fill 4, 90h, jmp device_entrypoint
   208                                  .interrupt_entry:
   209                                  	fill 4, 90h, retf
   210                                  .pass_lcfg:
   211                                  %endif
   212                                  
   213                                  
   214                                  %if _IMAGE_EXE || _DEVICE
   215                                  	nop
   216                                  	align 32, nop
   217                                  init0_kernel_entry:
   218                                  		; cs:ip = load seg : 32 here
   219                                  %if ($ - $$) != 32
   220                                   %error Wrong kernel mode entrypoint
   221                                  %endif
   222                                  %if _TEST_PROGRAM
   223                                  @@:
   224                                  	int3
   225                                  	sti
   226                                  	hlt
   227                                  	jmp @B
   228                                  %endif
   229                                  %if _BOOTLDR
   230                                  %if ! _IMAGE_EXE
   231                                  j_zero_entrypoint:
   232                                  %endif
   233                                  	xor bx, bx		; 0 = kernel mode
   234                                  	push ax
   235                                  	mov ax, cs
   236                                  	add ax, (init0_end - init0_start) >> 4
   237                                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   238                                  	mov si, 60h		; => destination
   239                                  	jmp init0_common
   240                                  %endif
   241                                  
   242                                   %if _IMAGE_EXE
   243                                  	align 64, nop
   244                                  j_zero_entrypoint:
   245                                  init0_exe_entry:
   246                                  		; NOTE:	This part is called with ip = 256 + 64, cs = PSP.
   247                                  %if ($ - $$) != 64
   248                                   %error Wrong EXE mode entrypoint
   249                                  %endif
   250                                  %if _IMAGE_EXE_GET_COM_STACK
   251                                  	mov bx, ds		; => PSP
   252                                  	dec bx			; => MCB
   253                                  	mov ds, bx
   254                                  	add bx, word [3]	; add size of memory block
   255                                  	sub bx, -1 + paras(512)	; add one, then subtract enough paragraphs
   256                                  	cli
   257                                  	mov ss, bx
   258                                  	mov sp, 512		; -> new stack
   259                                  	sti
   260                                  %endif
   261                                  	mov bx, 1		; EXE mode
   262                                  	push ax
   263                                    %if _TEST_PROGRAM
   264                                  	mov si, 81h
   265                                  	xor dx, dx
   266                                  	xor ax, ax
   267                                  cmdline:
   268                                  .:
   269                                  	lodsb
   270                                  	cmp al, 9
   271                                  	je .
   272                                  	cmp al, 32
   273                                  	je .
   274                                  	cmp al, 13
   275                                  	je .end
   276                                  	cmp al, '0'
   277                                  	jb .notdigit
   278                                  	cmp al, '9'
   279                                  	ja .notdigit
   280                                  .digit:
   281                                  	sub al, '0'
   282                                  	mov cx, dx		; times 1
   283                                  	add dx, dx
   284                                  	jc .invalid
   285                                  	add dx, dx		; times 4
   286                                  	jc .invalid
   287                                  	add dx, cx		; times 5
   288                                  	jc .invalid
   289                                  	add dx, dx		; times 10
   290                                  	jc .invalid
   291                                  	add dx, ax		; add in low digit
   292                                  	jc .invalid
   293                                  	jmp .
   294                                  
   295                                  .notdigit:
   296                                  	cmp al, 'A'
   297                                  	je .a
   298                                  	cmp al, 'a'
   299                                  	je .a
   300                                  	cmp al, 'B'
   301                                  	je .b
   302                                  	cmp al, 'b'
   303                                  	je .b
   304                                  	cmp al, 'C'
   305                                  	je .c
   306                                  	cmp al, 'c'
   307                                  	je .c
   308                                  .invalid:
   309                                  	mov dx, -1		; invalid
   310                                  	jmp .end
   311                                  
   312                                  .a:
   313                                  	and bh, ~ 80h		; A mode. determine min alloc size
   314                                  	jmp .
   315                                  
   316                                  .b:
   317                                  	or bh, 80h		; B mode. repeat depack, counter in command line
   318                                  	jmp .
   319                                  
   320                                  .c:
   321                                  	or bh, 40h		; C mode. how often would the counter be called
   322                                  	jmp .
   323                                  
   324                                  .end:
   325                                  	push dx
   326                                    %endif
   327                                  	mov dx, ss		; => after end of available space
   328                                  	mov ax, cs
   329                                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   330                                  	mov si, cs
   331                                  	add si, 256 >> 4	; => destination
   332                                   %endif
   333                                  
   334                                  init0_common:
   335                                  		; REM:	This part must be position-independent, as it is
   336                                  		;	 called either with ip = init0_common (kernel mode
   337                                  		;	 or device mode)
   338                                  		;	 or ip = init0_common + 256 (application mode).
   339                                  		; INP:	si => depack destination
   340                                  		;	ax => source of payload + INIT1
   341                                  		;	dx => behind available memory
   342                                  		; OUT:	cs:ip -> init1_start:
   343                                  		;	ax => INIT1
   344                                  		;	dx => payload source
   345                                  		;	si => depack destination
   346                                  		;	bx = mode
   347                                  	cld
   348                                  %if _TEST_PROGRAM
   349                                  	sub dx, ( (payload_end - payload) ) >> 4
   350                                  	jc .error
   351                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		+ (init2_end - init2_start) 		) >> 4
   357                                  	sub dx, cx
   358                                  	jc .error
   359                                  	cmp dx, ax
   360                                  	jb .error
   361                                  %else
   362                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   367                                  				; cx = amount paragraphs in INIT0B + payload + INIT1
   368                                  	sub dx, cx		; => destination for INIT0B + payload + INIT1
   369                                  				;  (highest possible spot in available memory)
   370                                  %endif
   371                                  	push si			; preserve destination
   372                                  	call init0_movp		; move up payload + INIT1
   373                                  	pop si
   374                                  %else
   375 00000000 FC                      	cld
   376 00000001 8CC8                    	mov ax, cs
   377 00000003 83C00E                  	add ax, (init0_end - init0_start) >> 4
   378 00000006 B90A0D                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   383 00000009 8B56E2                  	mov dx, word [ bp + ldLoadTop ]
   384 0000000C 29CA                    	sub dx, cx
   385 0000000E E83F00                  	call init0_movp
   386                                  %endif
   387                                  
   388                                  %if _LCFG && ! _TEST_PROGRAM
   389 00000011 0E                      	push cs
   390 00000012 E80000                  	call @F			; position-independent far pointer
   391                                  @@:
   392 00000015 58                      	pop ax
   393 00000016 83C01B                  	add ax, lcfg - @B	; -> lCFG block
   394 00000019 50                      	push ax
   395                                  %endif
   396                                  
   397 0000001A 89D0                    	mov ax, dx		; => INIT0B
   398                                  				;  (same as => payload if INIT0B is empty)
   399                                  %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM
   400 0000001C 83C205                  	add dx, ( 		+ (init0b_end - init0b_start) 		) >> 4		; => payload
   403                                  %else
   404                                   %if _TEST_PROGRAM
   405                                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4		; => INIT2
   410                                   %else
   411                                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   415                                   %endif
   416                                  %endif
   417 0000001F 31C9                    	xor cx, cx
   418 00000021 50                      	push ax
   419 00000022 51                      	push cx
   420 00000023 CB                      	retf			; jump to relocated
   421                                  				;  INIT0B:init0b_start
   422                                  				;  or INIT1:init1_start
   423                                  				;  or INIT2:init2_start
   424                                  
   425                                  
   426                                  %if _TEST_PROGRAM
   427                                  .error:
   428                                  	mov di, bx		; whichtest
   429                                  
   430                                  	push cs
   431                                  	pop ds
   432                                  	mov dx, init0_msg.error_stderr + 256
   433                                  	mov cx, init0_msg.error_stderr.length
   434                                  	mov bx, 2
   435                                  	mov ah, 40h
   436                                  	int 21h
   437                                  
   438                                  	test di, 4000h		; whichtest
   439                                  	jz @F
   440                                  	mov dx, init0_msg.error_c_stdout + 256
   441                                  	mov cx, init0_msg.error_c_stdout.length
   442                                  	jmp @FF
   443                                  @@:
   444                                  	test di, di		; whichtest
   445                                  	js @FF
   446                                  	mov dx, init0_msg.error_stdout + 256
   447                                  	mov cx, init0_msg.error_stdout.length
   448                                  @@:
   449                                  	mov bx, 1
   450                                  	mov ah, 40h
   451                                  	int 21h
   452                                  @@:
   453                                  	mov ax, 4CFFh
   454                                  	int 21h
   455                                  %endif
   456                                  
   457                                  
   458                                  %if _LCFG
   459                                  	%imacro lcfgoption 3+.nolist
   460                                  	_fill %1, 0, lcfg
   461                                  %%start:
   462                                  	%2
   463                                  	%3
   464                                  %%end:
   465                                  %assign %%index %%start - lcfg
   466                                  %rep %%end - %%start
   467                                  %assign LCFGINUSE LCFGINUSE | (1 << %%index)
   468                                   %assign %%index %%index + 1
   469                                  %endrep
   470                                  	%endmacro
   471                                  %assign LCFGINUSE 0
   472                                  
   473 00000024 90<rep Ch>              	align 16
   474                                  lcfg:
   475 00000030 EB1E                    .:		jmp strict short .end
   476 00000032 6C434647                lcfgoption 2,,	db "lCFG"
   477 00000036 3030                    lcfgoption 6,,	db "00"
   478 00000038 FCFFF40C00000000        lcfgoption 8,,	dq .inuse
   479                                   %if _PROGRESS && _PROGRESSMULTI
   480                                    %if _IMAGE_EXE
   481                                  lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP
   482                                    %endif
   483                                    %if _DEVICE
   484                                  lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE
   485                                    %endif
   486                                    %if _BOOTLDR
   487 00000040 00<rep 2h>01            lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT
   488                                    %endif
   489                                   %endif
   490                                  
   491                                  %ifnidn _LCFG_CFG, ""
   492                                   %include _LCFG_CFG
     1                              <1> ; File auto-generated, do not edit.
     2                              <1> %include "src/INC/scanptab.mac"
     1                              <2> 
     2                              <2> %if 0
     3                              <2> 
     4                              <2> scanptab - Scan partition table (macros)
     5                              <2>  2019, 2025 by E. C. Masloch
     6                              <2> 
     7                              <2> Usage of the works is permitted provided that this
     8                              <2> instrument is retained with the works, so that any entity
     9                              <2> that uses the works is notified of this instrument.
    10                              <2> 
    11                              <2> DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
    12                              <2> 
    13                              <2> %endif
    14                              <2> 
    15                              <2> mode_all_ext5			equ 00b
    16                              <2> mode_ignore_ext5		equ 01b
    17                              <2> mode_first_ext5			equ 10b
    18                              <2> mode_first_type_ext5		equ 11b
    19                              <2> 
    20                              <2> mode_all_ext15			equ 00b << 2
    21                              <2> mode_ignore_ext15		equ 01b << 2
    22                              <2> mode_first_ext15		equ 10b << 2
    23                              <2> mode_first_type_ext15		equ 11b << 2
    24                              <2> 
    25                              <2> mode_all_ext85			equ 00b << 4
    26                              <2> mode_ignore_ext85		equ 01b << 4
    27                              <2> mode_first_ext85		equ 10b << 4
    28                              <2> mode_first_type_ext85		equ 11b << 4
    29                              <2> 
    30                              <2> mode_ignore_subsequent_nested	equ            1_00_00_00b
    31                              <2> mode_ignore_subsequent_logical	equ           10_00_00_00b
    32                              <2> mode_ignore_subsequent_primary	equ          100_00_00_00b
    33                              <2> mode_traditional_order_logical	equ         1000_00_00_00b
    34                              <2> mode_active_priority		equ       1_0000_00_00_00b
    35                              <2> mode_subsequent_primary_after	equ      10_0000_00_00_00b
    36                              <2> mode_disable_fat32		equ 00_1000_0000_00_00_00b
    37                              <2> mode_disable_lba		equ 01_0000_0000_00_00_00b
    38                              <2> mode_dlasort_zero		equ 10_0000_0000_00_00_00b
     3                              <1> %include "src/INC/verbose.mac"
     1                              <2> 
     2                              <2> ; Public Domain, 2025 by E. C. Masloch
     3                              <2> 
     4                              <2> verbose_intro	equ 1
     5                              <2> verbose_xms	equ 2
     6                              <2> verbose_cds	equ 4
     4                              <1> %include "src/INC/haltflag.mac"
     1                              <2> 
     2                              <2> ; Public Domain
     3                              <2> 
     4                              <2> flag_no_halt_tagcrash	equ 1
     5                              <2> flag_no_halt_mcb	equ 2
     6                              <2> flag_no_halt_hmcb	equ 4
     7                              <2> flag_no_halt_hmcb_free	equ 8
     5 00000043 0000                <1> lcfgoption 20, .checkdebugger:, db 0
     6 00000045 01                  <1> lcfgoption 21, .verbose:, db verbose_intro
     7 00000046 0000                <1> lcfgoption 22, .scanmode:, dw 0
     8 00000048 00<rep 2h>0C00      <1> lcfgoption 26, .haltflag:, dw 0 | flag_no_halt_hmcb | flag_no_halt_hmcb_free
   493                                  %endif
   494                                  
   495 0000004C 00<rep 4h>              lcfgoption 32,,
   496                                  .end:
   497                                  .size: equ .end - .
   498                                  .inuse equ LCFGINUSE
   499                                  %endif
   500                                  
   501                                  
   502                                  %if _DEVICE
   503                                  device_entrypoint:
   504                                  %if _TEST_PROGRAM
   505                                  @@:
   506                                  	int3
   507                                  	sti
   508                                  	hlt
   509                                  	jmp @B
   510                                  %endif
   511                                  	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   512                                  	je @F
   513                                  
   514                                  	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   515                                  	retf
   516                                  
   517                                  @@:
   518                                  	or word [cs:device_header.next], -1
   519                                  	push cs
   520                                  	push word [cs:device_header.strategy]
   521                                  					; -> far return to payload's strategy
   522                                  	push bp
   523                                  	push ds
   524                                  	push si
   525                                  	push di
   526                                  	push dx
   527                                  	push cx
   528                                  	push ax
   529                                  	push bx
   530                                  	push es
   531                                  
   532                                  	mov dx, word [es:bx + 14]
   533                                  	mov cl, 4
   534                                  	shr dx, cl		; = how many full paragraphs (rounded down)
   535                                  	add dx, word [es:bx + 14 + 2]
   536                                  				; ax => behind end
   537                                  
   538                                  	mov di, cs
   539                                  image_size: equ  ( 		+ (init0_end - init0_start) 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   545                                  	add di, image_size >> 4		; di => end of image
   546                                  
   547                                  	cmp dx, di			; enough memory to hold all of us ?
   548                                  	jb @F				; no -->
   549                                  				; yes
   550                                  .have_some_memory:
   551                                  				; dx => after end of memory
   552                                  	mov bx, 2		; device mode
   553                                  	push ax
   554                                  	mov ax, cs
   555                                  	add ax, (init0_end - init0_start) >> 4
   556                                  	mov si, cs		; => destination
   557                                  	jmp init0_common
   558                                  
   559                                  
   560                                  @@:
   561                                  	push cs
   562                                  	pop ds
   563                                  	mov dx, .msg_no_memory
   564                                  	mov ah, 09h
   565                                  	int 21h
   566                                  
   567                                  	mov ax, 3000h
   568                                  	int 21h
   569                                  	cmp al, 5
   570                                  	jae @F
   571                                  	mov dx, .msg_dos_below_5
   572                                  	mov ah, 09h
   573                                  	int 21h
   574                                  @@:
   575                                  
   576                                  	mov dx, .msg_linebreak
   577                                  	mov ah, 09h
   578                                  	int 21h
   579                                  
   580                                  		; tear down the stack frame and modify the request header
   581                                  	pop es
   582                                  	pop bx
   583                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   584                                  	mov byte [es:bx + 13], 0	; set number of units = 0
   585                                  	mov word [es:bx + 14 + 2], cs
   586                                  	and word [es:bx + 14], 0	; -> after end of memory to allocate
   587                                  	pop ax
   588                                  	pop cx
   589                                  	pop dx
   590                                  	pop di
   591                                  	pop si
   592                                  	pop ds
   593                                  	pop bp
   594                                  	add sp, 4		; discard far return to payload's strategy
   595                                  	retf			; return to DOS
   596                                  
   597                                  
   598                                  .msg_no_memory:		ascic "Load error: Not enough memory."
   599                                  .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   600                                  .msg_linebreak:		ascic 13,10
   601                                  %endif
   602                                  
   603                                  
   604                                  		; Move paragraphs
   605                                  		;
   606                                  		; INP:	ax => source
   607                                  		;	dx => destination
   608                                  		;	cx = number of paragraphs
   609                                  		; CHG:	cx, ds, si, es, di
   610                                  		; OUT:	ax and dx unchanged
   611                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
   612                                  		;	Do not provide a wrapped/HMA source or destination!
   613                                  init0_movp:
   614 00000050 39D0                    	cmp ax, dx		; source above destination ?
   615 00000052 770A                    	ja .up			; yes, move up (forwards) -->
   616 00000054 747B                    	je .return		; same, no need to move -->
   617 00000056 50                      	push ax
   618 00000057 01C8                    	add ax, cx		; (expected not to carry)
   619 00000059 39D0                    	cmp ax, dx		; end of source is above destination ?
   620 0000005B 58                      	pop ax
   621 0000005C 7730                    	ja .down		; yes, move from top down -->
   622                                  	; Here, the end of source is below-or-equal the destination,
   623                                  	;  so they do not overlap. In this case we prefer moving up.
   624                                  
   625                                  .up:
   626 0000005E 50                      	push ax
   627 0000005F 52                      	push dx
   628                                  .uploop:
   629 00000060 8ED8                    	mov ds, ax
   630 00000062 8EC2                    	mov es, dx
   631 00000064 31FF                    	xor di, di
   632 00000066 31F6                    	xor si, si		; -> start of segment
   633 00000068 81E90010                	sub cx, 1000h		; 64 KiB left ?
   634 0000006C 7610                    	jbe .uplast		; no -->
   635 0000006E 51                      	push cx
   636 0000006F B90080                  	mov cx, 10000h /2
   637 00000072 F3A5                    	rep movsw		; move 64 KiB
   638 00000074 59                      	pop cx
   639 00000075 050010                  	add ax, 1000h
   640 00000078 81C20010                	add dx, 1000h		; -> next segment
   641 0000007C EBE2                    	jmp short .uploop	; proceed for more -->
   642                                  .uplast:
   643 0000007E 81C10010                	add cx, 1000h		; restore counter
   644 00000082 D1E1                    	shl cx, 1
   645 00000084 D1E1                    	shl cx, 1
   646 00000086 D1E1                    	shl cx, 1		; *8, paragraphs to words
   647 00000088 F3A5                    	rep movsw		; move last part
   648 0000008A 5A                      	pop dx
   649 0000008B 58                      	pop ax
   650 0000008C EB43                    	jmp short .return
   651                                  
   652                                  .down:
   653 0000008E FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   654                                  .dnloop:
   655 0000008F 81E90010                	sub cx, 1000h		; 64 KiB left ?
   656 00000093 761A                    	jbe .dnlast		; no -->
   657 00000095 50                      	push ax
   658 00000096 52                      	push dx
   659 00000097 01C8                    	add ax, cx
   660 00000099 01CA                    	add dx, cx
   661 0000009B 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   662 0000009D 8EC2                    	mov es, dx
   663 0000009F 5A                      	pop dx
   664 000000A0 58                      	pop ax
   665 000000A1 BFFEFF                  	mov di, -2
   666 000000A4 89FE                    	mov si, di		; moved from last word down
   667 000000A6 51                      	push cx
   668 000000A7 B90080                  	mov cx, 10000h /2
   669 000000AA F3A5                    	rep movsw		; move 64 KiB
   670 000000AC 59                      	pop cx
   671 000000AD EBE0                    	jmp short .dnloop	; proceed for more -->
   672                                  .dnlast:
   673 000000AF 81C10010                	add cx, 1000h		; restore counter
   674 000000B3 D1E1                    	shl cx, 1
   675 000000B5 D1E1                    	shl cx, 1
   676 000000B7 D1E1                    	shl cx, 1		; *8, paragraphs to words
   677 000000B9 89CF                    	mov di, cx
   678 000000BB 4F                      	dec di
   679 000000BC D1E7                    	shl di, 1		; words to offset, -> last word
   680 000000BE 89FE                    	mov si, di
   681 000000C0 8ED8                    	mov ds, ax
   682 000000C2 8EC2                    	mov es, dx		; first segment correct
   683                                  
   684                                  
   685                                  	numdef AMD_ERRATUM_109_WORKAROUND, 1
   686                                  %if 0
   687                                  
   688                                  Jack R. Ellis pointed out this erratum:
   689                                  
   690                                  Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69:
   691                                  
   692                                  109   Certain Reverse REP MOVS May Produce Unpredictable Behavior
   693                                  
   694                                  Description
   695                                  
   696                                  In certain situations a REP MOVS instruction may lead to
   697                                  incorrect results. An incorrect address size, data size
   698                                  or source operand segment may be used or a succeeding
   699                                  instruction may be skipped. This may occur under the
   700                                  following conditions:
   701                                  
   702                                  * EFLAGS.DF=1 (the string is being moved in the reverse direction).
   703                                  
   704                                  * The number of items being moved (RCX) is between 1 and 20.
   705                                  
   706                                  * The REP MOVS instruction is preceded by some microcoded instruction
   707                                    that has not completely retired by the time the REP MOVS begins
   708                                    execution. The set of such instructions includes BOUND, CLI, LDS,
   709                                    LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions.
   710                                  
   711                                  Potential Effect on System
   712                                  
   713                                  Incorrect results may be produced or the system may hang.
   714                                  
   715                                  Suggested Workaround
   716                                  
   717                                  Contact your AMD representative for information on a BIOS update.
   718                                  
   719                                  %endif
   720                                  
   721                                  %if _AMD_ERRATUM_109_WORKAROUND
   722 000000C4 E308                    	jcxz @FF
   723 000000C6 83F914                  	cmp cx, 20
   724 000000C9 7703                    	ja @FF
   725                                  @@:
   726 000000CB A5                      	movsw
   727 000000CC E2FD                    	loop @B
   728                                  @@:
   729                                  %endif
   730 000000CE F3A5                    	rep movsw		; move first part
   731 000000D0 FC                      	cld
   732                                  .return:
   733 000000D1 C3                      	retn
   734                                  
   735                                  
   736                                  	addsection INIT0B, align=16 vstart=0 follows=INIT0
   737                                  		; INP:	ax:cx = cs:ip = cs:0
   738                                  		;	ax => INIT0B
   739                                  		;	dx => payload source
   740                                  		;	ss:sp -> (dword pointer to lCFG block)
   741                                  		;	if app/device mode supported:
   742                                  		;	 si => depack destination
   743                                  		;	 bx = mode
   744                                  init0b_start:
   745                                  %if _LCFG || _PROGRESS
   746                                  
   747 00000000 055C0C                  	add ax, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		) >> 4		; => INIT1
   751                                  
   752                                  %if _LCFG && _PASSLCFG
   753                                   %if (_IMAGE_EXE || _DEVICE)
   754                                  	mov cx, si		; preserve si
   755                                   %endif
   756 00000003 5E                      	pop si
   757 00000004 1F                      	pop ds			; -> lCFG block
   758 00000005 8EC0                    	mov es, ax
   759 00000007 BF[C00A]                	mov di, transfer_lcfg_block
   760                                  				; -> destination
   761                                   %if (_IMAGE_EXE || _DEVICE)
   762                                  	push cx
   763                                   %endif
   764 0000000A 57                      	push di
   765 0000000B B91000                  	mov cx, words(lcfg.size)
   766 0000000E F3A5                    	rep movsw		; cx = 0
   767 00000010 5F                      	pop di			; es:di -> relocated lCFG block, same difference
   768                                   %if (_IMAGE_EXE || _DEVICE)
   769                                  	pop si			; preserve si
   770                                   %endif
   771                                  %elif _LCFG
   772                                  	pop di
   773                                  	pop es			; es:di -> (original) lCFG block
   774                                  %endif
   775                                  
   776 00000011 50                      	push ax
   777 00000012 51                      	push cx			; -> far return address to init1_start
   778                                  
   779                                  %if _PROGRESS && _PROGRESSMULTI
   780                                   %if (_IMAGE_EXE || _DEVICE)
   781                                  	push si
   782                                  	push bx
   783                                   %endif
   784                                   %if _BOOTLDR
   785                                    %if _LCFG
   786 00000013 31C0                    	xor ax, ax
   787 00000015 268A4512                	mov al, byte [es:di + lcfg.progress_boot - lcfg]
   788 00000019 97                      	xchg di, ax		; di = boot default progress
   789                                  				; es:ax -> lCFG block
   790                                    %else			; _LCFG
   791                                  	mov di, _PROGRESSDEFAULTBOOT
   792                                    %endif		; _LCFG
   793                                   %endif			; _BOOTLDR
   794                                   %if (_IMAGE_EXE || _DEVICE)
   795                                    %if _BOOTLDR
   796                                  	test bx, bx
   797                                  	jz .default
   798                                    %endif		; _BOOTLDR
   799                                    %if _LCFG
   800                                  	push es
   801                                     %if _BOOTLDR
   802                                  	push ax			; -> lCFG block
   803                                     %else		; _BOOTLDR
   804                                  	push di
   805                                     %endif		; _BOOTLDR
   806                                    %endif		; _LCFG
   807                                    %if _PROGRESSVAR
   808                                  	mov ah, 51h
   809                                  	int 21h
   810                                  @@:
   811                                  	mov ds, bx
   812                                  	mov ax, word [2Ch]
   813                                  	test ax, ax
   814                                  	jnz .gotenv
   815                                  	mov ax, word [16h]
   816                                  	inc ax
   817                                  	jz .default_nonboot
   818                                  	dec ax
   819                                  	jz .default_nonboot
   820                                  	cmp bx, ax
   821                                  	je .default_nonboot
   822                                  	xchg bx, ax
   823                                  	jmp @B
   824                                  
   825                                  .gotenv:
   826                                  	push cs
   827                                  	pop ds				; => cs
   828                                  	mov es, ax			; => environment
   829                                   %ifnidni _PROGRESSVARNAME, ""
   830                                  	mov bx, progressvarname1
   831                                  	call .findenv
   832                                  	jnc .foundenv			; match -->
   833                                  	mov bx, progressvarname2
   834                                   %endif
   835                                  	call .findenv
   836                                  	jnc .foundenv			; match -->
   837                                  	jmp .default_nonboot
   838                                  
   839                                  .findenv:
   840                                  	xor di, di
   841                                  @@:
   842                                   %ifnidni _PROGRESSVARNAME, ""
   843                                  	mov si, bx			; -> variable name
   844                                   %else
   845                                  	mov si, progressvarname2	; -> variable name
   846                                   %endif
   847                                  	xor ax, ax
   848                                  	lodsb				; get length
   849                                  	xchg cx, ax			; cx = length
   850                                  	push di
   851                                  	repe cmpsb			; match ?
   852                                  	je .findret_pop			; (NC) yes -->
   853                                  	pop di
   854                                  	mov cx, 8000h			; maximum env size
   855                                  	sub cx, di			; any left ?
   856                                  	jbe .findret_CY			; no -->
   857                                  	mov al, 0
   858                                  	repne scasb			; find next NUL
   859                                  	jne .findret_CY
   860                                  	cmp byte [es:di], al		; double NUL ?
   861                                  	jne @B				; no, loop -->
   862                                  .findret_CY:
   863                                  	stc				; not found
   864                                  	retn
   865                                  
   866                                  .findret_pop:
   867                                  	pop cx
   868                                  	retn
   869                                  
   870                                  .foundenv:
   871                                  %if _LCFG
   872                                  	pop si
   873                                  	pop si				; discard far pointer to lCFG
   874                                  %endif
   875                                  	mov si, di			; es:si -> var content
   876                                  	xor di, di			; = 0
   877                                  	xor ax, ax			; ah = 0
   878                                  @@:
   879                                  	es lodsb			; next candidate digit
   880                                  	sub al, '0'			; digit ?
   881                                  	jb @F				; no -->
   882                                  	cmp al, 9
   883                                  	ja @F				; no -->
   884                                  	add di, di			; times 2
   885                                  	mov bx, di
   886                                  	add di, di			; times 4
   887                                  	add di, di			; times 8
   888                                  	add di, bx			; times 8 + times 2 = times 10
   889                                  	add di, ax			; add in next digit
   890                                  	jmp @B				; and loop
   891                                  
   892                                  @@:
   893                                  	and di, 31			; mask to low 5 bits
   894                                  	jmp @F
   895                                    %endif	; _PROGRESSVAR
   896                                  
   897                                  .default_nonboot:
   898                                  %if _LCFG
   899                                  	pop di
   900                                  	pop es			; -> lCFG block
   901                                  	pop bx			; = 1 if app, = 2 if device
   902                                  	push bx
   903                                  	mov ax, word [es:di + lcfg.progress_app - lcfg]
   904                                   %if _DEVICE
   905                                    %if lcfg.progress_app + 1 != lcfg.progress_dev
   906                                     %error Unexpected layout
   907                                    %endif
   908                                  				; al = app, ah = device
   909                                  	dec bx
   910                                  	jz .default_app
   911                                  	xchg al, ah		; al = device
   912                                  .default_app:
   913                                   %endif			; _DEVICE
   914                                  	mov ah, 0		; ax = default
   915                                  	xchg di, ax		; di = default
   916                                  %else			; _LCFG
   917                                  	mov di, _PROGRESSDEFAULT
   918                                  %endif			; _LCFG
   919                                  @@:
   920                                  	test di, 16
   921                                  	jz @F
   922                                  	and di, ~16
   923                                  	jmp .outputdevice	; if 16 set skip device check
   924                                  @@:
   925                                  	push dx
   926                                  	mov ax, 4400h		; IOCTL get device information
   927                                  	mov bx, 1		; StdOut
   928                                  	mov dl, 83h		; default if 21.4400 fails
   929                                  	int 21h
   930                                  	test dl, 80h
   931                                  	pop dx
   932                                  	jnz .outputdevice
   933                                  	xor di, di		; stdout is a file: force no progress marker
   934                                  .outputdevice:
   935                                   %endif			; (_IMAGE_EXE || _DEVICE)
   936                                  
   937                                  .default:
   938                                   %if (_IMAGE_EXE || _DEVICE)
   939                                  	pop bx
   940                                  	pop si
   941                                   %endif
   942 0000001A 83FF05                  	cmp di, step_progress_table.amount
   943                                  					; valid ?
   944 0000001D 7202                    	jb @F				; yes -->
   945 0000001F 31FF                    	xor di, di			; disable
   946                                  @@:
   947 00000021 D1E7                    	shl di, 1			; = word index
   948 00000023 59                      	pop cx				; = 0
   949 00000024 1F                      	pop ds				; ds => INIT1
   950                                  
   951 00000025 2E8B85[3A00]            	mov ax, word [cs:step_progress_table + di]
   952                                  					; ax = rel16 for step progress handler
   953 0000002A 1E                      	push ds
   954 0000002B 51                      	push cx				; -> init1_start
   955 0000002C A3[4800]                	mov word [step_progress.handler], ax
   956                                  					; patch it
   957                                  
   958 0000002F 83FF04                  	cmp di, 2 * 2			; none or dots ?
   959 00000032 7305                    	jae @F				; no, skip -->
   960 00000034 C606[0200]A9            	mov byte [..@empty_step_progress], __TEST_IMM16
   961                                  					; for none and dots do not call here
   962                                  @@:
   963                                  %endif			;  _PROGRESS && _PROGRESSMULTI
   964 00000039 CB                      	retf
   965                                  %endif
   966                                  
   967                                  %if _PROGRESS && _PROGRESSMULTI
   968                                  		align 2, db 0
   969                                  step_progress_table:
   970                                  .:
   971 0000003A 1600                    		dw step_progress.0_step - step_progress.base
   972 0000003C 3B00                    		dw step_progress.1_step - step_progress.base
   973 0000003E 0000                    		dw step_progress.2_step - step_progress.base
   974 00000040 4100                    		dw step_progress.3_step - step_progress.base
   975 00000042 8600                    		dw step_progress.4_step - step_progress.base
   976                                  .amount equ ($ - .) / 2
   977                                  
   978                                   %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE)
   979                                    %ifnidni _PROGRESSVARNAME, ""
   980                                  progressvarname1:	counted _PROGRESSVARNAME, '='
   981                                    %endif
   982                                  progressvarname2:	counted "LDOSPROGRESS="
   983                                   %endif
   984                                  %endif
   985                                  
   986 00000044 90<rep Ch>              	align 16
   987                                  init0b_end:
   988                                  
   989                                  
   990                                  	addsection PAYLOAD, align=16 follows=INIT0B
   991                                  payload:
   992 00000000 <bin C56Bh>             	incbin _PAYLOAD_FILE
   993                                  .end:
   994 0000C56B 26<rep 5h>              	align 16, db 38
   995                                  payload_end:
   996                                  
   997                                  %if _OPTIMISE_INPUT_SMALL
   998                                   %ifn (payload_end - payload) <= 65_520
   999                                    %error Input declared small is not small
  1000                                   %endif
  1001                                  %else
  1002                                   %if (payload_end - payload) <= 65_520
  1003                                    %warning Input could be declared small
  1003          ******************       warning: Input could be declared small [-w+user]
  1004                                   %endif
  1005                                  %endif
  1006                                  
  1007                                  
  1008                                  	addsection INIT1, align=16 follows=PAYLOAD vstart=0
  1009                                  init1_start:
  1010                                  		; INP:	ax = cs = INIT1
  1011                                  		;	dx = cs - (payload_end - payload) >> 4 => source data
  1012                                  		;	if kernel mode:
  1013                                  		;	 ss:bp -> LOADDATA and LOADSTACKVARS
  1014                                  		;	 ss:sp -> valid stack above [bp + ldLoadTop]
  1015                                  		;	 60h => destination
  1016                                  		;	any mode:
  1017                                  		;	 ss:sp -> word value for ax
  1018                                  		;	 bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode
  1019                                  		;	 si => destination (60h for kernel mode,
  1020                                  		;		after PSP for EXE mode,
  1021                                  		;		at device header for device mode)
  1022                                  		;		(not set if only kernel mode supported)
  1023                                  		;	 if EXE mode:
  1024                                  		;	  ss:sp -> valid stack above INIT1
  1025                                  		;	  bp = unset
  1026                                  		;	 if device mode:
  1027                                  		;	  ss:sp -> device entrypoint stack
  1028                                  		;	  holds: es, bx, ax, cx, dx, di, si, ds, bp,
  1029                                  		;		  far address of payload strategy entrypoint,
  1030                                  		;		  far return address to DOS
  1031                                  		;	  bp = unset
  1032                                  		; STT:	UP
  1033                                  		; CHG:	ax, bx, cx, dx, es, ds, si, di
  1034                                  %if _IMAGE_EXE || _DEVICE
  1035                                  	lframe
  1036                                  	lenter
  1037                                  	lvar word,	exemode		; must be bp - 2!
  1038                                  	 push bx
  1039                                   %if ?exemode != -2
  1040                                    %error exemode variable must be directly below bp
  1041                                   %endif
  1042                                  	push si
  1043                                   %if _PROGRESS
  1044                                  	clc			; NC
  1045                                   %endif
  1046                                  %else
  1047 00000000 31DB                    	xor bx, bx		; always tell them it is kernel mode (NC)
  1048                                  %endif
  1049                                  
  1050                                  %if _PROGRESS
  1051                                  	; clc
  1052                                  ..@empty_step_progress:		; SMC, byte patched to __TEST_IMM16 if none or dots
  1053                                   %if _TEST_PROGRAM
  1054                                  	times 3 nop
  1055                                   %else
  1056 00000002 E83100                  	call step_progress.CF	; display empty / 0.0%
  1057                                   %endif
  1058                                  @@:
  1059                                  %endif
  1060                                  
  1061                                  %if _IMAGE_EXE || _DEVICE
  1062                                  	mov es, si		; es => destination
  1063                                  %else
  1064 00000005 B86000                  	mov ax, 60h
  1065 00000008 8EC0                    	mov es, ax		; es => destination
  1066                                  %endif
  1067 0000000A 31FF                    	xor di, di		; -> destination
  1068                                  
  1069 0000000C 8EDA                    	mov ds, dx
  1070 0000000E 31F6                    	xor si, si		; -> source
  1071                                  
  1072 00000010 B96BC5                  	mov cx, (payload.end - payload) & 0FFFFh
  1073                                  %if (payload.end - payload) >> 16
  1074                                  	mov dx, (payload.end - payload) >> 16	; = length of source
  1075                                  %else
  1076 00000013 31D2                    	xor dx, dx
  1077                                  %endif
  1078                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  1079                                  	mov ax, _PAYLOAD_KERNEL_MAX_PARAS
  1080                                  	test bx, bx
  1081                                  	jz @F
  1082                                  %endif
  1083 00000015 B8FFFF                  	mov ax, -1
  1084                                  @@:
  1085                                  
  1086                                  		; INP:	ds:si -> source
  1087                                  		;	dx:cx = length of source
  1088                                  		;	es:di -> destination (below source)
  1089                                  		;	bx = EXE mode flag
  1090                                  		;	 (1 if EXE mode, 0 if kernel mode)
  1091                                  		;	 (always 0 if this is a build without EXE mode)
  1092                                  		;	if _PAYLOAD_KERNEL_MAX_PARAS:
  1093                                  		;	 ax = maximum amount in paragraphs of destination needed
  1094                                  		;	 (-1 if full source should be decompressed)
  1095                                  		;	else:
  1096                                  		;	 ax = -1
  1097                                  		; Note:	The destination reaches up to below the source.
  1098 00000018 E8D603                  	call depack
  1099                                  %ifn _TEST_PROGRAM
  1100 0000001B 720A                    	jc strict short error	; -2 (replaced by retf \ nop)
  1101                                  %endif
  1102                                  %if _IMAGE_EXE || _DEVICE
  1103                                  	pop si			; si
  1104                                   %if _TEST_PROGRAM
  1105                                  	pop ax			; (discard ?exemode, leave bx as returned)
  1106                                   %else
  1107                                  	pop bx			; ?exemode
  1108                                   %endif
  1109                                  	pop bp			; bp
  1110                                  	pop ax			; ax
  1111                                  	lleave ctx
  1112                                  %endif
  1113                                  %if _TEST_PROGRAM
  1114                                  	retf			; +1 (replace jc error)
  1115                                  	nop			; +1
  1116                                  %endif
  1117                                  
  1118                                  %if _DEVICE
  1119                                  	test bl, 2
  1120                                  	jz .jmp_exe_or_kernel_mode
  1121                                  
  1122                                  .jmp_device_mode:
  1123                                  	mov ds, si
  1124                                  	or word [device_header.next], -1
  1125                                  %if _LCFG && _PASSLCFG
  1126                                  	mov word [device_header.pass_lcfg], transfer_lcfg_block
  1127                                  	mov word [device_header.pass_lcfg + 2], cs
  1128                                  %endif
  1129                                  	pop es
  1130                                  	pop bx
  1131                                  	pop ax
  1132                                  	pop cx
  1133                                  	pop dx
  1134                                  	pop di
  1135                                  	pop si
  1136                                  	pop ds
  1137                                  	pop bp
  1138                                  	retf			; transfer to payload strategy entrypoint
  1139                                  				; still on stack: far return address to DOS
  1140                                  
  1141                                  .jmp_exe_or_kernel_mode:
  1142                                  %endif
  1143                                  
  1144                                  %if _IMAGE_EXE
  1145                                  	test bl, 1
  1146                                  	jz .jmp_kernel_mode
  1147                                  
  1148                                  .jmp_exe_mode:
  1149                                  %if ! _IMAGE_EXE_AUTO_STACK
  1150                                  	mov cx, cs
  1151                                  	lea dx, [si + _IMAGE_EXE_SS]
  1152                                  	push dx			; stack = relocated ss value
  1153                                  	add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4
  1154                                  	cmp cx, dx		; INIT1 code is above intended stack ?
  1155                                  	jae @F			; yes -->
  1156                                  
  1157                                  	lframe
  1158                                  	lenter
  1159                                  	lvar	word, exemode
  1160                                  	 push bx
  1161                                   %if ?exemode != -2
  1162                                    %error exemode variable must be directly below bp
  1163                                   %endif
  1164                                  	mov bx, -1		; unimplemented, return error
  1165                                  	jmp error
  1166                                  	lleave ctx
  1167                                  @@:
  1168                                  	cli
  1169                                  	pop ss			; = relocated ss value
  1170                                  	mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh	; change stack
  1171                                  	sti
  1172                                  %endif
  1173                                  
  1174                                  	xor cx, cx
  1175                                  	push cx			; put zero on top of stack
  1176                                  
  1177                                  %if _IMAGE_EXE_IP < 256
  1178                                  	mov cl, _IMAGE_EXE_IP
  1179                                  %elif (_IMAGE_EXE_IP & 255) == 0
  1180                                  	mov ch, _IMAGE_EXE_IP >> 8
  1181                                  %else
  1182                                  	mov cx, _IMAGE_EXE_IP
  1183                                  %endif
  1184                                  
  1185                                  %if _IMAGE_EXE_CS == -16
  1186                                  	add si, -16
  1187                                  	mov ds, si
  1188                                  	mov es, si
  1189                                  %else
  1190                                  	lea dx, [si - 10h]	; => PSP
  1191                                  	mov ds, dx
  1192                                  	mov es, dx		; ds = es => PSP
  1193                                   %if _IMAGE_EXE_CS
  1194                                  	add si, _IMAGE_EXE_CS	; = relocated cs value
  1195                                   %endif
  1196                                  %endif
  1197                                  	push si
  1198                                  	push cx
  1199                                  %if _LCFG && _PASSLCFG
  1200                                  	mov di, transfer_lcfg_block
  1201                                  	mov cx, cs
  1202                                  %endif
  1203                                  	retf			; jump to EXE mode of image
  1204                                  
  1205                                  %endif
  1206                                  .jmp_kernel_mode:
  1207                                  %if _LCFG && _PASSLCFG
  1208 0000001D BF[C00A]                	mov di, transfer_lcfg_block
  1209 00000020 8CC9                    	mov cx, cs
  1210                                  %endif
  1211 00000022 EA01006000              	jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET
  1212                                  
  1213                                  
  1214                                  %if _TEST_PROGRAM
  1215                                  disp_al_counter:
  1216                                  	inc word [cs:init1_c_mode_counter]	; 5 bytes
  1217                                  	retn					; 1 byte
  1218                                  
  1219                                  init1_c_mode_counter:		dw 0		; 2 bytes, total 8
  1220                                  %else
  1221                                   %if _PROGRESS
  1222                                  disp_al_counter equ step_progress
  1223                                   %else
  1224                                  disp_al_counter equ disp_al
  1225                                   %endif
  1226                                  %endif
  1227                                  
  1228                                  
  1229                                  error:
  1230                                   %ifn _TEST_PROGRAM		; 2 bytes
  1231 00000027 0E                      	push cs
  1232 00000028 1F                      	pop ds
  1233                                   %endif
  1234                                  %if _DEBUG0
  1235                                  	mov si, msg.error_begin
  1236                                  	call disp_error
  1237                                  	xchg ax, bx			; ax = error code
  1238                                  	call disp_ax_hex
  1239                                   %ifn _TEST_PROGRAM		; 3 bytes
  1240                                  	mov si, msg.error_end
  1241                                   %endif
  1242                                  %else
  1243                                   %ifn _TEST_PROGRAM		; 3 bytes
  1244 00000029 BE[A601]                	mov si, msg.error
  1245                                   %endif
  1246                                  %endif
  1247                                   %ifn _TEST_PROGRAM		; 3 bytes, total 2 + 3 + 3 = 8
  1248 0000002C E85B01                  	call disp_error
  1249                                   %endif
  1250                                  %if _DEVICE
  1251                                  	test byte [bp - 2], 2
  1252                                  	jz .exit_app_or_kernel
  1253                                  
  1254                                  	pop si				; => device segment
  1255                                  	pop bx				; mode word
  1256                                  	pop bp
  1257                                  	pop ax
  1258                                  	mov es, si
  1259                                  	xor di, di			; -> device header
  1260                                  	 push cs
  1261                                  	 pop ds
  1262                                  	mov si, device_header_copy	; -> to reset header
  1263                                  	mov cx, words(device_header_copy.length)
  1264                                  	rep movsw		; overwrite device header with default
  1265                                  				;  (reset to a valid state after unsuccessful
  1266                                  				;  decompression, which may have partially
  1267                                  				;  written the header already)
  1268                                  	 push es
  1269                                  	 pop ds				; -> device segment
  1270                                  	pop es
  1271                                  	pop bx
  1272                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1273                                  	mov byte [es:bx + 13], 0	; set number of units = 0
  1274                                  	mov word [es:bx + 14 + 2], ds
  1275                                  	and word [es:bx + 14], 0	; -> after end of memory to allocate
  1276                                  	pop ax
  1277                                  	pop cx
  1278                                  	pop dx
  1279                                  	pop di
  1280                                  	pop si
  1281                                  	pop ds
  1282                                  	pop bp
  1283                                  	add sp, 4		; discard far return to payload's strategy
  1284                                  	retf			; return to DOS
  1285                                  
  1286                                  
  1287                                  .exit_app_or_kernel:
  1288                                  %endif
  1289                                  
  1290                                  %if _IMAGE_EXE
  1291                                  %if _BOOTLDR
  1292                                  	test byte [bp - 2], 1
  1293                                  	jz .exit_kernel_mode
  1294                                  %endif
  1295                                  
  1296                                  	mov ax, 4C7Fh
  1297                                  	int 21h
  1298                                  
  1299                                  .exit_kernel_mode:
  1300                                  %endif
  1301                                  %if _BOOTLDR
  1302 0000002F 31C0                    	xor ax, ax
  1303 00000031 CD16                    	int 16h
  1304 00000033 CD19                    	int 19h
  1305                                  %endif
  1306                                  
  1307                                  
  1308                                  %if _PROGRESS
  1309                                  step_progress:
  1310 00000035 F9                      	stc
  1311                                  .CF:
  1312 00000036 53                      	push bx
  1313 00000037 51                      	push cx
  1314 00000038 52                      	push dx
  1315 00000039 1E                      	push ds
  1316 0000003A 56                      	push si
  1317 0000003B 57                      	push di
  1318 0000003C 50                      	push ax
  1319                                  
  1320 0000003D 0E                      	push cs
  1321 0000003E 1F                      	pop ds
  1322                                  
  1323 0000003F 8316[7001]00            	adc word [.counter], 0
  1324 00000044 A1[7001]                	mov ax, word [.counter]
  1325                                  
  1326                                   %if _PROGRESSMULTI
  1327                                    %if _IMAGE_EXE || _DEVICE
  1328                                     %assign defaultprogresshandler _PROGRESSDEFAULT
  1329                                    %else
  1330                                     %assign defaultprogresshandler _PROGRESSDEFAULTBOOT
  1331                                    %endif
  1332 00000047 E93B00                  	jmp strict near . %+ defaultprogresshandler %+ _step
  1333                                  .handler: equ $ - 2		; SMC, patched to dispatch to handler
  1334                                  .base:
  1335                                   %endif
  1336                                  
  1337                                  .2_step:
  1338 0000004A BAE803                  	mov dx, 1000
  1339 0000004D F7E2                    	mul dx			; dx:ax = counter times 1000
  1340                                  %if _PROGRESSAMOUNT
  1341 0000004F B9B100                  	mov cx, _PROGRESSAMOUNT
  1342 00000052 F7F1                    	div cx			; ax = 0..1000
  1343                                  %else
  1344                                   %warning Progress amount is zero
  1345                                  	mov ax, 1
  1346                                  %endif
  1347                                  
  1348                                  %if 0
  1349                                  	cmp word [.display], ax
  1350                                  	je .ret
  1351                                  	mov word [.display], ax
  1352                                  %endif
  1353 00000054 BE[7901]                	mov si, .message_number_end - 1
  1354 00000057 E80E00                  	call .format_percentage
  1355                                  
  1356 0000005A BE[7201]                	mov si, .message
  1357 0000005D E82A01                  	call disp_error
  1358                                  
  1359                                  .ret:
  1360 00000060 58                      	pop ax
  1361                                  .ret_ax:
  1362 00000061 5F                      	pop di
  1363 00000062 5E                      	pop si
  1364 00000063 1F                      	pop ds
  1365 00000064 5A                      	pop dx
  1366 00000065 59                      	pop cx
  1367 00000066 5B                      	pop bx
  1368                                  .retn:
  1369 00000067 C3                      	retn
  1370                                  
  1371                                  
  1372                                  .format_percentage:
  1373 00000068 BB0200                  	mov bx, 2		; skip dot
  1374                                  
  1375 0000006B B90A00                  	mov cx, 10		; base
  1376                                  @@:
  1377 0000006E 31D2                    	xor dx, dx		; dx:ax = current number
  1378 00000070 F7F1                    	div cx			; dl = remainder, ax = next number
  1379 00000072 80C230                  	add dl, '0'		; make decit
  1380 00000075 8814                    	mov byte [si], dl	; store
  1381 00000077 29DE                    	sub si, bx		; -> next digit slot
  1382 00000079 80FB02                  	cmp bl, 2		; did we just store fractional ?
  1383 0000007C B301                    	mov bl, 1		; ! next iteration do not skip dot
  1384 0000007E 74EE                    	je @B			; yes, loop always -->
  1385 00000080 85C0                    	test ax, ax		; nonzero left ?
  1386 00000082 75EA                    	jnz @B			; yes, loop if so -->
  1387 00000084 C3                      	retn
  1388                                  
  1389                                  
  1390                                   %if _PROGRESSMULTI
  1391                                  .0_step: equ .ret
  1392                                  
  1393                                  .1_step:
  1394 00000085 58                      	pop ax
  1395 00000086 E80F01                  	call disp_al
  1396 00000089 EBD6                    	jmp .ret_ax
  1397                                  
  1398                                  .3_step:
  1399 0000008B BB4B00                  	mov bx, 80 - 1 - 4
  1400 0000008E F7E3                    	mul bx			; dx:ax = counter times 75
  1401                                  %if _PROGRESSAMOUNT
  1402 00000090 B9B100                  	mov cx, _PROGRESSAMOUNT
  1403 00000093 F7F1                    	div cx			; ax = 0..75
  1404                                  %else
  1405                                   %warning Progress amount is zero
  1406                                  	mov ax, 1
  1407                                  %endif
  1408                                  
  1409 00000095 3906[6E01]              	cmp word [.display], ax
  1410 00000099 74C5                    	je .ret
  1411 0000009B A3[6E01]                	mov word [.display], ax
  1412                                  
  1413 0000009E 50                      	push ax
  1414 0000009F 91                      	xchg cx, ax
  1415 000000A0 B00D                    	mov al, 13
  1416 000000A2 E8F300                  	call disp_al
  1417 000000A5 B05B                    	mov al, '['
  1418 000000A7 E8EE00                  	call disp_al
  1419 000000AA B020                    	mov al, 32
  1420 000000AC E8E900                  	call disp_al
  1421                                  
  1422 000000AF B023                    	mov al, '#'
  1423 000000B1 E305                    	jcxz @FF
  1424                                  @@:
  1425 000000B3 E8E200                  	call disp_al
  1426 000000B6 E2FB                    	loop @B
  1427                                  @@:
  1428                                  
  1429 000000B8 B020                    	mov al, 32
  1430 000000BA 59                      	pop cx
  1431 000000BB 29CB                    	sub bx, cx
  1432 000000BD 7607                    	jbe @FF
  1433 000000BF 89D9                    	mov cx, bx
  1434                                  @@:
  1435 000000C1 E8D400                  	call disp_al
  1436 000000C4 E2FB                    	loop @B
  1437                                  @@:
  1438                                  
  1439                                  .m4done:
  1440 000000C6 E8CF00                  	call disp_al
  1441 000000C9 B05D                    	mov al, ']'
  1442 000000CB E8CA00                  	call disp_al
  1443 000000CE EB90                    	jmp .ret
  1444                                  
  1445                                  
  1446                                  .4_step:
  1447 000000D0 50                      	push ax
  1448                                  
  1449 000000D1 BAE803                  	mov dx, 1000
  1450 000000D4 F7E2                    	mul dx			; dx:ax = counter times 1000
  1451                                  %if _PROGRESSAMOUNT
  1452 000000D6 B9B100                  	mov cx, _PROGRESSAMOUNT
  1453 000000D9 F7F1                    	div cx			; ax = 0..1000
  1454                                  %else
  1455                                   %warning Progress amount is zero
  1456                                  	mov ax, 1
  1457                                  %endif
  1458                                  
  1459 000000DB BE[8301]                	mov si, .message_4_number_end - 1
  1460 000000DE E887FF                  	call .format_percentage
  1461                                  
  1462 000000E1 58                      	pop ax
  1463 000000E2 BB4B00                  	mov bx, 80 - 1 - 4
  1464 000000E5 F7E3                    	mul bx			; dx:ax = counter times 75
  1465                                  %if _PROGRESSAMOUNT
  1466 000000E7 B9B100                  	mov cx, _PROGRESSAMOUNT
  1467 000000EA F7F1                    	div cx			; ax = 0..75
  1468                                  %else
  1469                                   %warning Progress amount is zero
  1470                                  	mov ax, 1
  1471                                  %endif
  1472                                  
  1473 000000EC 50                      	push ax
  1474 000000ED 91                      	xchg cx, ax
  1475 000000EE B00D                    	mov al, 13
  1476 000000F0 E8A500                  	call disp_al
  1477 000000F3 B05B                    	mov al, '['
  1478 000000F5 E8A000                  	call disp_al
  1479 000000F8 B020                    	mov al, 32
  1480 000000FA E89B00                  	call disp_al
  1481                                  
  1482 000000FD 31FF                    	xor di, di
  1483 000000FF BA2200                  	mov dx, (80 - 1 - 4 - .message_4_length) / 2
  1484 00000102 803E[7F01]20            	cmp byte [.message_4_number], 32
  1485 00000107 7401                    	je @F
  1486 00000109 47                      	inc di
  1487                                  @@:
  1488 0000010A 29FA                    	sub dx, di
  1489                                  
  1490 0000010C B023                    	mov al, '#'
  1491 0000010E E306                    	jcxz @FF
  1492                                  @@:
  1493 00000110 E88500                  	call disp_al
  1494 00000113 4A                      	dec dx
  1495 00000114 E0FA                    	loopnz @B
  1496                                  @@:
  1497                                  
  1498 00000116 85D2                    	test dx, dx
  1499 00000118 752E                    	jnz .notyetm4
  1500                                  
  1501 0000011A BE[7F01]                	mov si, .message_4
  1502 0000011D 29FE                    	sub si, di
  1503 0000011F E86800                  	call disp_error
  1504                                  
  1505 00000122 29F9                    	sub cx, di
  1506 00000124 760E                    	jbe @FF
  1507 00000126 83E907                  	sub cx, .message_4_length
  1508 00000129 7609                    	jbe @FF
  1509 0000012B 89CA                    	mov dx, cx
  1510 0000012D B023                    	mov al, '#'
  1511                                  @@:
  1512 0000012F E86600                  	call disp_al
  1513 00000132 E2FB                    	loop @B
  1514                                  @@:
  1515 00000134 59                      	pop cx
  1516 00000135 B020                    	mov al, 32
  1517 00000137 83EB29                  	sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length
  1518 0000013A 29D3                    	sub bx, dx
  1519 0000013C 7607                    	jbe @FF
  1520 0000013E 89D9                    	mov cx, bx
  1521                                  @@:
  1522 00000140 E85500                  	call disp_al
  1523 00000143 E2FB                    	loop @B
  1524                                  @@:
  1525 00000145 E97EFF                  	jmp .m4done
  1526                                  
  1527                                  .notyetm4:
  1528 00000148 B020                    	mov al, 32
  1529 0000014A 59                      	pop cx
  1530 0000014B 29CB                    	sub bx, cx
  1531 0000014D 7608                    	jbe @FF
  1532 0000014F 89D9                    	mov cx, bx
  1533                                  @@:
  1534 00000151 E84400                  	call disp_al
  1535 00000154 4A                      	dec dx
  1536 00000155 E0FA                    	loopnz @B
  1537                                  @@:
  1538                                  
  1539 00000157 BE[7F01]                	mov si, .message_4
  1540 0000015A 29FE                    	sub si, di
  1541 0000015C E82B00                  	call disp_error
  1542                                  
  1543 0000015F B020                    	mov al, 32
  1544 00000161 29F9                    	sub cx, di
  1545 00000163 83E907                  	sub cx, .message_4_length
  1546                                  	; jbe @FF
  1547                                  @@:
  1548 00000166 E82F00                  	call disp_al
  1549 00000169 E2FB                    	loop @B
  1550                                  @@:
  1551 0000016B E958FF                  	jmp .m4done
  1552                                  %endif
  1553                                  
  1554                                  	align 2, db 0
  1555                                   %if _PROGRESSMULTI
  1556 0000016E FFFF                    .display:	dw -1
  1557                                   %endif
  1558 00000170 0000                    .counter:	dw 0
  1559 00000172 0D5B20                  .message:	db 13,"[ "
  1560 00000175 2020312E30              .message_number:db "  1.0"	; enough digit slots for 100.0%,
  1561                                  				;  blanks are pre-init until written
  1562                                  .message_number_end:
  1563 0000017A 25205D00                		db "% ]",0
  1564                                   %if _PROGRESSMULTI
  1565 0000017E 20                      		db " "
  1566                                  .message_4:
  1567 0000017F 2020312E30              .message_4_number:db "  1.0"	; enough digit slots for 100.0%,
  1568                                  				;  blanks are pre-init until written
  1569                                  .message_4_number_end:
  1570 00000184 252000                  		db "% ",0
  1571                                  .message_4_length: equ $ - 1 - .message_4
  1572                                   %endif
  1573                                  %endif
  1574                                  
  1575                                  
  1576                                  %if _DEVICE
  1577                                  	align 16
  1578                                  device_header_copy:
  1579                                  .:
  1580                                  .next:
  1581                                  	dd -1				; already initialised
  1582                                  .attributes:
  1583                                  	dw _DEVICE_ATTRIBUTE
  1584                                  .strategy:
  1585                                  	dw .strategy_entry - .		; -> strategy entry
  1586                                  .interrupt:
  1587                                  	dw .interrupt_entry - .		; -> interrupt entry
  1588                                  .name:
  1589                                  	fill 8, 32, db _DEVICE_NAME
  1590                                  
  1591                                  .strategy_entry:
  1592                                  	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
  1593                                  .interrupt_entry:
  1594                                  	fill 4, 90h, retf
  1595                                  
  1596                                  .set_error:
  1597                                  	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1598                                  	retf
  1599                                  .length: equ $ - .
  1600                                  %endif
  1601                                  
  1602                                  
  1603                                  disp_error.loop:
  1604 00000187 E80E00                  	call disp_al
  1605                                  disp_error:
  1606 0000018A AC                      	lodsb
  1607 0000018B 84C0                    	test al, al
  1608 0000018D 75F8                    	jnz .loop
  1609 0000018F C3                      	retn
  1610                                  
  1611                                  %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3
  1612                                  disp_ax_hex:			; ax
  1613                                  		xchg al,ah
  1614                                  		call disp_al_hex		; display former ah
  1615                                  		xchg al,ah			;  and fall trough for al
  1616                                  disp_al_hex:			; al
  1617                                  		push cx
  1618                                  		mov cl,4
  1619                                  		ror al,cl
  1620                                  		call disp_al_lownibble_hex	; display former high-nibble
  1621                                  		rol al,cl
  1622                                  		pop cx
  1623                                  						;  and fall trough for low-nibble
  1624                                  disp_al_lownibble_hex:
  1625                                  		push ax			 ; save ax for call return
  1626                                  		and al,00001111b		; high nibble must be zero
  1627                                  		add al,'0'			; if number is 0-9, now it's the correct character
  1628                                  		cmp al,'9'
  1629                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  1630                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  1631                                   .decimalnum:
  1632                                  		call disp_al
  1633                                  		pop ax
  1634                                  		retn
  1635                                  %endif
  1636                                  
  1637                                  
  1638                                  disp_al_for_progress:
  1639                                  %if _PROGRESS && _PROGRESSMULTI
  1640 00000190 2E833E[4800]16          	cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base
  1641 00000196 740D                    	je disp_al.retn
  1642                                  %endif
  1643                                  disp_al:
  1644                                  %if _TEST_PROGRAM
  1645                                  	retn
  1646                                  %else
  1647 00000198 50                      	push ax
  1648                                  %endif
  1649                                  %if _BOOTLDR
  1650 00000199 53                      	push bx
  1651 0000019A 55                      	push bp
  1652 0000019B B40E                    	mov ah, 0Eh
  1653 0000019D BB0700                  	mov bx, 7
  1654                                  %endif
  1655                                  %if _IMAGE_EXE || _DEVICE
  1656                                  	push dx
  1657                                  
  1658                                  %if _BOOTLDR
  1659                                  	test byte [bp - 2], 1 | 2
  1660                                  	jz .display_kernel_mode
  1661                                  %endif
  1662                                  
  1663                                  	xchg dx, ax				; dl = input al
  1664                                  	mov ah, 02h
  1665                                  	int 21h
  1666                                  %if _BOOTLDR
  1667                                  	db __TEST_IMM16				; (skip int)
  1668                                  %endif
  1669                                  
  1670                                  .display_kernel_mode:
  1671                                  %endif
  1672                                  %if _BOOTLDR
  1673 000001A0 CD10                    	int 10h
  1674                                  %endif
  1675                                  %if _IMAGE_EXE
  1676                                  	pop dx
  1677                                  %endif
  1678                                  %if _BOOTLDR
  1679 000001A2 5D                      	pop bp
  1680 000001A3 5B                      	pop bx
  1681                                  %endif
  1682 000001A4 58                      	pop ax
  1683                                  .retn:
  1684                                  disp_error.ret:
  1685 000001A5 C3                      	retn
  1686                                  
  1687                                  
  1688                                  msg:
  1689                                  %if _DEBUG0
  1690                                  .error_begin:	db "Load error: Decompression failure, code ",0
  1691                                  .error_end:	db "h.",13,10,0
  1692                                  %else
  1693 000001A6 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
  1693 000001AF 723A204465636F6D70-
  1693 000001B8 72657373696F6E2066-
  1693 000001C1 61696C7572652E0D0A-
  1693 000001CA 00                 
  1694                                  %endif
  1695                                  
  1696                                  
  1697                                  %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1
  1698                                  %assign NEED_NORMALISE_BOTH_POINTERS 1
  1699                                  %assign CHECK_POINTERS_VARIABLE_SRC 1
  1700                                  %assign CHECK_POINTERS_VARIABLE_DST 1
  1701                                  
  1702                                  		; Specific depacker's file is included within label msg.
  1703                                  		; In the file, lframe is used and lleave ctx is not used.
  1704                                  
  1705                                  %if _BRIEFLZ
  1706                                  	%include "brieflz.asm"
  1707                                  %endif
  1708                                  
  1709                                  
  1710                                  %if _LZ4
  1711                                  	%include "lz4.asm"
  1712                                  %endif
  1713                                  
  1714                                  
  1715                                  %if _SNAPPY
  1716                                  	%include "snappy.asm"
  1717                                  %endif
  1718                                  
  1719                                  
  1720                                  %if _EXODECR
  1721                                  	%include "exodecr.asm"
  1722                                  %endif
  1723                                  
  1724                                  
  1725                                  %if _X
  1726                                  	%include "x.asm"
  1727                                  %endif
  1728                                  
  1729                                  
  1730                                  %if _HEATSHRINK
  1731                                  	%include "heatshr.asm"
  1732                                  %endif
  1733                                  
  1734                                  
  1735                                  %if _LZD
  1736                                  	%include "lzd.asm"
     1                              <1> 
     2                              <1> %if 0
     3                              <1> 
     4                              <1>     Lzd - Educational decompressor for the lzip format
     5                              <1>     Copyright (C) 2013-2019 Antonio Diaz Diaz.
     6                              <1> 
     7                              <1>     This program is free software. Redistribution and use in source and
     8                              <1>     binary forms, with or without modification, are permitted provided
     9                              <1>     that the following conditions are met:
    10                              <1> 
    11                              <1>     1. Redistributions of source code must retain the above copyright
    12                              <1>     notice, this list of conditions and the following disclaimer.
    13                              <1> 
    14                              <1>     2. Redistributions in binary form must reproduce the above copyright
    15                              <1>     notice, this list of conditions and the following disclaimer in the
    16                              <1>     documentation and/or other materials provided with the distribution.
    17                              <1> 
    18                              <1>     This program is distributed in the hope that it will be useful,
    19                              <1>     but WITHOUT ANY WARRANTY; without even the implied warranty of
    20                              <1>     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    21                              <1> 
    22                              <1> %endif
    23                              <1> 
    24                              <1> 
    25                              <1> 	numdef COUNTER,		0, 256
    26                              <1> %if (_COUNTER - 1) & _COUNTER
    27                              <1>  %error COUNTER must be a power of two
    28                              <1> %endif
    29                              <1> 
    30                              <1> 
    31                              <1> amount_states equ 12
    32                              <1> 
    33                              <1> 		numdef XLATBSEQ, 7
    34                              <1> 		numdef WARNXLATBSEQ, 0
    35                              <1> 
    36                              <1> 
    37                              <1> %if _XLATBSEQ != 7
    38                              <1> next_states.beforealign:
    39                              <1> 	align 2
    40                              <1> next_states:
    41                              <1> .:
    42                              <1> 	times 4 db 0
    43                              <1> 	db 1, 2, 3, 4, 5, 6, 4, 5
    44                              <1> .amount: equ $ - .
    45                              <1>  %if .amount != amount_states
    46                              <1>   %error Invalid next_states array content
    47                              <1>  %endif
    48                              <1>  %assign XLATBTABSIZE $ - .beforealign
    49                              <1> %else
    50                              <1>  %assign XLATBTABSIZE 0
    51                              <1> %endif
    52                              <1> 
    53                              <1> 
    54                              <1> State:
    55                              <1> 		; INP:	ds:bx -> localvariables
    56                              <1> 		;	byte [bx + state.st]
    57                              <1> 		; OUT:	CY if st < 7 (is_char() == true)
    58                              <1> 		;	NC if st >= 7 (is_char() == false)
    59                              <1> 		; CHG:	-
    60                              <1> .is_char:
    61 000001CB 807F2807            <1> 	cmp byte [bx + state.st], 7
    62 000001CF 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 000001D0 8A4728              <1> 	mov al, byte [bx + state.st]
   129 000001D3 2C03                <1> 	sub al, 3		; below 4 ?
   130 000001D5 7607                <1> 	jbe .zero		; yes -->
   131 000001D7 3C07                <1> 	cmp al, 10 - 3		; 10 or 11 initially ?
   132 000001D9 7202                <1> 	jb .have		; no -->
   133 000001DB 2C03                <1> 	sub al, 3		; convert
   134                              <1> .have:
   135 000001DD A9                  <1> 	db __TEST_IMM16		; (skip mov)
   136                              <1> .zero:
   137 000001DE 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 000001E0 884728              <1> 	mov byte [bx + state.st], al
   147 000001E3 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 000001E4 E8E4FF              <1> 	call .is_char
   158 000001E7 72F7                <1> 	jc .end
   159 000001E9 88E0                <1> 	mov al, ah
   160 000001EB 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 000001ED 1E                  <1> 	push ds
   231 000001EE 07                  <1> 	pop es
   232 000001EF B80600              <1> 	mov ax, 6
   233 000001F2 89DF                <1> 	mov di, bx		; -> .member_pos
   234 000001F4 AB                  <1> 	stosw			; low word of .member_pos
   235 000001F5 31C0                <1> 	xor ax, ax
   236 000001F7 AB                  <1> 	stosw			; high word of .member_pos
   237 000001F8 AB                  <1> 	stosw
   238 000001F9 AB                  <1> 	stosw			; .code
   239 000001FA 48                  <1> 	dec ax
   240 000001FB AB                  <1> 	stosw
   241 000001FC AB                  <1> 	stosw			; .range
   242 000001FD B90500              <1> 	mov cx, 5
   243                              <1> .loop:
   244 00000200 E81900              <1> 	call getbyteshiftcode
   245 00000203 E2FB                <1> 	loop .loop
   246 00000205 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 00000206 807F0B00            <1> 	cmp byte [bx + range_decoder.range + 3], 0
   255 0000020A 7521                <1> 	jnz @F			; (retn)
   256 0000020C 50                  <1> 	push ax
   257 0000020D 8B4709              <1> 	mov ax, word [bx + range_decoder.range + 1]
   258 00000210 89470A              <1> 	mov word [bx + range_decoder.range + 2], ax
   259 00000213 8A6708              <1> 	mov ah, byte [bx + range_decoder.range]
   260 00000216 B000                <1> 	mov al, 0
   261 00000218 894708              <1> 	mov word [bx + range_decoder.range], ax
   262 0000021B 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 0000021C 50                  <1> 	push ax
   272 0000021D 8B4705              <1> 	mov ax, word [bx + range_decoder.code + 1]
   273 00000220 894706              <1> 	mov word [bx + range_decoder.code + 2], ax
   274 00000223 8A6704              <1> 	mov ah, byte [bx + range_decoder.code]
   275 00000226 E8A206              <1> 	call Range_decoder.get_byte
   276 00000229 894704              <1> 	mov word [bx + range_decoder.code], ax
   277 0000022C 58                  <1> 	pop ax
   278                              <1> @@:
   279 0000022D 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 0000022E 31D2                <1> 	xor dx, dx
   291 00000230 31C0                <1> 	xor ax, ax
   292 00000232 E32C                <1> 	jcxz .end
   293                              <1> .loop:
   294 00000234 D16F0A              <1> 	shr word [bx + range_decoder.range + 2], 1
   295 00000237 D15F08              <1> 	rcr word [bx + range_decoder.range], 1
   296 0000023A D1E0                <1> 	shl ax, 1
   297 0000023C D1D2                <1> 	rcl dx, 1
   298 0000023E 8B7F06              <1> 	mov di, word [bx + range_decoder.code + 2]
   299 00000241 3B7F0A              <1> 	cmp di, word [bx + range_decoder.range + 2]
   300 00000244 7506                <1> 	jne @F
   301 00000246 8B7F04              <1> 	mov di, word [bx + range_decoder.code]
   302 00000249 3B7F08              <1> 	cmp di, word [bx + range_decoder.range]
   303                              <1> @@:				; code >= range ?
   304 0000024C 720D                <1> 	jnae @F			; no, skip -->
   305 0000024E 8B7F08              <1> 	mov di, word [bx + range_decoder.range]
   306 00000251 297F04              <1> 	sub word [bx + range_decoder.code], di
   307 00000254 8B7F0A              <1> 	mov di, word [bx + range_decoder.range + 2]
   308 00000257 197F06              <1> 	sbb word [bx + range_decoder.code + 2], di
   309 0000025A 40                  <1> 	inc ax			; symbol |= 1 (lowest bit always was zero)
   310                              <1> @@:
   311 0000025B E8A8FF              <1> 	call normaliserange
   312 0000025E E2D4                <1> 	loop .loop
   313                              <1> .end:
   314 00000260 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 00000261 8B570A              <1> 	mov dx, word [bx + range_decoder.range + 2]
   327 00000264 8B4708              <1> 	mov ax, word [bx + range_decoder.range]
   328 00000267 B90B00              <1> 	mov cx, bit_model_total_bits
   329                              <1> @@:
   330 0000026A D1EA                <1> 	shr dx, 1
   331 0000026C D1D8                <1> 	rcr ax, 1
   332 0000026E E2FA                <1> 	loop @B
   333                              <1> 
   334 00000270 89D1                <1> 	mov cx, dx
   335 00000272 26F725              <1> 	mul word [es:di + bit_model.probability]
   336                              <1> 				; dx:ax = low word + first high word
   337 00000275 52                  <1> 	 push dx
   338 00000276 50                  <1> 	 push ax		; on stack = low word + first high word
   339 00000277 91                  <1> 	xchg ax, cx
   340 00000278 26F725              <1> 	mul word [es:di + bit_model.probability]
   341                              <1> 				; ax = second high word (dx overflow)
   342 0000027B 91                  <1> 	xchg ax, cx		; cx
   343 0000027C 58                  <1> 	 pop ax
   344 0000027D 5A                  <1> 	 pop dx
   345 0000027E 01CA                <1> 	add dx, cx		; = full uint32_t result
   346 00000280 B90500              <1> 	mov cx, bit_model_move_bits
   347                              <1> 
   348 00000283 395706              <1> 	cmp word [bx + range_decoder.code + 2], dx
   349 00000286 7503                <1> 	jne @F
   350 00000288 394704              <1> 	cmp word [bx + range_decoder.code], ax
   351                              <1> @@:
   352 0000028B 7317                <1> 	jnb .not_code_below_bound
   353                              <1> 
   354                              <1> .code_below_bound:
   355 0000028D 894708              <1> 	mov word [bx + range_decoder.range], ax
   356 00000290 89570A              <1> 	mov word [bx + range_decoder.range + 2], dx
   357 00000293 B80008              <1> 	mov ax, bit_model_total
   358 00000296 262B05              <1> 	sub ax, word [es:di + bit_model.probability]
   359 00000299 7228                <1> 	jc .error
   360 0000029B D3E8                <1> 	shr ax, cl
   361 0000029D 260105              <1> 	add word [es:di + bit_model.probability], ax
   362 000002A0 B000                <1> 	mov al, 0
   363 000002A2 EB18                <1> 	jmp .after_if
   364                              <1> 
   365                              <1> .not_code_below_bound:
   366 000002A4 294708              <1> 	sub word [bx + range_decoder.range], ax
   367 000002A7 19570A              <1> 	sbb word [bx + range_decoder.range + 2], dx
   368 000002AA 294704              <1> 	sub word [bx + range_decoder.code], ax
   369 000002AD 195706              <1> 	sbb word [bx + range_decoder.code + 2], dx
   370                              <1> 
   371 000002B0 268B05              <1> 	mov ax, word [es:di + bit_model.probability]
   372 000002B3 D3E8                <1> 	shr ax, cl
   373 000002B5 262905              <1> 	sub word [es:di + bit_model.probability], ax
   374 000002B8 7209                <1> 	jc .error
   375 000002BA B001                <1> 	mov al, 1
   376                              <1> 
   377                              <1> .after_if:
   378 000002BC E847FF              <1> 	call normaliserange
   379 000002BF 3C01                <1> 	cmp al, 1		; CY if 0, NC if 1
   380 000002C1 F5                  <1> 	cmc			; NC if 0, CY if 1
   381 000002C2 C3                  <1> 	retn
   382                              <1> 
   383                              <1> .error:
   384 000002C3 E9F405              <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 000002C6 BE0100              <1> 	mov si, 1		; symbol = 1
   397 000002C9 83F90F              <1> 	cmp cx, 15
   398 000002CC 7721                <1> 	ja .error
   399 000002CE 51                  <1> 	push cx
   400 000002CF E312                <1> 	jcxz .end
   401                              <1> .loop:
   402 000002D1 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 000002D2 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 000002D4 01F7                <1> 	add di, si		; index into bit_model array
   411 000002D6 7217                <1> 	jc .error_pop_2
   412 000002D8 51                  <1> 	push cx
   413 000002D9 E885FF              <1> 	call Range_decoder.decode_bit
   414 000002DC 59                  <1> 	pop cx
   415 000002DD 83D600              <1> 	adc si, 0		; add in the decoded bit
   416 000002E0 5F                  <1> 	pop di
   417 000002E1 E2EE                <1> 	loop .loop
   418                              <1> .end:
   419 000002E3 59                  <1> 	pop cx
   420 000002E4 B80100              <1> 	mov ax, 1
   421 000002E7 D3E0                <1> 	shl ax, cl		; = 1 << num_bits
   422 000002E9 29C6                <1> 	sub si, ax		; symbol - ( 1 << num_bits )
   423 000002EB 96                  <1> 	xchg ax, si
   424 000002EC 31D2                <1> 	xor dx, dx		; return symbol
   425 000002EE C3                  <1> 	retn
   426                              <1> 
   427                              <1> .error_pop_2:
   428                              <1> .error:
   429 000002EF E9C805              <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 000002F2 51                  <1> 	push cx
   442 000002F3 E8D0FF              <1> 	call Range_decoder.decode_tree
   443 000002F6 59                  <1> 	pop cx
   444 000002F7 92                  <1> 	xchg dx, ax		; dx = symbol
   445 000002F8 31C0                <1> 	xor ax, ax		; = reversed_symbol
   446 000002FA E306                <1> 	jcxz .end
   447                              <1> .loop:
   448 000002FC D1EA                <1> 	shr dx, 1
   449 000002FE D1D0                <1> 	rcl ax, 1
   450 00000300 E2FA                <1> 	loop .loop
   451                              <1> .end:
   452 00000302 31D2                <1> 	xor dx, dx
   453 00000304 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 00000305 88C6                <1> 	mov dh, al		; = match_byte
   466                              <1> 
   467 00000307 B80100              <1> 	mov ax, 1		; initialise symbol = 1
   468                              <1> 
   469 0000030A B90800              <1> 	mov cx, 8
   470                              <1> .loop:
   471 0000030D 52                  <1> 	push dx			; preserve dh = match_byte
   472 0000030E 51                  <1> 	push cx			; preserve loop counter
   473 0000030F 49                  <1> 	dec cx
   474 00000310 D2EE                <1> 	shr dh, cl		; match_byte >> i
   475 00000312 81E20001            <1> 	and dx, 100h		; dh &= 1 = match_bit, dl = 0
   476 00000316 52                  <1> 	push dx
   477 00000317 FEC6                <1> 	inc dh			; = (match_bit << 8) + 100h
   478 00000319 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 0000031B 57                  <1> 	push di
   483 0000031C 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 0000031D 01D2                <1> 	add dx, dx
   488                              <1> 		; As dx was < 300h before this addition, it cannot carry.
   489 0000031F 01D7                <1> 	add di, dx
   490                              <1> 		; We assume that this does not carry.
   491 00000321 E83DFF              <1> 	call Range_decoder.decode_bit
   492 00000324 91                  <1> 	xchg ax, cx		; cl = result (1 or 0)
   493 00000325 58                  <1> 	pop ax			; = symbol
   494 00000326 5F                  <1> 	pop di
   495 00000327 5A                  <1> 	pop dx			; = match_bit << 8
   496 00000328 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 0000032A 38F1                <1> 	cmp cl, dh		; if( match_bit != bit ) ...-
   500 0000032C 59                  <1> 	pop cx			; = loop counter
   501 0000032D 5A                  <1> 	pop dx			; = dh = match_byte
   502 0000032E 7519                <1> 	jne .inner_next		; -... do the following -->
   503                              <1> .next:
   504 00000330 E2DB                <1> 	loop .loop
   505                              <1> .end:
   506 00000332 30E4                <1> 	xor ah, ah		; return ax = symbol & 0FFh
   507 00000334 C3                  <1> 	retn
   508                              <1> 
   509                              <1> .error_pop_2:
   510                              <1> .error:
   511 00000335 E98205              <1> 	jmp depack.error
   512                              <1> 
   513                              <1> 
   514                              <1> .inner_loop:
   515 00000338 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 00000339 01C0                <1> 	add ax, ax
   520 0000033B 57                  <1> 	push di
   521 0000033C 01C7                <1> 	add di, ax
   522 0000033E 72F5                <1> 	jc .error_pop_2
   523 00000340 E81EFF              <1> 	call Range_decoder.decode_bit
   524 00000343 5F                  <1> 	pop di
   525 00000344 58                  <1> 	pop ax
   526 00000345 D1D0                <1> 	rcl ax, 1
   527 00000347 72EC                <1> 	jc .error
   528                              <1> 
   529                              <1> .inner_next:
   530 00000349 3D0001              <1> 	cmp ax, 100h
   531 0000034C 72EA                <1> 	jb .inner_loop
   532 0000034E 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 00000350 89C6                <1> 	mov si, ax		; = pos_state
   545 00000352 57                  <1> 	 push di		; = len_model_struc (on stack)
   546                              <1> 
   547 00000353 8D3D                <1> 	lea di, [di + len_model.choice1]
   548 00000355 E809FF              <1> 	call Range_decoder.decode_bit
   549 00000358 5F                  <1> 	 pop di			; reset to ?len_model_struc
   550 00000359 57                  <1> 	 push di
   551 0000035A 7218                <1> 	jc .not_decode_bit_choice1_equals_zero
   552                              <1> 
   553 0000035C 8D7D04              <1> 	lea di, [di + len_model.bm_low]
   554 0000035F B81000              <1> 	mov ax, len_low_symbols * bit_model_size
   555 00000362 F7E6                <1> 	mul si
   556 00000364 85D2                <1> 	test dx, dx
   557 00000366 7546                <1> 	jnz .error
   558 00000368 01C7                <1> 	add di, ax
   559 0000036A 7242                <1> 	jc .error
   560 0000036C B90300              <1> 	mov cx, len_low_bits
   561 0000036F E854FF              <1> 	call Range_decoder.decode_tree
   562 00000372 EB38                <1> 	jmp .ret
   563                              <1> 
   564                              <1> .not_decode_bit_choice1_equals_zero:
   565 00000374 8D7D02              <1> 	lea di, [di + len_model.choice2]
   566 00000377 E8E7FE              <1> 	call Range_decoder.decode_bit
   567 0000037A 5F                  <1> 	 pop di			; reset to ?len_model_struc
   568 0000037B 57                  <1> 	 push di
   569 0000037C 721E                <1> 	jc .not_decode_bit_choice2_equals_zero
   570                              <1> 
   571 0000037E 8D7D44              <1> 	lea di, [di + len_model.bm_mid]
   572 00000381 B81000              <1> 	mov ax, len_mid_symbols * bit_model_size
   573 00000384 F7E6                <1> 	mul si
   574 00000386 85D2                <1> 	test dx, dx
   575 00000388 7524                <1> 	jnz .error
   576 0000038A 01C7                <1> 	add di, ax
   577 0000038C 7220                <1> 	jc .error
   578 0000038E B90300              <1> 	mov cx, len_mid_bits
   579 00000391 E832FF              <1> 	call Range_decoder.decode_tree
   580 00000394 83C008              <1> 	add ax, len_low_symbols & 0FFFFh
   581 00000397 83D200              <1> 	adc dx, len_low_symbols >> 16
   582 0000039A EB10                <1> 	jmp .ret
   583                              <1> 
   584                              <1> .not_decode_bit_choice2_equals_zero:
   585 0000039C 8DBD8400            <1> 	lea di, [di + len_model.bm_high]
   586 000003A0 B90800              <1> 	mov cx, len_high_bits
   587 000003A3 E820FF              <1> 	call Range_decoder.decode_tree
   588 000003A6 83C010              <1> 	add ax, (len_low_symbols + len_mid_symbols) & 0FFFFh
   589 000003A9 83D200              <1> 	adc dx, (len_low_symbols + len_mid_symbols) >> 16
   590                              <1> .ret:
   591 000003AC 5F                  <1> 	 pop di
   592 000003AD C3                  <1> 	retn
   593                              <1> 
   594                              <1> .error:
   595 000003AE E90905              <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 000003B1 395716              <1> 	cmp word [bx + lz_decoder.pos + 2], dx
   612 000003B4 7503                <1> 	jne @F
   613 000003B6 394714              <1> 	cmp word [bx + lz_decoder.pos], ax
   614                              <1> @@:
   615 000003B9 760A                <1> 	jna .not_pos_above_distance
   616                              <1> 
   617 000003BB E80A00              <1> 	call calculate_peek_pointer_disi
   618                              <1> 
   619 000003BE 8EC7                <1> 	mov es, di			; es:si -> peek address
   620 000003C0 31C0                <1> 	xor ax, ax
   621 000003C2 26AC                <1> 	es lodsb
   622 000003C4 C3                  <1> 	retn
   623                              <1> 
   624                              <1> .not_pos_above_distance:
   625 000003C5 31C0                <1> 	xor ax, ax
   626 000003C7 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 000003C8 53                  <1> 	push bx
   635 000003C9 FF772E              <1> 	 push word [bx + destinationbuffer_constant + 2]
   636 000003CC FF772C              <1> 	 push word [bx + destinationbuffer_constant]
   637                              <1> 
   638 000003CF F7DA                <1> 	neg dx
   639 000003D1 F7D8                <1> 	neg ax
   640 000003D3 83DA00              <1> 	sbb dx, byte 0			; neg dx:ax = - distance
   641 000003D6 83E801              <1> 	sub ax, 1
   642 000003D9 83DA00              <1> 	sbb dx, 0			; - 1
   643 000003DC 034714              <1> 	add ax, word [bx + lz_decoder.pos]
   644 000003DF 135716              <1> 	adc dx, word [bx + lz_decoder.pos + 2]
   645                              <1> 					; + pos
   646 000003E2 91                  <1> 	xchg cx, ax
   647 000003E3 87DA                <1> 	xchg bx, dx
   648                              <1> 
   649 000003E5 E88A06              <1> 	call normalise_pointer_with_displacement_bxcx
   650 000003E8 5E                  <1> 	 pop si
   651 000003E9 5F                  <1> 	 pop di				; di:si -> source
   652 000003EA 5B                  <1> 	pop bx
   653 000003EB 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 000003EC 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 000003F1 5589E5              <1> 	lenter early
   733                              <1>  %if _IMAGE_EXE
   734                              <1> 	lvar word,	exemode	; must be bp - 2!
   735                              <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 000003F4 31DB                <1> 	xor bx, bx
   742                              <1>  %endif
   743                              <1> %endif
   744                              <1> %if _COUNTER
   745                              <1> 	lvar word,	counter
   746 000003F6 53                  <1> 	 push bx		; initialise counter to zero
   747                              <1> %endif
   748                              <1> d0	lvar word,	errordata
   749                              <1> d0	 push bx
   750                              <1> 	lvar dword,	distance
   751                              <1> 	lvar dword,	len
   752                              <1> 	lvar dword,	dis_slot
   753                              <1> 	lvar word,	len_state
   754                              <1> 	lvar word,	pos_state
   755 000003F7 8D66EE              <1> 	lenter
   756                              <1> 
   757 000003FA E84406              <1> 	call normalise_both_pointers
   758                              <1> 
   759                              <1> 		; ! di < 16, so dih == 0
   760                              <1> 	lvar dword,	src
   761 000003FD 1E                  <1> 	 push ds
   762 000003FE 56                  <1> 	 push si
   763                              <1> 	lvar dword,	final_dst
   764 000003FF 06                  <1> 	 push es
   765 00000400 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 00000401 52                  <1> 	 push dx
   771 00000402 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 00000403 1E                  <1> 	 push ds
   792 00000404 56                  <1> 	 push si
   793 00000405 E89906              <1> 	call pointer_to_linear
   794                              <1> 
   795 00000408 87DA                <1> 	xchg bx, dx
   796 0000040A 91                  <1> 	xchg cx, ax		; bx:cx = source linear, clobber dx:ax
   797                              <1> 
   798 0000040B 06                  <1> 	 push es
   799 0000040C 57                  <1> 	 push di
   800 0000040D E89106              <1> 	call pointer_to_linear
   801                              <1> 
   802                              <1> %if _ALLOW_OVERLAPPING
   803 00000410 034EE2              <1> 	add cx, word [bp + ?length_of_source]
   804 00000413 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 00000416 29C1                <1> 	sub cx, ax
   819 00000418 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   820                              <1> 
   821 0000041A 81E96039            <1> 	sub cx, localvariables_size & 0FFFFh
   822 0000041E 83DB00              <1> 	sbb bx, localvariables_size >> 16
   823 00000421 7703E99404          <1> 	jbe .error		; make variables buffer available
   824                              <1> 
   825                              <1> 	lvar dword,	length_of_destination
   826 00000426 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   827 00000427 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   828                              <1> 
   829 00000428 06                  <1> 	push es
   830 00000429 57                  <1> 	push di
   831                              <1> %if localvariables_size >> 16
   832                              <1> 	mov bx, localvariables_size >> 16
   833                              <1> %else
   834 0000042A 31DB                <1> 	xor bx, bx
   835                              <1> %endif
   836 0000042C B96039              <1> 	mov cx, localvariables_size & 0FFFFh
   837 0000042F E84006              <1> 	call normalise_pointer_with_displacement_bxcx
   838 00000432 5F                  <1> 	pop di
   839 00000433 07                  <1> 	pop es
   840                              <1> 
   841                              <1> 	lvar dword,	original_dst
   842 00000434 06                  <1> 	 push es
   843 00000435 57                  <1> 	 push di
   844                              <1> 	lvar dword,	dst
   845 00000436 06                  <1> 	 push es
   846 00000437 57                  <1> 	 push di
   847                              <1> 
   848                              <1> %if _ALLOW_OVERLAPPING
   849 00000438 E8EA05              <1> 	call check_pointers_not_overlapping
   850                              <1> 		; Note:	We initially check here that the write pointer is
   851                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   852                              <1> 		;	Unlike the other decompressors, this check is done
   853                              <1> 		;	 after any copied match or literal too, because
   854                              <1> 		;	 literals can presumably be encoded with less than
   855                              <1> 		;	 one byte of source data to the range decoder.
   856                              <1> d0	mov byte [bp + ?errordata], 1Bh
   857                              <1> .error_CY_a1:
   858 0000043B 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 0000043D 837EE400            <1> 	cmp word [bp + ?length_of_source + 2], 0
   868 00000441 7504                <1> 	jne @F
   869 00000443 837EE21A            <1> 	cmp word [bp + ?length_of_source], member_min_size
   870                              <1> @@:
   871 00000447 770F                <1> 	ja .got_member
   872                              <1> 
   873 00000449 837EE400            <1> 	cmp word [bp + ?length_of_source + 2], 0
   874 0000044D 7504                <1> 	jne @F
   875 0000044F 837EE20F            <1> 	cmp word [bp + ?length_of_source], 15
   876                              <1> @@:
   877 00000453 7710                <1> 	ja short .error_NZ_a		; (NZ if jumping)
   878 00000455 E92E04              <1> 	jmp .end
   879                              <1> 
   880                              <1> .got_member:
   881 00000458 C576EA              <1> 	lds si, [bp + ?src]		; ds:si -> lzip_header.magic, .version
   882 0000045B 0E                  <1> 	push cs
   883 0000045C 07                  <1> 	pop es
   884 0000045D BF[EC03]            <1> 	mov di, lzip_header_bytes
   885 00000460 B90500              <1> 	mov cx, lzip_header_bytes.length
   886 00000463 F3A6                <1> 	repe cmpsb
   887                              <1> .error_NZ_a:
   888 00000465 7403E95004          <1> 	jne .error
   889                              <1> %if _COUNTER && !_PROGRESS
   890                              <1> 	mov al, '#'
   891                              <1> 	call disp_al
   892                              <1> %endif
   893 0000046A 31C0                <1> 	xor ax, ax
   894 0000046C AC                  <1> 	lodsb				; ax = lzip_header.coded_dict_size
   895                              <1> 
   896 0000046D 1E                  <1> 	 push ds
   897 0000046E 56                  <1> 	 push si
   898 0000046F E8DE05              <1> 	call normalise_pointer
   899 00000472 8F46EA              <1> 	 pop word [bp + ?src]
   900 00000475 8F46EC              <1> 	 pop word [bp + ?src + 2]
   901 00000478 836EE206            <1> 	sub word [bp + ?length_of_source], 6
   902 0000047C 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
   903                              <1> .error_CY_a:
   904 00000480 7235                <1> 	jc short .error_CY_b
   905                              <1> 
   906 00000482 50                  <1> 	push ax
   907 00000483 241F                <1> 	and al, 1Fh
   908 00000485 91                  <1> 	xchg cx, ax			; cx = coded dict size & 1Fh, clobber ax
   909 00000486 B80100              <1> 	mov ax, 1
   910 00000489 31D2                <1> 	xor dx, dx
   911                              <1> @@:
   912 0000048B D1E0                <1> 	shl ax, 1
   913 0000048D D1D2                <1> 	rcl dx, 1
   914 0000048F E2FA                <1> 	loop @B
   915                              <1> 
   916 00000491 89D3                <1> 	mov bx, dx
   917 00000493 89C7                <1> 	mov di, ax			; bx:di = dict_size
   918 00000495 B104                <1> 	mov cl, 4
   919                              <1> @@:
   920 00000497 D1EB                <1> 	shr bx, 1
   921 00000499 D1DF                <1> 	rcr di, 1
   922 0000049B E2FA                <1> 	loop @B				; bx:di = dict_size / 16
   923 0000049D 59                  <1> 	pop cx
   924 0000049E 88CD                <1> 	mov ch, cl
   925 000004A0 B105                <1> 	mov cl, 5
   926 000004A2 D2ED                <1> 	shr ch, cl
   927 000004A4 88E9                <1> 	mov cl, ch
   928 000004A6 B500                <1> 	mov ch, 0
   929 000004A8 E331                <1> 	jcxz @FF
   930                              <1> 
   931 000004AA 52                  <1> 	push dx
   932 000004AB 50                  <1> 	push ax
   933                              <1> 
   934 000004AC 89F8                <1> 	mov ax, di			; ax = low word of input
   935 000004AE F7E1                <1> 	mul cx
   936 000004B0 93                  <1> 	xchg ax, bx			; ax = high word of input
   937 000004B1 89D7                <1> 	mov di, dx			; di:bx = low word + first high word
   938 000004B3 F7E1                <1> 	mul cx				; = high word
   939 000004B5 01C7                <1> 	add di, ax			; add into sum
   940                              <1> .error_CY_b:
   941 000004B7 7217                <1> 	jc short .error_CY_c
   942 000004B9 85D2                <1> 	test dx, dx			; overflows ?
   943 000004BB 7403E9FA03          <1> 	jnz .error
   944                              <1> 					; bx:di = dict_size / 16 * fraction
   945 000004C0 58                  <1> 	pop ax
   946 000004C1 5A                  <1> 	pop dx
   947 000004C2 29D8                <1> 	sub ax, bx
   948 000004C4 19FA                <1> 	sbb dx, di
   949 000004C6 7208                <1> 	jc short .error_CY_c
   950                              <1> 
   951 000004C8 83FA00              <1> 	cmp dx, min_dictionary_size >> 16
   952 000004CB 7503                <1> 	jne @F
   953 000004CD 3D0010              <1> 	cmp ax, min_dictionary_size & 0FFFFh
   954                              <1> @@:
   955                              <1> .error_CY_c:
   956 000004D0 7273                <1> 	jb short .error_CY_d
   957                              <1> 
   958 000004D2 81FA0020            <1> 	cmp dx, max_dictionary_size >> 16
   959 000004D6 7503                <1> 	jne @F
   960 000004D8 83F800              <1> 	cmp ax, max_dictionary_size & 0FFFFh
   961                              <1> @@:
   962 000004DB 7603E9DA03          <1> 	ja .error
   963                              <1> 
   964 000004E0 C55EE6              <1> 	lds bx, [bp + ?final_dst]
   965 000004E3 FF76D8              <1> 	push word [bp + ?dst + 2]
   966 000004E6 FF76D6              <1> 	push word [bp + ?dst]
   967 000004E9 8F472C              <1> 	pop word [bx + destinationbuffer_constant]
   968 000004EC 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 000004EF 52                  <1> 	 push dx
   986 000004F0 50                  <1> 	 push ax			; preserve dictionary size
   987 000004F1 1E                  <1> 	push ds
   988 000004F2 07                  <1> 	pop es
   989 000004F3 89DF                <1> 	mov di, bx
   990 000004F5 B90C00              <1> 	mov cx, fromdwords(dwords(lz_decoder_size)) / 2
   991 000004F8 31C0                <1> 	xor ax, ax
   992 000004FA F3AB                <1> 	rep stosw			; initialise lz_decoder structure
   993                              <1> 
   994 000004FC E8EEFC              <1> 	call Range_decoder.init		; initialise embedded range_decoder
   995                              <1> 
   996 000004FF 8F4710              <1> 	 pop word [bx + lz_decoder.dictionary_size]
   997 00000502 8F4712              <1> 	 pop word [bx + lz_decoder.dictionary_size + 2]
   998                              <1> 					; set dictionary size
   999                              <1> 
  1000 00000505 8D7F30              <1> 	lea di, [bx + bit_models_start]
  1001 00000508 B9971C              <1> 	mov cx, (bit_models_end - bit_models_start) / bit_model_size
  1002 0000050B 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 0000050E F3AB                <1> 	rep stosw			; initialise this bit_model
  1007                              <1> 					; loop for all bit_model and len_model
  1008                              <1> 
  1009 00000510 8D7F18              <1> 	lea di, [bx + zeros_start]
  1010 00000513 31C0                <1> 	xor ax, ax
  1011 00000515 B10A                <1> 	mov cl, (zeros_end - zeros_start) / 2
  1012 00000517 F3AB                <1> 	rep stosw
  1013                              <1> 
  1014                              <1> .loop:
  1015                              <1> %if _COUNTER
  1016 00000519 FE46FE              <1> 	inc byte [bp + ?counter]
  1017 0000051C F646FEFF            <1> 	test byte [bp + ?counter], _COUNTER - 1
  1018 00000520 7505                <1> 	jnz @F
  1019 00000522 B02E                <1> 	mov al, '.'
  1020 00000524 E80EFB              <1> 	call disp_al_counter
  1021                              <1> @@:
  1022                              <1> %endif
  1023 00000527 8B5EE6              <1> 	mov bx, word [bp + ?localvariables]
  1024 0000052A 8B4714              <1> 	mov ax, word [bx + lz_decoder.pos]
  1025 0000052D 83E003              <1> 	and ax, pos_state_mask
  1026 00000530 91                  <1> 	xchg cx, ax			; cx = pos_state, ax clobbered
  1027 00000531 894EEE              <1> 	mov word [bp + ?pos_state], cx
  1028                              <1> 
  1029 00000534 1E                  <1> 	push ds
  1030 00000535 07                  <1> 	pop es
  1031 00000536 8D7F30              <1> 	lea di, [bx + bm_match]		; es:di -> bm_match 2D array
  1032 00000539 B80800              <1> 	mov ax, bit_model_size * pos_states
  1033 0000053C 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 0000053F 01C9                <1> 	add cx, cx			; = second index (from pos_state)
  1042                              <1> 		; pos_state < 4
  1043                              <1> 		; cx < 8
  1044                              <1> 		; ax <= 88
  1045 00000541 01C8                <1> 	add ax, cx			; = second index is pos_state
  1046 00000543 01C7                <1> 	add di, ax			; es:di -> bm_match[state()][pos_state]
  1047                              <1> .error_CY_d:
  1048 00000545 7222                <1> 	jc short .error_CY_1
  1049 00000547 E817FD              <1> 	call Range_decoder.decode_bit
  1050 0000054A 7244                <1> 	jc .1st_bit_not_zero
  1051                              <1> 
  1052                              <1> .1st_bit_zero:			; literal byte
  1053 0000054C 31C0                <1> 	xor ax, ax
  1054 0000054E 31D2                <1> 	xor dx, dx
  1055 00000550 E85EFE              <1> 	call LZ_decoder.peek		; al = prev_byte
  1056                              <1> 
  1057 00000553 B105                <1> 	mov cl, 8 - literal_context_bits
  1058 00000555 D2E8                <1> 	shr al, cl			; = literal_state
  1059 00000557 1E                  <1> 	push ds
  1060 00000558 07                  <1> 	pop es
  1061 00000559 8DBFF000            <1> 	lea di, [bx + bm_literal]	; -> 2D array bm_literal
  1062 0000055D B90006              <1> 	mov cx, bit_model_size * 300h
  1063 00000560 F7E1                <1> 	mul cx				; first index is literal_state
  1064 00000562 85D2                <1> 	test dx, dx
  1065 00000564 F9                  <1> 	stc
  1066 00000565 7502                <1> 	jnz short .error_CY_1
  1067 00000567 01C7                <1> 	add di, ax			; es:di -> bm_literal[literal_state]
  1068                              <1> .error_CY_1:
  1069 00000569 7232                <1> 	jc short .error_CY_2
  1070                              <1> 
  1071 0000056B E85DFC              <1> 	call State.is_char
  1072 0000056E 7308                <1> 	jnc .not_is_char
  1073                              <1> .is_char:
  1074 00000570 B90800              <1> 	mov cx, 8
  1075 00000573 E850FD              <1> 	call Range_decoder.decode_tree
  1076 00000576 EB10                <1> 	jmp @F
  1077                              <1> 
  1078                              <1> .not_is_char:
  1079 00000578 8B4718              <1> 	mov ax, word [bx + rep0]
  1080 0000057B 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1081 0000057E 06                  <1> 	push es
  1082 0000057F 57                  <1> 	push di
  1083 00000580 E82EFE              <1> 	call LZ_decoder.peek
  1084 00000583 5F                  <1> 	pop di
  1085 00000584 07                  <1> 	pop es
  1086 00000585 E87DFD              <1> 	call Range_decoder.decode_matched
  1087                              <1> @@:
  1088 00000588 E86703              <1> 	call LZ_decoder.put_byte
  1089 0000058B E842FC              <1> 	call State.set_char
  1090 0000058E EB89                <1> 	jmp .loop
  1091                              <1> 
  1092                              <1> 
  1093                              <1> .1st_bit_not_zero:		; match or repeated match
  1094 00000590 1E                  <1> 	push ds
  1095 00000591 07                  <1> 	pop es
  1096 00000592 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 00000596 8B4728              <1> 	mov ax, word [bx + state.st]
  1101 00000599 01C0                <1> 	add ax, ax			; ax = index is state
  1102                              <1> 	; jc short .error_CY_2	; (state.st is always < 12)
  1103 0000059B 01C7                <1> 	add di, ax			; es:di -> bm_rep[state()]
  1104                              <1> .error_CY_2:
  1105 0000059D 7230                <1> 	jc short .error_CY_3
  1106 0000059F E8BFFC              <1> 	call Range_decoder.decode_bit
  1107 000005A2 7203E9EA00          <1> 	jnc .2nd_bit_zero
  1108                              <1> 
  1109                              <1> .2nd_bit_not_zero:
  1110 000005A7 1E                  <1> 	push ds
  1111 000005A8 07                  <1> 	pop es
  1112 000005A9 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 000005AD 8B4728              <1> 	mov ax, word [bx + state.st]
  1117 000005B0 01C0                <1> 	add ax, ax			; ax = index is state
  1118                              <1> 	; jc short .error_CY_3	; (state.st is always < 12)
  1119 000005B2 01C7                <1> 	add di, ax			; es:di -> bm_rep0[state()]
  1120 000005B4 7219                <1> 	jc short .error_CY_3
  1121 000005B6 E8A8FC              <1> 	call Range_decoder.decode_bit
  1122 000005B9 7233                <1> 	jc .3rd_bit_not_zero
  1123                              <1> 
  1124                              <1> .3rd_bit_zero:
  1125 000005BB 1E                  <1> 	push ds
  1126 000005BC 07                  <1> 	pop es
  1127 000005BD 8DBFF030            <1> 	lea di, [bx + bm_len]		; es:di -> bm_len 2D array
  1128 000005C1 B80800              <1> 	mov ax, bit_model_size * pos_states
  1129                              <1> 				; (2 * 4 = 8)
  1130 000005C4 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 000005C7 0346EE              <2>  add ax, word [bp + ?pos_state]
  1140                              <2> 
  1141                              <2> 
  1142                              <2> 
  1139 000005CA 0346EE              <2>  add ax, word [bp + ?pos_state]
  1140                              <2> 
  1141                              <2> 
  1142                              <2> 
  1144 000005CD 01C7                <1> 	add di, ax			; es:di -> bm_len[state()]
  1145                              <1> .error_CY_3:
  1146 000005CF 722A                <1> 	jc short .error_CY_4
  1147 000005D1 E88DFC              <1> 	call Range_decoder.decode_bit
  1148 000005D4 7303E99500          <1> 	jc .4th_bit_not_zero
  1149                              <1> 
  1150                              <1> .4th_bit_zero:
  1151                              <1> ; State.set_short_rep
  1152 000005D9 B8090B              <1> 	mov ax, 9 | (11 << 8)
  1153 000005DC E805FC              <1> 	call State.select
  1154                              <1> 
  1155 000005DF 8B4718              <1> 	mov ax, word [bx + rep0]
  1156 000005E2 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1157 000005E5 E8C9FD              <1> 	call LZ_decoder.peek
  1158 000005E8 E80703              <1> 	call LZ_decoder.put_byte
  1159 000005EB E92BFF              <1> 	jmp .loop
  1160                              <1> 
  1161                              <1> .3rd_bit_not_zero:
  1162 000005EE 1E                  <1> 	push ds
  1163 000005EF 07                  <1> 	pop es
  1164 000005F0 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 000005F4 8B4728              <1> 	mov ax, word [bx + state.st]
  1169 000005F7 01C0                <1> 	add ax, ax			; ax = index is state
  1170                              <1> 	; jc short .error_CY_4	; (state.st is always < 12)
  1171 000005F9 01C7                <1> 	add di, ax			; es:di -> bm_rep1[state()]
  1172                              <1> .error_CY_4:
  1173 000005FB 7220                <1> 	jc short .error_CY_4a
  1174 000005FD E861FC              <1> 	call Range_decoder.decode_bit
  1175 00000600 720E                <1> 	jc .3rd_bit_not_zero.4th_bit_not_zero
  1176                              <1> 
  1177                              <1> .3rd_bit_not_zero.4th_bit_zero:
  1178 00000602 FF771E              <1> 	push word [bx + rep1 + 2]
  1179 00000605 FF771C              <1> 	push word [bx + rep1]
  1180 00000608 8F46FA              <1> 	pop word [bp + ?distance]
  1181 0000060B 8F46FC              <1> 	pop word [bp + ?distance + 2]
  1182 0000060E EB46                <1> 	jmp .3rd_bit_not_zero.common
  1183                              <1> 
  1184                              <1> .3rd_bit_not_zero.4th_bit_not_zero:
  1185 00000610 1E                  <1> 	push ds
  1186 00000611 07                  <1> 	pop es
  1187 00000612 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 00000616 8B4728              <1> 	mov ax, word [bx + state.st]
  1192 00000619 01C0                <1> 	add ax, ax			; ax = index is state
  1193                              <1> 	; jc short .error_CY_5	; (state.st is always < 12)
  1194 0000061B 01C7                <1> 	add di, ax			; es:di -> bm_rep2[state()]
  1195                              <1> .error_CY_4a:
  1196 0000061D 7267                <1> 	jc short .error_CY_5
  1197 0000061F E83FFC              <1> 	call Range_decoder.decode_bit
  1198 00000622 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 00000624 FF7722              <1> 	push word [bx + rep2 + 2]
  1202 00000627 FF7720              <1> 	push word [bx + rep2]
  1203 0000062A 8F46FA              <1> 	pop word [bp + ?distance]
  1204 0000062D 8F46FC              <1> 	pop word [bp + ?distance + 2]
  1205 00000630 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 00000632 FF7726              <1> 	push word [bx + rep3 + 2]
  1209 00000635 FF7724              <1> 	push word [bx + rep3]
  1210 00000638 8F46FA              <1> 	pop word [bp + ?distance]
  1211 0000063B 8F46FC              <1> 	pop word [bp + ?distance + 2]	; distance = rep3
  1212 0000063E FF7722              <1> 	push word [bx + rep2 + 2]
  1213 00000641 FF7720              <1> 	push word [bx + rep2]
  1214 00000644 8F4724              <1> 	pop word [bx + rep3]
  1215 00000647 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  1216                              <1> 
  1217                              <1> .3rd_bit_not_zero.4th_bit_not_zero.common:
  1218 0000064A FF771E              <1> 	push word [bx + rep1 + 2]
  1219 0000064D FF771C              <1> 	push word [bx + rep1]
  1220 00000650 8F4720              <1> 	pop word [bx + rep2]
  1221 00000653 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  1222                              <1> 
  1223                              <1> .3rd_bit_not_zero.common:
  1224 00000656 FF771A              <1> 	push word [bx + rep0 + 2]
  1225 00000659 FF7718              <1> 	push word [bx + rep0]
  1226 0000065C 8F471C              <1> 	pop word [bx + rep1]
  1227 0000065F 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  1228 00000662 FF76FC              <1> 	push word [bp + ?distance + 2]
  1229 00000665 FF76FA              <1> 	push word [bp + ?distance]
  1230 00000668 8F4718              <1> 	pop word [bx + rep0]
  1231 0000066B 8F471A              <1> 	pop word [bx + rep0 + 2]	; rep0 = distance
  1232                              <1> 
  1233                              <1> .4th_bit_not_zero:
  1234                              <1> ; State.set_rep
  1235 0000066E B8080B              <1> 	mov ax, 8 | (11 << 8)
  1236 00000671 E870FB              <1> 	call State.select
  1237                              <1> 
  1238 00000674 8B46EE              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  1239 00000677 1E                  <1> 	push ds
  1240 00000678 07                  <1> 	pop es
  1241 00000679 8DBFDA36            <1> 	lea di, [bx + rep_len_model]	; -> len_model to use
  1242 0000067D E8D0FC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  1243 00000680 83C002              <1> 	add ax, min_match_len
  1244 00000683 83D200              <1> 	adc dx, 0
  1245                              <1> .error_CY_5:
  1246 00000686 7250                <1> 	jc short .error_CY_6
  1247 00000688 8946F6              <1> 	mov word [bp + ?len], ax
  1248 0000068B 8956F8              <1> 	mov word [bp + ?len + 2], dx
  1249 0000068E E93001              <1> 	jmp .handle_match
  1250                              <1> 
  1251                              <1> .2nd_bit_zero:			; match
  1252 00000691 FF7722              <1> 	push word [bx + rep2 + 2]
  1253 00000694 FF7720              <1> 	push word [bx + rep2]
  1254 00000697 8F4724              <1> 	pop word [bx + rep3]
  1255 0000069A 8F4726              <1> 	pop word [bx + rep3 + 2]	; rep3 = rep2
  1256                              <1> 
  1257 0000069D FF771E              <1> 	push word [bx + rep1 + 2]
  1258 000006A0 FF771C              <1> 	push word [bx + rep1]
  1259 000006A3 8F4720              <1> 	pop word [bx + rep2]
  1260 000006A6 8F4722              <1> 	pop word [bx + rep2 + 2]	; rep2 = rep1
  1261                              <1> 
  1262 000006A9 FF771A              <1> 	push word [bx + rep0 + 2]
  1263 000006AC FF7718              <1> 	push word [bx + rep0]
  1264 000006AF 8F471C              <1> 	pop word [bx + rep1]
  1265 000006B2 8F471E              <1> 	pop word [bx + rep1 + 2]	; rep1 = rep0
  1266                              <1> 
  1267 000006B5 8B46EE              <1> 	mov ax, word [bp + ?pos_state]	; ax = pos_state variable
  1268 000006B8 1E                  <1> 	push ds
  1269 000006B9 07                  <1> 	pop es
  1270 000006BA 8DBF5634            <1> 	lea di, [bx + match_len_model]	; -> len_model to use
  1271 000006BE E88FFC              <1> 	call Range_decoder.decode_len	; dx:ax = length
  1272                              <1> 
  1273 000006C1 8946F0              <1> 	mov word [bp + ?len_state], ax
  1274 000006C4 85D2                <1> 	test dx, dx
  1275 000006C6 7505                <1> 	jnz @F
  1276 000006C8 83F803              <1> 	cmp ax, len_states - 1
  1277 000006CB 7205                <1> 	jb @FF
  1278                              <1> @@:
  1279 000006CD C746F00300          <1> 	mov word [bp + ?len_state], len_states - 1
  1280                              <1> @@:
  1281                              <1> 
  1282 000006D2 83C002              <1> 	add ax, min_match_len
  1283 000006D5 83D200              <1> 	adc dx, 0
  1284                              <1> .error_CY_6:
  1285 000006D8 723C                <1> 	jc short .error_CY_7
  1286                              <1> 
  1287 000006DA 8946F6              <1> 	mov word [bp + ?len], ax
  1288 000006DD 8956F8              <1> 	mov word [bp + ?len + 2], dx
  1289                              <1> 
  1290 000006E0 1E                  <1> 	push ds
  1291 000006E1 07                  <1> 	pop es
  1292 000006E2 8DBF5031            <1> 	lea di, [bx + bm_dis_slot]	; -> 2D array bm_dis_slot
  1293                              <1> 
  1294 000006E6 B88000              <1> 	mov ax, bit_model_size * (1 << dis_slot_bits)
  1295 000006E9 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 000006EC 01C7                <1> 	add di, ax			; -> 1D array at bm_dis_slot[len_state]
  1302 000006EE B90600              <1> 	mov cx, dis_slot_bits
  1303 000006F1 E8D2FB              <1> 	call Range_decoder.decode_tree
  1304 000006F4 894718              <1> 	mov word [bx + rep0], ax
  1305 000006F7 89571A              <1> 	mov word [bx + rep0 + 2], dx
  1306                              <1> 
  1307 000006FA 85D2                <1> 	test dx, dx			; (same flags as cmp dx, 0)
  1308 000006FC 7503                <1> 	jne @F
  1309 000006FE 83F804              <1> 	cmp ax, start_dis_model
  1310                              <1> @@:
  1311 00000701 7303E99B00          <1> 	jnae .not_rep0_ae_start_dis_model
  1312                              <1> 
  1313                              <1> .rep0_ae_start_dis_model:
  1314 00000706 8946F2              <1> 	mov word [bp + ?dis_slot], ax
  1315 00000709 8956F4              <1> 	mov word [bp + ?dis_slot + 2], dx
  1316                              <1> 
  1317 0000070C D1EA                <1> 	shr dx, 1
  1318 0000070E D1D8                <1> 	rcr ax, 1			; dis_slot >> 1
  1319 00000710 83E801              <1> 	sub ax, 1
  1320 00000713 83DA00              <1> 	sbb dx, 0			; - 1
  1321                              <1> .error_CY_7:
  1322                              <1> .error_CY_8:
  1323 00000716 7230                <1> 	jc short .error_CY_9
  1324 00000718 F9                  <1> 	stc
  1325 00000719 752D                <1> 	jnz short .error_CY_9
  1326 0000071B 91                  <1> 	xchg cx, ax			; cx = direct_bits, clobber ax
  1327 0000071C 31D2                <1> 	xor dx, dx
  1328 0000071E B80100              <1> 	mov ax, 1
  1329 00000721 2246F2              <1> 	and al, byte [bp + ?dis_slot]
  1330 00000724 0C02                <1> 	or al, 2
  1331 00000726 51                  <1> 	push cx
  1332 00000727 E306                <1> 	jcxz @FF
  1333                              <1> @@:
  1334 00000729 D1E0                <1> 	shl ax, 1
  1335 0000072B D1D2                <1> 	rcl dx, 1
  1336 0000072D E2FA                <1> 	loop @B
  1337                              <1> @@:
  1338 0000072F 59                  <1> 	pop cx
  1339 00000730 894718              <1> 	mov word [bx + rep0], ax
  1340 00000733 89571A              <1> 	mov word [bx + rep0 + 2], dx
  1341                              <1> 
  1342 00000736 837EF400            <1> 	cmp word [bp + ?dis_slot + 2], 0
  1343 0000073A 7504                <1> 	jne @F
  1344 0000073C 837EF20E            <1> 	cmp word [bp + ?dis_slot], end_dis_model
  1345                              <1> @@:
  1346 00000740 7328                <1> 	jnb .not_dis_slot_below_end_dis_model
  1347                              <1> 
  1348                              <1> .dis_slot_below_end_dis_model:
  1349 00000742 2B46F2              <1> 	sub ax, word [bp + ?dis_slot]
  1350 00000745 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 00000748 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 0000074A 01C0                <1> 	add ax, ax
  1360 0000074C 11D2                <1> 	adc dx, dx			; dx:ax *= 2
  1361 0000074E 7227                <1> 	jc short .error_CY_10
  1362 00000750 F9                  <1> 	stc
  1363 00000751 7524                <1> 	jnz short .error_CY_10		; if dx != 0 -->
  1364 00000753 1E                  <1> 	push ds
  1365 00000754 07                  <1> 	pop es
  1366 00000755 8DBF5033            <1> 	lea di, [bx + bm_dis]		; es:di -> bm_dis array
  1367 00000759 01C7                <1> 	add di, ax			; index into the array
  1368 0000075B 721A                <1> 	jc short .error_CY_10
  1369 0000075D E892FB              <1> 	call Range_decoder.decode_tree_reversed
  1370 00000760 014718              <1> 	add word [bx + rep0], ax
  1371 00000763 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1372 00000766 720F                <1> 	jc short .error_CY_10
  1373 00000768 EB37                <1> 	jmp .after_dis_slot_below
  1374                              <1> 
  1375                              <1> .not_dis_slot_below_end_dis_model:
  1376 0000076A 83E904              <1> 	sub cx, dis_align_bits
  1377 0000076D E8BEFA              <1> 	call Range_decoder.decode
  1378 00000770 B90400              <1> 	mov cx, dis_align_bits
  1379                              <1> @@:
  1380 00000773 D1E0                <1> 	shl ax, 1
  1381 00000775 D1D2                <1> 	rcl dx, 1
  1382                              <1> .error_CY_10:
  1383 00000777 721A                <1> 	jc short .error_CY_11
  1384 00000779 E2F8                <1> 	loop @B
  1385 0000077B 014718              <1> 	add word [bx + rep0], ax
  1386 0000077E 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1387                              <1> 
  1388 00000781 B90400              <1> 	mov cx, dis_align_bits
  1389 00000784 1E                  <1> 	push ds
  1390 00000785 07                  <1> 	pop es
  1391 00000786 8DBF3634            <1> 	lea di, [bx + bm_align]
  1392 0000078A E865FB              <1> 	call Range_decoder.decode_tree_reversed
  1393 0000078D 014718              <1> 	add word [bx + rep0], ax
  1394 00000790 11571A              <1> 	adc word [bx + rep0 + 2], dx
  1395                              <1> .error_CY_11:
  1396 00000793 727D                <1> 	jc .error_CY_12
  1397                              <1> 
  1398 00000795 837F1AFF            <1> 	cmp word [bx + rep0 + 2], -1	; rep0 = 0FFFF_FFFFh ?
  1399 00000799 7504                <1> 	jne @F
  1400 0000079B 837F18FF            <1> 	cmp word [bx + rep0], -1
  1401                              <1> @@:
  1402 0000079F 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 000007A1 B8070A              <1> 	mov ax, 7 | (10 << 8)
  1410 000007A4 E83DFA              <1> 	call State.select
  1411                              <1> 
  1412 000007A7 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1413 000007AA 8B4718              <1> 	mov ax, word [bx + rep0]
  1414                              <1> 
  1415 000007AD 3B5712              <1> 	cmp dx, word [bx + lz_decoder.dictionary_size + 2]
  1416 000007B0 7503                <1> 	jne @F
  1417 000007B2 3B4710              <1> 	cmp ax, word [bx + lz_decoder.dictionary_size]
  1418                              <1> @@:
  1419 000007B5 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 000007B7 3B5716              <1> 	cmp dx, word [bx + lz_decoder.pos + 2]
  1424 000007BA 7503                <1> 	jne @F
  1425 000007BC 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  1426                              <1> @@:
  1427                              <1> .error_AE_1:
  1428 000007BF 7356                <1> 	jae short .error_1
  1429                              <1> 
  1430                              <1> .handle_match:
  1431 000007C1 8B571A              <1> 	mov dx, word [bx + rep0 + 2]
  1432 000007C4 8B4718              <1> 	mov ax, word [bx + rep0]
  1433                              <1> 
  1434 000007C7 E8FEFB              <1> 	call calculate_peek_pointer_disi
  1435                              <1> 
  1436 000007CA 8B46F6              <1> 	mov ax, word [bp + ?len]
  1437 000007CD 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 000007D0 014714              <1> 	add word [bx + lz_decoder.pos], ax
  1453 000007D3 115716              <1> 	adc word [bx + lz_decoder.pos + 2], dx
  1454 000007D6 723A                <1> 	jc short .error_CY_12		; (CY) -->
  1455                              <1> 
  1456 000007D8 2946DE              <1> 	sub word [bp + ?length_of_destination], ax
  1457 000007DB 1956E0              <1> 	sbb word [bp + ?length_of_destination + 2], dx
  1458                              <1> 					; enough space left ?
  1459 000007DE 7232                <1> 	jb short .error_CY_12		; no --> (below == CY)
  1460                              <1> 
  1461 000007E0 1E                  <1> 	push ds
  1462                              <1> 
  1463 000007E1 8EDF                <1> 	mov ds, di			; ds:si -> source
  1464 000007E3 C47ED6              <1> 	les di, [bp + ?dst]		; es:di -> destination
  1465                              <1> .hm_loop:
  1466 000007E6 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 000007E9 85D2                <1> 	test dx, dx			; >= 1_0000h ?
  1471 000007EB 7508                <1> 	jnz @F				; yes, full block -->
  1472 000007ED 85C0                <1> 	test ax, ax			; == 0 ?
  1473 000007EF 7415                <1> 	jz .hm_end			; yes, done -->
  1474 000007F1 39C8                <1> 	cmp ax, cx			; can move in one (last) block ?
  1475 000007F3 7607                <1> 	jbe .hm_last			; yes -->
  1476                              <1> @@:
  1477                              <1> 					; no, move one block and continue
  1478 000007F5 29C8                <1> 	sub ax, cx
  1479 000007F7 83DA00              <1> 	sbb dx, 0			; left over remaining
  1480 000007FA EB03                <1> 	jmp .hm_copy
  1481                              <1> 
  1482                              <1> .hm_last:
  1483 000007FC 91                  <1> 	xchg cx, ax			; cx = remaining length
  1484 000007FD 31C0                <1> 	xor ax, ax			; no more remaining
  1485                              <1> 
  1486                              <1> .hm_copy:
  1487 000007FF F3A4                <1> 	rep movsb			; move one block (full or partial)
  1488                              <1> 
  1489 00000801 E83D02              <1> 	call normalise_both_pointers
  1490 00000804 EBE0                <1> 	jmp .hm_loop
  1491                              <1> 
  1492                              <1> .hm_end:
  1493 00000806 897ED6              <1> 	mov word [bp + ?dst], di
  1494 00000809 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 0000080C 1F                  <1> 	pop ds
  1503                              <1> %if _ALLOW_OVERLAPPING
  1504 0000080D 53                  <1> 	push bx
  1505 0000080E E81402              <1> 	call check_pointers_not_overlapping
  1506 00000811 5B                  <1> 	pop bx				; returns CF
  1507                              <1> .error_CY_12:
  1508 00000812 7203                <1> 	jc short .error_1
  1509                              <1> %endif
  1510 00000814 E902FD              <1> 	jmp .loop
  1511                              <1> 
  1512                              <1> %if ! _ALLOW_OVERLAPPING
  1513                              <1> .error_CY_12:
  1514                              <1> %endif
  1515                              <1> .error_1:
  1516 00000817 E9A000              <1> 	jmp .error
  1517                              <1> 
  1518                              <1> 
  1519                              <1> .end_member:			; End Of Stream marker
  1520 0000081A 837EF800            <1> 	cmp word [bp + ?len + 2], min_match_len >> 16
  1521 0000081E 7504                <1> 	jne @F
  1522 00000820 837EF602            <1> 	cmp word [bp + ?len], min_match_len & 0FFFFh
  1523                              <1> @@:
  1524 00000824 75F1                <1> 	jne short .error_1
  1525                              <1> 
  1526                              <1> 		; decode_member succeeded
  1527                              <1> 
  1528 00000826 C55EE6              <1> 	lds bx, [bp + ?final_dst]	; -> localvariables
  1529                              <1> 
  1530 00000829 836EE214            <1> 	sub word [bp + ?length_of_source], lzip_trailer_size
  1531 0000082D 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1532 00000831 7303E98400          <1> 	jc .error
  1533                              <1> 
  1534 00000836 C476EA              <1> 	les si, [bp + ?src]	; es:si -> lzip_trailer.uncompressed_checksum
  1535 00000839 83C604              <1> 	add si, 4			; skip CRC
  1536                              <1> 
  1537                              <1> 				; es:si -> lzip_trailer.uncompressed_size
  1538 0000083C 26AD                <1> 	es lodsw			; does the destination length match ?
  1539 0000083E 3B4714              <1> 	cmp ax, word [bx + lz_decoder.pos]
  1540 00000841 7577                <1> 	jne .error
  1541 00000843 26AD                <1> 	es lodsw
  1542 00000845 3B4716              <1> 	cmp ax, word [bx + lz_decoder.pos + 2]
  1543 00000848 7570                <1> 	jne .error			; if no -->
  1544 0000084A 26AD                <1> 	es lodsw
  1545 0000084C 85C0                <1> 	test ax, ax
  1546 0000084E 756A                <1> 	jnz .error
  1547 00000850 26AD                <1> 	es lodsw
  1548 00000852 85C0                <1> 	test ax, ax
  1549 00000854 7564                <1> 	jnz .error
  1550                              <1> 
  1551 00000856 830714              <1> 	add word [bx + lz_decoder.range_decoder + range_decoder.member_pos], lzip_trailer_size
  1552 00000859 83570200            <1> 	adc word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2], 0
  1553 0000085D 725B                <1> 	jc .error
  1554                              <1> 
  1555                              <1> 				; es:si -> lzip_trailer.member_size
  1556 0000085F 26AD                <1> 	es lodsw			; does the source length match ?
  1557 00000861 3B07                <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos]
  1558 00000863 7555                <1> 	jne .error
  1559 00000865 26AD                <1> 	es lodsw
  1560 00000867 3B4702              <1> 	cmp ax, word [bx + lz_decoder.range_decoder + range_decoder.member_pos + 2]
  1561 0000086A 754E                <1> 	jne .error
  1562 0000086C 26AD                <1> 	es lodsw
  1563 0000086E 85C0                <1> 	test ax, ax
  1564 00000870 7548                <1> 	jnz .error
  1565 00000872 26AD                <1> 	es lodsw
  1566 00000874 85C0                <1> 	test ax, ax
  1567 00000876 7542                <1> 	jnz .error
  1568                              <1> 
  1569                              <1> 				; es:si -> behind lzip_trailer
  1570 00000878 06                  <1> 	 push es
  1571 00000879 56                  <1> 	 push si
  1572 0000087A E8D301              <1> 	call normalise_pointer
  1573 0000087D 8F46EA              <1> 	 pop word [bp + ?src]
  1574 00000880 8F46EC              <1> 	 pop word [bp + ?src + 2]
  1575                              <1> 
  1576 00000883 E9B7FB              <1> 	jmp .loop_member
  1577                              <1> 
  1578                              <1> .end:
  1579                              <1> 
  1580                              <1> .final:
  1581                              <1> %if _COUNTER && !_PROGRESS
  1582                              <1> 	mov al, '%'
  1583                              <1> 	call disp_al
  1584                              <1> %endif
  1585 00000886 C47EE6              <1> 	les di, [bp + ?final_dst]
  1586                              <1> 				; -> destination
  1587 00000889 C576DA              <1> 	lds si, [bp + ?original_dst]
  1588                              <1> 				; -> source
  1589 0000088C 1E                  <1> 	 push ds
  1590 0000088D 56                  <1> 	 push si
  1591 0000088E E81002              <1> 	call pointer_to_linear	; dx:ax = linear ?original_dst
  1592 00000891 91                  <1> 	xchg cx, ax
  1593 00000892 87DA                <1> 	xchg bx, dx		; bx:cx = linear ?original_dst, clobber dx:ax
  1594 00000894 FF76D8              <1> 	 push word [bp + ?dst + 2]
  1595 00000897 FF76D6              <1> 	 push word [bp + ?dst]
  1596 0000089A E80402              <1> 	call pointer_to_linear
  1597 0000089D 29C8                <1> 	sub ax, cx
  1598 0000089F 19DA                <1> 	sbb dx, bx		; = linear dst minus linear original_dst
  1599                              <1> 
  1600 000008A1 B90400              <1> 	mov cx, 4
  1601 000008A4 83C00F              <1> 	add ax, 15
  1602 000008A7 83D200              <1> 	adc dx, 0
  1603                              <1> @@:
  1604 000008AA D1EA                <1> 	shr dx, 1
  1605 000008AC D1D8                <1> 	rcr ax, 1
  1606 000008AE E2FA                <1> 	loop @B
  1607 000008B0 89C1                <1> 	mov cx, ax
  1608 000008B2 85D2                <1> 	test dx, dx
  1609                              <1> d0	mov byte [bp + ?errordata], 84h
  1610 000008B4 7504                <1> 	jnz .error
  1611                              <1> 
  1612 000008B6 E8D400              <1> 	call x_mov_p
  1613                              <1> 
  1614 000008B9 A8                  <1> 	db __TEST_IMM8			; (NC)
  1615                              <1> .error:
  1616 000008BA F9                  <1> 	stc
  1617                              <1> 
  1618                              <1> %if _COUNTER
  1619 000008BB 9F                  <1> 	lahf
  1620 000008BC B00D                <1> 	mov al, 13
  1621 000008BE E8CFF8              <1> 	call disp_al_for_progress
  1622 000008C1 B00A                <1> 	mov al, 10
  1623 000008C3 E8CAF8              <1> 	call disp_al_for_progress
  1624 000008C6 9E                  <1> 	sahf
  1625                              <1> %endif
  1626                              <1> d0	mov bx, word [bp + ?errordata]
  1627 000008C7 89EC5D              <1> 	lleave code
  1628 000008CA 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 000008CB 830701              <1> 	add word [bx + range_decoder.member_pos], 1
  1639 000008CE 83570200            <1> 	adc word [bx + range_decoder.member_pos + 2], 0
  1640 000008D2 72E6                <1> 	jc short .error
  1641                              <1> 
  1642                              <1> 		; INP:	ds:bx -> range_decoder structure
  1643                              <1> 		;	ss:bp -> depack stack frame
  1644                              <1> 		; OUT:	! If an error occurs, jumps to depack.error
  1645                              <1> 		;	If success,
  1646                              <1> 		;	 al = value read
  1647                              <1> 		; CHG:	-
  1648                              <1> ; get_byte:
  1649 000008D4 1E                  <1> 	push ds
  1650 000008D5 56                  <1> 	push si
  1651                              <1> 
  1652 000008D6 836EE201            <1> 	sub word [bp + ?length_of_source], 1
  1653 000008DA 835EE400            <1> 	sbb word [bp + ?length_of_source + 2], 0
  1654 000008DE 72DA                <1> 	jc short .error
  1655                              <1> 
  1656 000008E0 C576EA              <1> 	lds si, [bp + ?src]
  1657 000008E3 AC                  <1> 	lodsb
  1658 000008E4 1E                  <1> 	 push ds
  1659 000008E5 56                  <1> 	 push si
  1660 000008E6 E86701              <1> 	call normalise_pointer
  1661 000008E9 8F46EA              <1> 	 pop word [bp + ?src]
  1662 000008EC 8F46EC              <1> 	 pop word [bp + ?src + 2]
  1663 000008EF 5E                  <1> 	pop si
  1664 000008F0 1F                  <1> 	pop ds
  1665 000008F1 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 000008F2 C47ED6              <1> 	les di, [bp + ?dst]
  1677                              <1> 
  1678 000008F5 83471401            <1> 	add word [bx + lz_decoder.pos], 1
  1679 000008F9 83571600            <1> 	adc word [bx + lz_decoder.pos + 2], 0
  1680 000008FD 72BB                <1> 	jc short .error
  1681                              <1> 
  1682 000008FF 836EDE01            <1> 	sub word [bp + ?length_of_destination], 1
  1683 00000903 835EE000            <1> 	sbb word [bp + ?length_of_destination + 2], 0
  1684 00000907 72B1                <1> 	jb short .error
  1685                              <1> 
  1686 00000909 AA                  <1> 	stosb
  1687 0000090A 06                  <1> 	 push es
  1688 0000090B 57                  <1> 	 push di
  1689 0000090C E84101              <1> 	call normalise_pointer
  1690 0000090F 8F46D6              <1> 	 pop word [bp + ?dst]
  1691 00000912 8F46D8              <1> 	 pop word [bp + ?dst + 2]
  1692                              <1> 
  1693                              <1> %if _ALLOW_OVERLAPPING
  1694 00000915 53                  <1> 	push bx
  1695 00000916 E80C01              <1> 	call check_pointers_not_overlapping
  1696 00000919 5B                  <1> 	pop bx			; returns CF
  1697 0000091A 729E                <1> 	jc short .error
  1698                              <1> %endif
  1699 0000091C 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 0000091D 1E                  <1> 	 push ds
  1710 0000091E 56                  <1> 	 push si
  1711 0000091F E80A00              <1> 	call anti_normalise_pointer
  1712 00000922 5E                  <1> 	 pop si
  1713 00000923 1F                  <1> 	 pop ds
  1714                              <1> 
  1715 00000924 06                  <1> 	 push es
  1716 00000925 57                  <1> 	 push di
  1717 00000926 E80300              <1> 	call anti_normalise_pointer
  1718 00000929 5F                  <1> 	 pop di
  1719 0000092A 07                  <1> 	 pop es
  1720 0000092B 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 0000092C 5589E5              <1> 	lenter
  1734 0000092F 53                  <1> 	push bx
  1735 00000930 51                  <1> 	push cx
  1736                              <1> 
  1737 00000931 31DB                <1> 	xor bx, bx
  1738 00000933 31C9                <1> 	xor cx, cx
  1739 00000935 FF7606              <1> 	 push word [bp + ?segment]
  1740 00000938 FF7604              <1> 	 push word [bp + ?offset]
  1741 0000093B E80A00              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1742 0000093E 8F4604              <1> 	 pop word [bp + ?offset]
  1743 00000941 8F4606              <1> 	 pop word [bp + ?segment]
  1744                              <1> 
  1745 00000944 59                  <1> 	pop cx
  1746 00000945 5B                  <1> 	pop bx
  1747 00000946 5D                  <1> 	lleave
  1748 00000947 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 00000948 5589E5              <1> 	lenter
  1765 0000094B 50                  <1> 	push ax
  1766 0000094C 52                  <1> 	push dx
  1767                              <1> 
  1768 0000094D FF7606              <1> 	 push word [bp + ?segment]
  1769 00000950 FF7604              <1> 	 push word [bp + ?offset]
  1770 00000953 E84B01              <1> 	call pointer_to_linear
  1771                              <1> 
  1772 00000956 01C8                <1> 	add ax, cx
  1773 00000958 11DA                <1> 	adc dx, bx			; dx:ax += bx:cx
  1774                              <1> 
  1775 0000095A 83FA01              <1> 	cmp dx, 1
  1776 0000095D 7223                <1> 	jb @F
  1777                              <1> 
  1778 0000095F 50                  <1> 	push ax
  1779 00000960 83C8F0              <1> 	or ax, 0FFF0h
  1780 00000963 894604              <1> 	mov word [bp + ?offset], ax
  1781 00000966 58                  <1> 	pop ax
  1782                              <1> 
  1783 00000967 83E8F0              <1> 	sub ax, 0FFF0h
  1784 0000096A 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 0000096D D1EA                <2>  shr dx, 1
  1788 0000096F D1D8                <2>  rcr ax, 1
  1787 00000971 D1EA                <2>  shr dx, 1
  1788 00000973 D1D8                <2>  rcr ax, 1
  1787 00000975 D1EA                <2>  shr dx, 1
  1788 00000977 D1D8                <2>  rcr ax, 1
  1787 00000979 D1EA                <2>  shr dx, 1
  1788 0000097B D1D8                <2>  rcr ax, 1
  1790 0000097D 894606              <1> 	mov word [bp + ?segment], ax
  1791                              <1> 
  1792 00000980 EB07                <1> 	jmp .return
  1793                              <1> 
  1794                              <1> 		; dx:ax = 0000:offset
  1795                              <1> @@:
  1796 00000982 894604              <1> 	mov word [bp + ?offset], ax
  1797 00000985 83660600            <1> 	and word [bp + ?segment], 0
  1798                              <1> 
  1799                              <1> .return:
  1800 00000989 5A                  <1> 	pop dx
  1801 0000098A 58                  <1> 	pop ax
  1802 0000098B 5D                  <1> 	lleave
  1803 0000098C 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 0000098D E8B100              <1> 	call normalise_both_pointers
  1818 00000990 8CD8                <1> 	mov ax, ds
  1819 00000992 8CC2                <1> 	mov dx, es
  1820                              <1> 
  1821 00000994 85C9                <1> 	test cx, cx
  1822 00000996 7503E98800          <1> 	jz .return
  1823                              <1> 
  1824 0000099B 39D0                <1> 	cmp ax, dx		; source above destination ?
  1825 0000099D 7716                <1> 	ja .up			; yes, move up (forwards) -->
  1826 0000099F 7206                <1> 	jb .check_down
  1827                              <1> 
  1828 000009A1 39FE                <1> 	cmp si, di
  1829 000009A3 7710                <1> 	ja .up
  1830 000009A5 747C                <1> 	je .return		; pointers are the same, no need to move -->
  1831                              <1> .check_down:
  1832 000009A7 50                  <1> 	push ax
  1833 000009A8 01C8                <1> 	add ax, cx		; (expected not to carry)
  1834 000009AA 39D0                <1> 	cmp ax, dx		; end of source is above destination ?
  1835 000009AC 58                  <1> 	pop ax
  1836 000009AD 7726                <1> 	ja .down		; yes, move from top down -->
  1837 000009AF 7204                <1> 	jb .up
  1838 000009B1 39FE                <1> 	cmp si, di
  1839 000009B3 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 000009B5 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  1846 000009B9 760C                <1> 	jbe .uplast		; no -->
  1847 000009BB 51                  <1> 	push cx
  1848 000009BC B9F87F              <1> 	mov cx, 0FFF0h /2
  1849 000009BF F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  1850 000009C1 59                  <1> 	pop cx
  1851 000009C2 E87C00              <1> 	call normalise_both_pointers
  1852 000009C5 EBEE                <1> 	jmp short .uploop	; proceed for more -->
  1853                              <1> .uplast:
  1854 000009C7 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  1855 000009CB D1E1                <1> 	shl cx, 1
  1856 000009CD D1E1                <1> 	shl cx, 1
  1857 000009CF D1E1                <1> 	shl cx, 1		; *8, paragraphs to words
  1858 000009D1 F3A5                <1> 	rep movsw		; move last part
  1859 000009D3 EB4E                <1> 	jmp short .return
  1860                              <1> 
  1861                              <1> .down:
  1862 000009D5 FD                  <1> 	std			; _AMD_ERRATUM_109_WORKAROUND as below
  1863                              <1> 
  1864 000009D6 89C8                <1> 	mov ax, cx
  1865 000009D8 31DB                <1> 	xor bx, bx
  1866 000009DA 51                  <1> 	push cx
  1867 000009DB B90400              <1> 	mov cx, 4
  1868                              <1> @@:
  1869 000009DE D1E0                <1> 	shl ax, 1
  1870 000009E0 D1D3                <1> 	rcl bx, 1
  1871 000009E2 E2FA                <1> 	loop @B
  1872 000009E4 83E802              <1> 	sub ax, 2
  1873 000009E7 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 000009EA 91                  <1> 	xchg ax, cx		; bx:cx = displacement to point to last word
  1878 000009EB 1E                  <1> 	 push ds
  1879 000009EC 56                  <1> 	 push si
  1880 000009ED E858FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1881 000009F0 5E                  <1> 	 pop si
  1882 000009F1 1F                  <1> 	 pop ds			; -> last word of source
  1883 000009F2 06                  <1> 	 push es
  1884 000009F3 57                  <1> 	 push di
  1885 000009F4 E851FF              <1> 	call anti_normalise_pointer_with_displacement_bxcx
  1886 000009F7 5F                  <1> 	 pop di
  1887 000009F8 07                  <1> 	 pop es			; -> last word of destination
  1888 000009F9 59                  <1> 	pop cx
  1889                              <1> 
  1890                              <1> .dnloop:
  1891 000009FA 81E9FF0F            <1> 	sub cx, 0FFFh		; 64 KiB - 16 B left ?
  1892 000009FE 760C                <1> 	jbe .dnlast		; no -->
  1893 00000A00 51                  <1> 	push cx
  1894 00000A01 B9F87F              <1> 	mov cx, 0FFF0h /2
  1895 00000A04 F3A5                <1> 	rep movsw		; move 64 KiB - 16 B
  1896 00000A06 59                  <1> 	pop cx
  1897 00000A07 E813FF              <1> 	call anti_normalise_both_pointers
  1898 00000A0A EBEE                <1> 	jmp short .dnloop	; proceed for more -->
  1899                              <1> .dnlast:
  1900 00000A0C 81C1FF0F            <1> 	add cx, 0FFFh		; restore counter
  1901 00000A10 D1E1                <1> 	shl cx, 1
  1902 00000A12 D1E1                <1> 	shl cx, 1
  1903 00000A14 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 00000A16 E308                <1> 	jcxz @FF
  1944 00000A18 83F914              <1> 	cmp cx, 20
  1945 00000A1B 7703                <1> 	ja @FF
  1946                              <1> @@:
  1947 00000A1D A5                  <1> 	movsw
  1948 00000A1E E2FD                <1> 	loop @B
  1949                              <1> @@:
  1950                              <1> %endif
  1951 00000A20 F3A5                <1> 	rep movsw		; move first part
  1952 00000A22 FC                  <1> 	cld
  1953                              <1> .return:
  1954 00000A23 EB1C                <1> 	jmp normalise_both_pointers
  1737                                  %endif
  1738                                  
  1739                                  
  1740                                  %if _LZO
  1741                                  	%include "lzo.asm"
  1742                                  %endif
  1743                                  
  1744                                  
  1745                                  %if _LZSA2
  1746                                  	%include "lzsa2.asm"
  1747                                  %endif
  1748                                  
  1749                                  
  1750                                  %if _APL
  1751                                  	%include "apl.asm"
  1752                                  %endif
  1753                                  
  1754                                  
  1755                                  %if _BZP
  1756                                  	%include "bzp.asm"
  1757                                  %endif
  1758                                  
  1759                                  
  1760                                  %if _ZEROCOMP
  1761                                  	%include "zerocomp.asm"
  1762                                  %endif
  1763                                  
  1764                                  
  1765                                  %if _MVCOMP
  1766                                  	%include "mvcomp.asm"
  1767                                  %endif
  1768                                  
  1769                                  
  1770                                  %if _LZEXEDAT
  1771                                  	%include "lzexedat.asm"
  1772                                  %endif
  1773                                  
  1774                                  
  1775                                  %if _ALLOW_OVERLAPPING
  1776                                  		; INP:	?src, ?dst
  1777                                  		; OUT:	CY if error (?src < ?dst)
  1778                                  		;	NC if success
  1779                                  		; CHG:	ax, bx, cx, dx
  1780                                  check_pointers_not_overlapping:
  1781                                  %if CHECK_POINTERS_VARIABLE_DST
  1782 00000A25 FF76D8                  	 push word [bp + ?dst + 2]
  1783 00000A28 FF76D6                  	 push word [bp + ?dst]
  1784                                  %else
  1785                                  	 push es
  1786                                  	 push di
  1787                                  %endif
  1788 00000A2B E87300                  	call pointer_to_linear
  1789                                  
  1790 00000A2E 91                      	xchg cx, ax
  1791 00000A2F 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1792                                  
  1793                                  %if CHECK_POINTERS_VARIABLE_SRC
  1794 00000A31 FF76EC                  	 push word [bp + ?src + 2]
  1795 00000A34 FF76EA                  	 push word [bp + ?src]
  1796                                  %else
  1797                                  	 push ds
  1798                                  	 push si
  1799                                  %endif
  1800 00000A37 E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1801                                  
  1802 00000A3A 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1803 00000A3C 7502                    	jne @F
  1804 00000A3E 39C8                    	cmp ax, cx
  1805                                  @@:
  1806                                  					; (CY) if error (src < dst)
  1807                                  					; (NC) if no error
  1808 00000A40 C3                      	retn
  1809                                  %endif
  1810                                  
  1811                                  	; This leaves the lframe context created within the
  1812                                  	;  specific depacker's file. The above function
  1813                                  	;  check_pointers_not_overlapping uses the frame.
  1814                                  	lleave ctx
  1815                                  
  1816                                  
  1817                                  		; INP:	ds:si = pointer
  1818                                  		;	es:di = pointer
  1819                                  		; OUT:	ds:si normalised
  1820                                  		;	es:di normalised
  1821                                  %if NEED_NORMALISE_BOTH_POINTERS
  1822                                  normalise_both_pointers:
  1823 00000A41 06                      	 push es
  1824 00000A42 57                      	 push di
  1825 00000A43 E80A00                  	call normalise_pointer
  1826 00000A46 5F                      	 pop di
  1827 00000A47 07                      	 pop es
  1828                                  %endif
  1829                                  
  1830                                  normalise_dssi_pointer:
  1831 00000A48 1E                      	 push ds
  1832 00000A49 56                      	 push si
  1833 00000A4A E80300                  	call normalise_pointer
  1834 00000A4D 5E                      	 pop si
  1835 00000A4E 1F                      	 pop ds
  1836 00000A4F C3                      	retn
  1837                                  
  1838                                  
  1839                                  		; INP:	word [ss:sp + 2] = segment
  1840                                  		;	word [ss:sp] = offset
  1841                                  		;
  1842                                  		; Note:	Does not work correctly with pointers that point to
  1843                                  		;	 a HMA location. Do not use then!
  1844                                  normalise_pointer:
  1845                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1846                                  	lframe near
  1847                                  	lpar word,	segment
  1848                                  	lpar word,	offset
  1849                                  	lpar_return
  1850 00000A50 5589E5                  	lenter
  1851                                  
  1852 00000A53 837E040F                	cmp word [bp + ?offset], 15
  1853 00000A57 7617                    	jbe .ret
  1854                                  
  1855 00000A59 53                      	push bx
  1856 00000A5A 51                      	push cx
  1857                                  
  1858 00000A5B 31DB                    	xor bx, bx
  1859 00000A5D 31C9                    	xor cx, cx
  1860 00000A5F FF7606                  	 push word [bp + ?segment]
  1861 00000A62 FF7604                  	 push word [bp + ?offset]
  1862 00000A65 E80A00                  	call normalise_pointer_with_displacement_bxcx
  1863 00000A68 8F4604                  	 pop word [bp + ?offset]
  1864 00000A6B 8F4606                  	 pop word [bp + ?segment]
  1865                                  
  1866 00000A6E 59                      	pop cx
  1867 00000A6F 5B                      	pop bx
  1868                                  .ret:
  1869 00000A70 5D                      	lleave
  1870 00000A71 C3                      	lret
  1871                                  
  1872                                  
  1873                                  		; INP:	word [ss:sp + 2] = segment
  1874                                  		;	word [ss:sp] = offset
  1875                                  		;	bx:cx = add/sub displacement
  1876                                  		; OUT:	CY if the displacement carries
  1877                                  		;	NC if not
  1878                                  normalise_pointer_with_displacement_bxcx:
  1879                                  %endif
  1880                                  	lframe near
  1881                                  	lpar word,	segment
  1882                                  	lpar word,	offset
  1883                                  	lpar_return
  1884 00000A72 5589E5                  	lenter
  1885                                  
  1886                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1887                                  	cmp word [bp + ?offset], 15
  1888                                  	jbe .ret
  1889                                  %endif
  1890                                  
  1891 00000A75 50                      	push ax
  1892 00000A76 51                      	push cx
  1893 00000A77 52                      	push dx
  1894                                  
  1895 00000A78 FF7606                  	 push word [bp + ?segment]
  1896 00000A7B FF7604                  	 push word [bp + ?offset]
  1897 00000A7E E82000                  	call pointer_to_linear
  1898                                  
  1899                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1900                                  	; push bx
  1901                                  	; 				; sign-extend cx into bx:cx
  1902                                  	; cmp cx, 8000h			; CY if < 8000h (NC if negative)
  1903                                  	; cmc				; NC if positive
  1904                                  	; sbb bx, bx			; 0 if was NC, -1 if was CY
  1905                                  
  1906 00000A81 01C1                    	add cx, ax
  1907 00000A83 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1908                                  	; pop bx
  1909 00000A85 9F                      	lahf				; ah = flags
  1910                                  %else
  1911                                  	xchg ax, cx
  1912                                  %endif
  1913                                  
  1914                                  %if 0
  1915                                  		; Adds in HMA support for this function. Not currently used.
  1916                                  	cmp dx, 10h			; dx:ax >= 10_0000h ?
  1917                                  	jb @F				; no, linear-to-pointer normally -->
  1918                                  	; ja .error
  1919                                  
  1920                                  	add cx, 10h
  1921                                  	; jc .error
  1922                                  	mov word [bp + ?offset], cx
  1923                                  	or word [bp + ?segment], -1
  1924                                  	jmp .return
  1925                                  @@:
  1926                                  %endif
  1927                                  
  1928 00000A86 53                      	push bx
  1929 00000A87 89CB                    	mov bx, cx
  1930 00000A89 83E10F                  	and cx, 15
  1931 00000A8C 894E04                  	mov word [bp + ?offset], cx
  1932                                  
  1933 00000A8F B104                    	mov cl, 4
  1934                                  @@:
  1935 00000A91 D1EA                    	shr dx, 1
  1936 00000A93 D1DB                    	rcr bx, 1
  1937 00000A95 E2FA                    	loop @B
  1938                                  
  1939 00000A97 895E06                  	mov word [bp + ?segment], bx
  1940 00000A9A 5B                      	pop bx
  1941                                  
  1942                                  	; test dx, dx
  1943                                  	; jnz .error
  1944                                  
  1945                                  .return:
  1946                                  
  1947                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1948 00000A9B 9E                      	sahf				; restore flags from ah
  1949                                  %endif
  1950 00000A9C 5A                      	pop dx
  1951 00000A9D 59                      	pop cx
  1952 00000A9E 58                      	pop ax
  1953                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1954                                  .ret:
  1955                                  %endif
  1956 00000A9F 5D                      	lleave
  1957 00000AA0 C3                      	lret
  1958                                  
  1959                                  
  1960                                  		; INP:	word [ss:sp + 2] = segment
  1961                                  		;	word [ss:sp] = offset
  1962                                  		; OUT:	dx:ax = linear address
  1963                                  pointer_to_linear:
  1964                                  	lframe near
  1965                                  	lpar word,	segment
  1966                                  	lpar word,	offset
  1967 00000AA1 5589E5                  	lenter
  1968                                  
  1969 00000AA4 8B4606                  	mov ax, word [bp + ?segment]
  1970 00000AA7 31D2                    	xor dx, dx
  1971 00000AA9 51                      	push cx
  1972 00000AAA B90400                  	mov cx, 4
  1973                                  @@:
  1974 00000AAD D1E0                    	shl ax, 1
  1975 00000AAF D1D2                    	rcl dx, 1
  1976 00000AB1 E2FA                    	loop @B
  1977                                  
  1978 00000AB3 034604                  	add ax, word [bp + ?offset]
  1979 00000AB6 11CA                    	adc dx, cx			; cx = 0 here
  1980 00000AB8 59                      	pop cx
  1981                                  
  1982 00000AB9 5D                      	lleave
  1983 00000ABA C20400                  	lret
  1984                                  
  1985                                  
  1986                                  %if _PASSLCFG
  1987 00000ABD 90<rep 3h>              	align 16
  1988                                  transfer_lcfg_block:
  1989 00000AC0 90<rep 20h>             	times lcfg.size nop
  1990                                  %endif
  1991                                  	align 16
  1992                                  init1_end:
  1993                                  
  1994                                  
  1995                                  	usesection INIT0
  1996                                  %if _TEST_PROGRAM
  1997                                  init0_msg:
  1998                                  .error_stderr:	db "Error: Not enough memory allocated.",13,10
  1999                                  .error_stderr.length: equ $ - .error_stderr
  2000                                  .error_c_stdout:
  2001                                  .error_stdout:	db "0"
  2002                                  %if 0
  2003                                  		_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  2008                                  %endif
  2009                                  		db 13,10
  2010                                  .error_c_stdout.length: equ $ - .error_c_stdout
  2011                                  .error_stdout.length: equ $ - .error_stdout
  2012                                  
  2013                                  	align 1024
  2014                                  %if ($ - $$) != 1024
  2015                                   %error Wrong INIT0 size
  2016                                  %endif
  2017                                  %endif
  2018                                  
  2019 000000D2 90<rep Eh>              	align 16
  2020                                  init0_end:
  2021                                  
  2022                                  
  2023                                  %assign num (init1_end - init1_start) + (init0_end - init0_start)
  2024                                  %if _BRIEFLZ
  2025                                  %define which iniblz
  2026                                  %elif _LZ4
  2027                                  %define which inilz4
  2028                                  %elif _SNAPPY
  2029                                  %define which inisz
  2030                                  %elif _EXODECR
  2031                                  %define which iniexo
  2032                                  %elif _X
  2033                                  %define which inix
  2034                                  %elif _HEATSHRINK
  2035                                  %define which inihs
  2036                                  %elif _LZD
  2037                                  %define which inilz
  2038                                  %elif _LZO
  2039                                  %define which inilzo
  2040                                  %elif _LZSA2
  2041                                  %define which inilzsa2
  2042                                  %elif _APL
  2043                                  %define which iniapl
  2044                                  %elif _BZP
  2045                                  %define which inibzp
  2046                                  %elif _ZEROCOMP
  2047                                  %define which inizero
  2048                                  %elif _MVCOMP
  2049                                  %define which inimv
  2050                                  %elif _LZEXEDAT
  2051                                  %define which inilzexe
  2052                                  %endif
  2053                                  %warning which: num bytes used for depacker
  2053          ******************       warning: inilz: 3008 bytes used for depacker [-w+user]
  2054                                  
  2055                                  
  2056                                  %if _TEST_PROGRAM
  2057                                  	addsection INIT2, align=16 follows=INIT1 vstart=0
  2058                                  init2_start:
  2059                                  		; si => after PSP
  2060                                  		; cs => INIT2
  2061                                  		; psp, free, payload, init1, init2, payload space, stack
  2062                                  		;
  2063                                  		; The correct allocation for the test program
  2064                                  		;  is image size (init0, payload, init1, init2)
  2065                                  		;  minus init0 plus compressed payload size
  2066                                  		;  plus decompressed size plus stack. For
  2067                                  		;  simplicity, init0 subtraction may be skipped.
  2068                                  
  2069                                  		; ss:sp -> word amount repetitions, word ax
  2070                                  		; bx = 1 if A mode test,
  2071                                  		;	8001h if B mode test,
  2072                                  		;	4001h if C mode test
  2073                                  	push bx
  2074                                  
  2075                                  	lframe 0
  2076                                  	lpar word,	repetitions
  2077                                  	lpar word,	whichtest
  2078                                  	lenter
  2079                                  
  2080                                  	mov dx, word [bp + ?repetitions]
  2081                                  	cmp dx, -1
  2082                                  	jne @F
  2083                                  
  2084                                  .cmdline_error:
  2085                                  %if _DEBUG0
  2086                                  	mov bx, -1
  2087                                  %endif
  2088                                  	mov dx, init2_msg.cmdline_error
  2089                                  	mov cx, init2_msg.cmdline_error.length
  2090                                  	jmp init2_error
  2091                                  
  2092                                  
  2093                                  @@:
  2094                                  	testopt [bp + ?whichtest], 4000h
  2095                                  	jnz .a_or_c
  2096                                  	testopt [bp + ?whichtest], 8000h
  2097                                  	jz .a_or_c
  2098                                  .b:
  2099                                  	test dx, dx
  2100                                  	jz .cmdline_error
  2101                                  	jmp @F
  2102                                  
  2103                                  .a_or_c:
  2104                                  	test dx, dx
  2105                                  	jnz .cmdline_error
  2106                                  @@:
  2107                                  
  2108                                  	mov dx, cs
  2109                                  	add dx, (init2_end - init2_start) >> 4
  2110                                  				; => payload saving area
  2111                                  	mov ax, cs
  2112                                  	sub ax, ( (init1_end - init1_start) 		+ (payload_end - payload) 		) >> 4		; => payload source for first run
  2115                                  	mov cx, (payload_end - payload) >> 4
  2116                                  	call init2_movp		; copy payload to payload saving area
  2117                                  		; We save away the payload here because a failure
  2118                                  		;  to decompress generally overwrites part of that
  2119                                  		;  payload which was used as source.
  2120                                  
  2121                                  	mov dx, ax		; dx => payload source to use
  2122                                  	mov ax, cs
  2123                                  	sub ax, (init1_end - init1_start) >> 4
  2124                                  				; ax => INIT1
  2125                                  	mov bx, 1		; say we're in EXE mode
  2126                                  	push dx
  2127                                  	push ax
  2128                                  	push si			; si => target
  2129                                  	 push cs
  2130                                  	 call .transfer		; call decompression
  2131                                  	pop si
  2132                                  	pop ax
  2133                                  	pop dx
  2134                                  		; Returns here after decompression.
  2135                                  		; CY if error.
  2136                                  	jnc @F
  2137                                  
  2138                                  	mov dx, init2_msg.initial_error
  2139                                  	mov cx, init2_msg.initial_error.length
  2140                                  	jmp init2_error
  2141                                  
  2142                                  @@:
  2143                                  	numdef INCLUDE_UNCOMPRESSED
  2144                                  	numdef WRITE_WRONG_FILE
  2145                                  %if _INCLUDE_UNCOMPRESSED
  2146                                  payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed
  2147                                  
  2148                                  	call checkdecompressed
  2149                                  	je @F
  2150                                  
  2151                                  %if _WRITE_WRONG_FILE
  2152                                  	call writefiles
  2153                                  %endif
  2154                                  
  2155                                  %if _DEBUG0
  2156                                  	mov bx, -1
  2157                                  %endif
  2158                                  	mov dx, init2_msg.initial_error_2
  2159                                  	mov cx, init2_msg.initial_error_2.length
  2160                                  	jmp init2_error
  2161                                  
  2162                                  @@:
  2163                                  %endif
  2164                                  
  2165                                  	testopt [bp + ?whichtest], 4000h
  2166                                  	jz @F
  2167                                  	mov ax, cs
  2168                                  	sub ax, (init1_end - init1_start) >> 4
  2169                                  				; ax => INIT1
  2170                                  	mov es, ax
  2171                                  	mov ax, word [es:init1_c_mode_counter]
  2172                                  	call init2_disp_ax_dec
  2173                                  	mov al, 13
  2174                                  	call init2_disp_al
  2175                                  	mov al, 10
  2176                                  	call init2_disp_al
  2177                                  	mov ax, 4C00h
  2178                                  	int 21h
  2179                                  
  2180                                  @@:
  2181                                  	lvar word,	upperbound
  2182                                  	 push dx
  2183                                  	lvar word,	lowerbound
  2184                                  	 push si
  2185                                  	lvar word,	current_init1
  2186                                  	 push ax
  2187                                  
  2188                                  %if _TEST_PROGRESS
  2189                                  	mov dx, init2_msg.progress.1
  2190                                  	mov cx, init2_msg.progress.1.length
  2191                                  .loop:
  2192                                  	push cs
  2193                                  	pop ds
  2194                                  	mov bx, 2
  2195                                  	mov ah, 40h
  2196                                  	int 21h
  2197                                  %else
  2198                                  .loop:
  2199                                  %endif
  2200                                  
  2201                                  	mov dx, [bp + ?upperbound]
  2202                                  
  2203                                  	testopt [bp + ?whichtest], 8000h
  2204                                  	jz @F
  2205                                  
  2206                                  	dec word [bp + ?repetitions]
  2207                                  	jnz .test_b_skip_bound
  2208                                  
  2209                                  %if _TEST_PROGRESS
  2210                                  	push cs
  2211                                  	pop ds
  2212                                  	mov dx, init2_msg.progress.linebreak
  2213                                  	mov cx, init2_msg.progress.linebreak.length
  2214                                  	mov bx, 2
  2215                                  	mov ah, 40h
  2216                                  	int 21h
  2217                                  %endif
  2218                                  	mov ax, 4C00h
  2219                                  	int 21h
  2220                                  
  2221                                  
  2222                                  @@:
  2223                                  	sub dx, [bp + ?lowerbound]
  2224                                  	jz .found
  2225                                  	shr dx, 1
  2226                                  		; Rounding down, so that we never retry upper bound.
  2227                                  		;  The upper bound is known to be working.
  2228                                  	add dx, [bp + ?lowerbound]
  2229                                  
  2230                                  .test_b_skip_bound:
  2231                                  	push dx
  2232                                  	add dx, (payload_end - payload) >> 4
  2233                                  	mov ax, [bp + ?current_init1]
  2234                                  	mov cx, (init1_end - init1_start) >> 4
  2235                                  	call init2_movp
  2236                                  	mov [bp + ?current_init1], dx
  2237                                  	pop dx
  2238                                  
  2239                                  	mov ax, cs
  2240                                  	add ax, (init2_end - init2_start) >> 4
  2241                                  				; => payload in saving area
  2242                                  	mov cx, (payload_end - payload) >> 4
  2243                                  	call init2_movp		; copy payload from payload saving area
  2244                                  
  2245                                  		; dx => source
  2246                                  	mov ax, [bp + ?current_init1]
  2247                                  	mov bx, 1
  2248                                  	push dx
  2249                                  	push si
  2250                                  	 push cs
  2251                                  	 call .transfer
  2252                                  	pop si
  2253                                  	pop dx
  2254                                  		; Returns here after decompression.
  2255                                  		; CY if error.
  2256                                  	jnc @F
  2257                                  
  2258                                  	testopt [bp + ?whichtest], 8000h
  2259                                  	jnz .test_b_fail
  2260                                  
  2261                                  		; error: this attempt is one below the new lower bound
  2262                                  	inc dx
  2263                                  	mov word [bp + ?lowerbound], dx
  2264                                  
  2265                                  %if _TEST_PROGRESS
  2266                                  	mov dx, init2_msg.progress.fail
  2267                                  	mov cx, init2_msg.progress.fail.length
  2268                                  %endif
  2269                                  	jmp .loop
  2270                                  
  2271                                  @@:
  2272                                  %if _INCLUDE_UNCOMPRESSED
  2273                                  	call checkdecompressed
  2274                                  	je @F
  2275                                  
  2276                                  %if _WRITE_WRONG_FILE
  2277                                  	call writefiles
  2278                                  %endif
  2279                                  
  2280                                  .test_b_fail:
  2281                                  %if _TEST_PROGRESS
  2282                                  	push cs
  2283                                  	pop ds
  2284                                  	mov dx, init2_msg.progress.linebreak
  2285                                  	mov cx, init2_msg.progress.linebreak.length
  2286                                  	mov bx, 2
  2287                                  	mov ah, 40h
  2288                                  	int 21h
  2289                                  %endif
  2290                                  %if _DEBUG0
  2291                                  	mov bx, -2
  2292                                  %endif
  2293                                  	mov dx, init2_msg.subsequent_error_2
  2294                                  	mov cx, init2_msg.subsequent_error_2.length
  2295                                  	jmp init2_error
  2296                                  
  2297                                  @@:
  2298                                  %endif
  2299                                  		; success: this attempt is the new upper bound
  2300                                  	mov word [bp + ?upperbound], dx
  2301                                  %if _TEST_PROGRESS
  2302                                  	mov dx, init2_msg.progress.success
  2303                                  	mov cx, init2_msg.progress.success.length
  2304                                  %endif
  2305                                  	jmp .loop
  2306                                  
  2307                                  .found:
  2308                                  %if _TEST_PROGRESS
  2309                                  	push cs
  2310                                  	pop ds
  2311                                  	mov dx, init2_msg.progress.linebreak
  2312                                  	mov cx, init2_msg.progress.linebreak.length
  2313                                  	mov bx, 2
  2314                                  	mov ah, 40h
  2315                                  	int 21h
  2316                                  %endif
  2317                                  	mov ax, word [bp + ?upperbound]
  2318                                  	sub ax, si		; = how many paragraphs in buffer before source
  2319                                  	add ax, paras( (init1_end - init1_start) 			+ (payload_end - payload) )
  2321                                  				; = how many paragraphs needed for process
  2322                                  	call init2_disp_ax_dec
  2323                                  	mov al, 13
  2324                                  	call init2_disp_al
  2325                                  	mov al, 10
  2326                                  	call init2_disp_al
  2327                                  	mov ax, 4C00h
  2328                                  	int 21h
  2329                                  
  2330                                  
  2331                                  .transfer:
  2332                                  	xor di, di
  2333                                  	push di			; placeholder ax value on stack
  2334                                  	push ax			; INIT1 segment
  2335                                  	push di			; zero = init1_start
  2336                                  	retf			; transfer to INIT1:init1_start
  2337                                  
  2338                                  
  2339                                  
  2340                                  %if _INCLUDE_UNCOMPRESSED
  2341                                  
  2342                                  
  2343                                  %if _WRITE_WRONG_FILE
  2344                                  writefiles:
  2345                                  	push cs
  2346                                  	pop ds
  2347                                  	mov dx, init2_msg.wrong_file_name
  2348                                  	xor cx, cx
  2349                                  	mov ah, 3Ch
  2350                                  	int 21h
  2351                                  	jc .notfile
  2352                                  
  2353                                  	mov bx, ax
  2354                                  	mov cx, payload_uncompressed_size >> 4
  2355                                  	xor dx, dx
  2356                                  .loopfile:
  2357                                  	mov ds, si
  2358                                  	mov ah, 40h
  2359                                  	push cx
  2360                                  	mov cx, 16
  2361                                  	int 21h
  2362                                  	pop cx
  2363                                  	inc si
  2364                                  	loop .loopfile
  2365                                  
  2366                                  	mov ds, si
  2367                                  	mov cx, payload_uncompressed_size & 15
  2368                                  	mov ah, 40h
  2369                                  	int 21h
  2370                                  
  2371                                  	mov ah, 3Eh
  2372                                  	int 21h
  2373                                  
  2374                                  .notfile:
  2375                                  
  2376                                  	push cs
  2377                                  	pop ds
  2378                                  	mov dx, init2_msg.wrong_file_name2
  2379                                  	xor cx, cx
  2380                                  	mov ah, 3Ch
  2381                                  	int 21h
  2382                                  	jc .notfile2
  2383                                  
  2384                                  	mov bx, ax
  2385                                  	mov cx, payload_uncompressed_size >> 4
  2386                                  	mov si, cs
  2387                                  	add si, (payload_uncompressed - init2_start) >> 4
  2388                                  	xor dx, dx
  2389                                  .loopfile2:
  2390                                  	mov ds, si
  2391                                  	mov ah, 40h
  2392                                  	push cx
  2393                                  	mov cx, 16
  2394                                  	int 21h
  2395                                  	pop cx
  2396                                  	inc si
  2397                                  	loop .loopfile2
  2398                                  
  2399                                  	mov ds, si
  2400                                  	mov cx, payload_uncompressed_size & 15
  2401                                  	mov ah, 40h
  2402                                  	int 21h
  2403                                  
  2404                                  	mov ah, 3Eh
  2405                                  	int 21h
  2406                                  
  2407                                  .notfile2:
  2408                                  	retn
  2409                                  %endif
  2410                                  
  2411                                  		; INP:	si => decompressed image
  2412                                  		; OUT:	ZR if matching
  2413                                  		;	NZ if mismatching
  2414                                  		; CHG:	es, ds, di, bx, cx
  2415                                  		; STT:	UP
  2416                                  checkdecompressed:
  2417                                  	push ax
  2418                                  	push dx
  2419                                  	push si
  2420                                  %if _PAYLOAD_KERNEL_MAX_PARAS
  2421                                  	mov cx, _PAYLOAD_KERNEL_MAX_PARAS
  2422                                  	mov bx, 0
  2423                                  %else
  2424                                  	mov cx, payload_uncompressed_size >> 4
  2425                                  	mov bx, payload_uncompressed_size & 15
  2426                                  %endif
  2427                                  	mov di, cs
  2428                                  	add di, (payload_uncompressed - init2_start) >> 4
  2429                                  	jcxz .end
  2430                                  .loop:
  2431                                  	push cx
  2432                                  	mov cx, 8
  2433                                  	mov ds, si
  2434                                  	mov es, di
  2435                                  	inc si
  2436                                  	inc di
  2437                                  	push si
  2438                                  	push di
  2439                                  	xor si, si
  2440                                  	xor di, di
  2441                                  	repe cmpsw
  2442                                  	pop di
  2443                                  	pop si
  2444                                  	pop cx
  2445                                  	jne .ret
  2446                                  	loop .loop
  2447                                  .end:
  2448                                  	mov ds, si
  2449                                  	mov es, di
  2450                                  	xor si, si
  2451                                  	xor di, di		; (ZR)
  2452                                  	mov cx, bx
  2453                                  	repe cmpsb
  2454                                  .ret:
  2455                                  	pop si
  2456                                  	pop dx
  2457                                  	pop ax
  2458                                  	retn
  2459                                  %endif
  2460                                  
  2461                                  
  2462                                  init2_error:
  2463                                  %if _DEBUG0
  2464                                  	push bx
  2465                                  %endif
  2466                                  	push cs
  2467                                  	pop ds
  2468                                  	mov bx, 2
  2469                                  	mov ah, 40h
  2470                                  	int 21h
  2471                                  
  2472                                  %if _DEBUG0
  2473                                  	mov dx, init2_msg.rc
  2474                                  	mov cx, init2_msg.rc.length
  2475                                  	mov bx, 2
  2476                                  	mov ah, 40h
  2477                                  	int 21h
  2478                                  	pop ax
  2479                                  	call init2_error_disp_ax_hex
  2480                                  	mov dx, init2_msg.linebreak
  2481                                  	mov cx, init2_msg.linebreak.length
  2482                                  	mov bx, 2
  2483                                  	mov ah, 40h
  2484                                  	int 21h
  2485                                  %endif
  2486                                  
  2487                                  	testopt [bp + ?whichtest], 4000h
  2488                                  	jz @F
  2489                                  	mov dx, init2_msg.error_c_stdout
  2490                                  	mov cx, init2_msg.error_c_stdout.length
  2491                                  	jmp @FF
  2492                                  @@:
  2493                                  	testopt [bp + ?whichtest], 8000h
  2494                                  	jnz @FF
  2495                                  	mov dx, init2_msg.error_stdout
  2496                                  	mov cx, init2_msg.error_stdout.length
  2497                                  @@:
  2498                                  	mov bx, 1
  2499                                  	mov ah, 40h
  2500                                  	int 21h
  2501                                  @@:
  2502                                  	mov ax, 4CFFh
  2503                                  	int 21h
  2504                                  
  2505                                  	lleave ctx
  2506                                  
  2507                                  
  2508                                  %if _DEBUG0
  2509                                  init2_error_disp_ax_hex:	; ax
  2510                                  		xchg al,ah
  2511                                  		call init2_error_disp_al_hex	; display former ah
  2512                                  		xchg al,ah			;  and fall trough for al
  2513                                  init2_error_disp_al_hex:	; al
  2514                                  		push cx
  2515                                  		mov cl,4
  2516                                  		ror al,cl
  2517                                  		call init2_error_disp_al_lownibble_hex
  2518                                  						; display former high-nibble
  2519                                  		rol al,cl
  2520                                  		pop cx
  2521                                  						;  and fall trough for low-nibble
  2522                                  init2_error_disp_al_lownibble_hex:
  2523                                  		push ax			 ; save ax for call return
  2524                                  		and al,00001111b		; high nibble must be zero
  2525                                  		add al,'0'			; if number is 0-9, now it's the correct character
  2526                                  		cmp al,'9'
  2527                                  		jna .decimalnum		 ; if we get decimal number with this, ok -->
  2528                                  		add al,7			;  otherwise, add 7 and we are inside our alphabet
  2529                                   .decimalnum:
  2530                                  		call init2_error_disp_al
  2531                                  		pop ax
  2532                                  		retn
  2533                                  
  2534                                  
  2535                                  init2_error_disp_al:
  2536                                  	push dx
  2537                                  	push cx
  2538                                  	push bx
  2539                                  	push ax
  2540                                  	mov dx, sp
  2541                                  	push ds
  2542                                  	 push ss
  2543                                  	 pop ds
  2544                                  	mov cx, 1
  2545                                  	mov bx, 2
  2546                                  	mov ah, 40h
  2547                                  	int 21h
  2548                                  	pop ds
  2549                                  	pop ax
  2550                                  	pop bx
  2551                                  	pop cx
  2552                                  	pop dx
  2553                                  	retn
  2554                                  %endif
  2555                                  
  2556                                  
  2557                                  init2_disp_al:
  2558                                  	push dx
  2559                                  	push ax
  2560                                  	mov dl, al
  2561                                  	mov ah, 2
  2562                                  	int 21h
  2563                                  	pop ax
  2564                                  	pop dx
  2565                                  	retn
  2566                                  
  2567                                  
  2568                                  		; Display number in ax decimal
  2569                                  		;
  2570                                  		; INP:	ax = number
  2571                                  		; OUT:	displayed using Int21.02
  2572                                  		; CHG:	none
  2573                                  init2_disp_ax_dec:			; ax (no leading zeros)
  2574                                  		push bx
  2575                                  		xor bx, bx
  2576                                  .pushax:
  2577                                  		push dx
  2578                                  		push ax
  2579                                  		or bl, bl
  2580                                  		jz .nobl
  2581                                  		sub bl, 5
  2582                                  		neg bl
  2583                                  .nobl:
  2584                                  		push cx
  2585                                  		mov cx, 10000
  2586                                  		call .divide_out
  2587                                  		mov cx, 1000
  2588                                  		call .divide_out
  2589                                  		mov cx, 100
  2590                                  		call .divide_out
  2591                                  		mov cl, 10
  2592                                  		call .divide_out
  2593                                  							; (Divisor 1 is useless)
  2594                                  		add al, '0'
  2595                                  		call init2_disp_al
  2596                                  		pop cx
  2597                                  		pop ax
  2598                                  		pop dx
  2599                                  		pop bx					; Caller's register
  2600                                  		retn
  2601                                  
  2602                                  
  2603                                  		; INP:	ax = number
  2604                                  		;	cx = divisor
  2605                                  		; OUT:	ax = remainder of operation
  2606                                  		;	result displayed
  2607                                  .divide_out:
  2608                                  		push dx
  2609                                  		xor dx, dx
  2610                                  		div cx				; 0:ax / cx
  2611                                  		push dx				; remainder
  2612                                  		dec bl
  2613                                  		jnz .nobl2
  2614                                  		or bh, 1
  2615                                  .nobl2:
  2616                                  		or bh, al
  2617                                  		jz .leadingzero
  2618                                  		add al, '0'
  2619                                  		call init2_disp_al		; display result
  2620                                   .leadingzero:
  2621                                  		pop ax				; remainder
  2622                                  		pop dx
  2623                                  		retn
  2624                                  
  2625                                  
  2626                                  init2_msg:
  2627                                  %if _TEST_PROGRESS
  2628                                  .progress.1:		db "Info: 1"
  2629                                  .progress.1.length: equ $ - .progress.1
  2630                                  .progress.fail:		db "F"
  2631                                  .progress.fail.length: equ $ - .progress.fail
  2632                                  .progress.success:	db "S"
  2633                                  .progress.success.length: equ $ - .progress.success
  2634                                  .progress.linebreak:	db 13,10
  2635                                  .progress.linebreak.length: equ $ - .progress.linebreak
  2636                                  %endif
  2637                                  %if _WRITE_WRONG_FILE
  2638                                  .wrong_file_name:	asciz "WRONG.BIN"
  2639                                  .wrong_file_name2:	asciz "WRONG2.BIN"
  2640                                  %endif
  2641                                  .initial_error:	db "Error: Test program failed to decompress with full buffer."
  2642                                  .linebreak:	db 13,10
  2643                                  .initial_error.length: equ $ - .initial_error
  2644                                  .linebreak.length: equ $ - .linebreak
  2645                                  %if _DEBUG0
  2646                                  .rc:	db "Error: Failure code="
  2647                                  .rc.length: equ $ - .rc
  2648                                  %endif
  2649                                  %if _INCLUDE_UNCOMPRESSED
  2650                                  .initial_error_2:	db "Error: Test program decompressed wrongly with full buffer.",13,10
  2651                                  .initial_error_2.length: equ $ - .initial_error_2
  2652                                  .subsequent_error_2:	db "Error: Test program decompressed wrongly during test.",13,10
  2653                                  .subsequent_error_2.length: equ $ - .subsequent_error_2
  2654                                  %endif
  2655                                  .cmdline_error:	db "Error: Invalid command line input.",13,10
  2656                                  .cmdline_error.length: equ $ - .cmdline_error
  2657                                  
  2658                                  .error_c_stdout:
  2659                                  .error_stdout:	db "0"
  2660                                  %if 0
  2661                                  		_autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE 				+ (payload_end - payload) 				+ (init1_end - init1_start) 				+ ADDITIONAL_MEMORY 				)
  2666                                  %endif
  2667                                  		db 13,10
  2668                                  .error_c_stdout.length: equ $ - .error_c_stdout
  2669                                  .error_stdout.length: equ $ - .error_stdout
  2670                                  
  2671                                  
  2672                                  		; Move paragraphs
  2673                                  		;
  2674                                  		; INP:	ax => source
  2675                                  		;	dx => destination
  2676                                  		;	cx = number of paragraphs
  2677                                  		; CHG:	-
  2678                                  		; OUT:	ax and dx unchanged
  2679                                  		; Note:	Doesn't work correctly on HMA; doesn't always wrap to LMA either.
  2680                                  		;	Do not provide a wrapped/HMA source or destination!
  2681                                  init2_movp:
  2682                                  	push cx
  2683                                  	push ds
  2684                                  	push si
  2685                                  	push es
  2686                                  	push di
  2687                                  
  2688                                  	cmp ax, dx		; source above destination ?
  2689                                  	ja .up			; yes, move up (forwards) -->
  2690                                  	je .return		; same, no need to move -->
  2691                                  	push ax
  2692                                  	add ax, cx		; (expected not to carry)
  2693                                  	cmp ax, dx		; end of source is above destination ?
  2694                                  	pop ax
  2695                                  	ja .down		; yes, move from top down -->
  2696                                  	; Here, the end of source is below-or-equal the destination,
  2697                                  	;  so they do not overlap. In this case we prefer moving up.
  2698                                  
  2699                                  .up:
  2700                                  	push ax
  2701                                  	push dx
  2702                                  .uploop:
  2703                                  	mov ds, ax
  2704                                  	mov es, dx
  2705                                  	xor di, di
  2706                                  	xor si, si		; -> start of segment
  2707                                  	sub cx, 1000h		; 64 KiB left ?
  2708                                  	jbe .uplast		; no -->
  2709                                  	push cx
  2710                                  	mov cx, 10000h /2
  2711                                  	rep movsw		; move 64 KiB
  2712                                  	pop cx
  2713                                  	add ax, 1000h
  2714                                  	add dx, 1000h		; -> next segment
  2715                                  	jmp short .uploop	; proceed for more -->
  2716                                  .uplast:
  2717                                  	add cx, 1000h		; restore counter
  2718                                  	shl cx, 1
  2719                                  	shl cx, 1
  2720                                  	shl cx, 1		; *8, paragraphs to words
  2721                                  	rep movsw		; move last part
  2722                                  	pop dx
  2723                                  	pop ax
  2724                                  	jmp short .return
  2725                                  
  2726                                  .down:
  2727                                  	std			; _AMD_ERRATUM_109_WORKAROUND as below
  2728                                  .dnloop:
  2729                                  	sub cx, 1000h		; 64 KiB left ?
  2730                                  	jbe .dnlast		; no -->
  2731                                  	push ax
  2732                                  	push dx
  2733                                  	add ax, cx
  2734                                  	add dx, cx
  2735                                  	mov ds, ax		; -> 64 KiB not yet moved
  2736                                  	mov es, dx
  2737                                  	pop dx
  2738                                  	pop ax
  2739                                  	mov di, -2
  2740                                  	mov si, di		; moved from last word down
  2741                                  	push cx
  2742                                  	mov cx, 10000h /2
  2743                                  	rep movsw		; move 64 KiB
  2744                                  	pop cx
  2745                                  	jmp short .dnloop	; proceed for more -->
  2746                                  .dnlast:
  2747                                  	add cx, 1000h		; restore counter
  2748                                  	shl cx, 1
  2749                                  	shl cx, 1
  2750                                  	shl cx, 1		; *8, paragraphs to words
  2751                                  	mov di, cx
  2752                                  	dec di
  2753                                  	shl di, 1		; words to offset, -> last word
  2754                                  	mov si, di
  2755                                  	mov ds, ax
  2756                                  	mov es, dx		; first segment correct
  2757                                  
  2758                                  		; Refer to comment in init0_movp.
  2759                                  %if _AMD_ERRATUM_109_WORKAROUND
  2760                                  	jcxz @FF
  2761                                  	cmp cx, 20
  2762                                  	ja @FF
  2763                                  @@:
  2764                                  	movsw
  2765                                  	loop @B
  2766                                  @@:
  2767                                  %endif
  2768                                  	rep movsw		; move first part
  2769                                  	cld
  2770                                  .return:
  2771                                  	pop di
  2772                                  	pop es
  2773                                  	pop si
  2774                                  	pop ds
  2775                                  	pop cx
  2776                                  	retn
  2777                                  
  2778                                  
  2779                                  	align 16
  2780                                  
  2781                                  	strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN"
  2782                                  %if _INCLUDE_UNCOMPRESSED
  2783                                  payload_uncompressed:
  2784                                  	incbin _UNCOMPRESSED_FILE
  2785                                  .end:
  2786                                  	db 38
  2787                                  	align 16, db 38
  2788                                  %endif
  2789                                  init2_end:
  2790                                  %endif
  2791                                  
