     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 B9F70D                  	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 05AC0D                  	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[9004]                	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 DA6Ch>             	incbin _PAYLOAD_FILE
   993                                  .end:
   994 0000DA6C 26<rep 4h>              	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 B96CDA                  	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 E8B001                  	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[9004]                	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 B95100                  	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 B95100                  	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 B95100                  	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 B95100                  	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"
  1737                                  %endif
  1738                                  
  1739                                  
  1740                                  %if _LZO
  1741                                  	%include "lzo.asm"
  1742                                  %endif
  1743                                  
  1744                                  
  1745                                  %if _LZSA2
  1746                                  	%include "lzsa2.asm"
     1                              <1> 
     2                              <1> ; 8086 Assembly lDOS iniload payload LZSA2 depacker
     3                              <1> ;  by E. C. Masloch, 2021
     4                              <1> ;
     5                              <1> ;  based on:
     6                              <1> ;  decompress_small.S - space-efficient decompressor implementation for 8088
     7                              <1> ;
     8                              <1> ;  Copyright (C) 2019 Emmanuel Marty
     9                              <1> ;
    10                              <1> ;  This software is provided 'as-is', without any express or implied
    11                              <1> ;  warranty.  In no event will the authors be held liable for any damages
    12                              <1> ;  arising from the use of this software.
    13                              <1> ;
    14                              <1> ;  Permission is granted to anyone to use this software for any purpose,
    15                              <1> ;  including commercial applications, and to alter it and redistribute it
    16                              <1> ;  freely, subject to the following restrictions:
    17                              <1> ;
    18                              <1> ;  1. The origin of this software must not be misrepresented; you must not
    19                              <1> ;     claim that you wrote the original software. If you use this software
    20                              <1> ;     in a product, an acknowledgment in the product documentation would be
    21                              <1> ;     appreciated but is not required.
    22                              <1> ;  2. Altered source versions must be plainly marked as such, and must not be
    23                              <1> ;     misrepresented as being the original software.
    24                              <1> ;  3. This notice may not be removed or altered from any source distribution.
    25                              <1> 
    26                              <1> 
    27                              <1> 	numdef COUNTER,		0, 128
    28                              <1> %if (_COUNTER - 1) & _COUNTER
    29                              <1>  %error COUNTER must be a power of two
    30                              <1> %endif
    31                              <1> 
    32                              <1> %assign CHECK_POINTERS_VARIABLE_SRC 0
    33                              <1> %assign CHECK_POINTERS_VARIABLE_DST 0
    34                              <1> 
    35                              <1> 
    36                              <1> 		; INP:	ds:si -> source
    37                              <1> 		;	dx:cx = length of source
    38                              <1> 		;	es:di -> destination (below source)
    39                              <1> 		;	if _IMAGE_EXE:
    40                              <1> 		;	 bx = EXE mode flag (bit 0)
    41                              <1> 		;	else:
    42                              <1> 		;	 bx = 0
    43                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
    44                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
    45                              <1> 		;	 (-1 if full source should be decompressed)
    46                              <1> 		;	else:
    47                              <1> 		;	 ax = -1
    48                              <1> 		; OUT:	NC if success
    49                              <1> 		;	CY if error,
    50                              <1> 		;	 bx = ?errordata (if _DEBUG0)
    51                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
    52                              <1> 		; STT:	UP
    53                              <1> 		;
    54                              <1> 		; Note:	The destination reaches up to below the source.
    55                              <1> 		; Note:	The input pointers need not be normalised yet.
    56                              <1> 		;	 Normalised means that the offset part is below 16.
    57                              <1> depack:
    58                              <1> 	lframe near
    59                              <1> %if _IMAGE_EXE || _DEBUG0 || _COUNTER
    60 000001CB 5589E5              <1> 	lenter early
    61                              <1>  %if _IMAGE_EXE
    62                              <1> 	lvar word,	exemode	; must be bp - 2!
    63                              <1> 	 push bx
    64                              <1>   %if ?exemode != -2
    65                              <1>    %error exemode variable must be directly below bp
    66                              <1>   %endif
    67                              <1>  %endif
    68                              <1>  %if _DEBUG0 || _COUNTER
    69 000001CE 31DB                <1> 	xor bx, bx
    70                              <1>  %endif
    71                              <1>  %if _DEBUG0
    72                              <1> 	lvar word,	errordata
    73                              <1> 	 push bx
    74                              <1>  %endif
    75                              <1> %endif
    76                              <1> 	lvar word,	counter
    77                              <1> %if _COUNTER
    78 000001D0 53                  <1> 	 push bx		; initialise counter (high byte) to zero
    79                              <1> %endif
    80                              <1> 	lvar dword,	length_of_source_after_block
    81                              <1> 	lvar word,	matchlength
    82 000001D1 8D66F8              <1> 	lenter
    83                              <1> 
    84 000001D4 E83502              <1> 	call normalise_both_pointers
    85                              <1> 
    86                              <1> 	lvar dword,	src
    87 000001D7 1E                  <1> 	 push ds
    88 000001D8 56                  <1> 	 push si
    89                              <1> 	lvar dword,	original_dst
    90 000001D9 06                  <1> 	 push es
    91 000001DA 57                  <1> 	 push di
    92                              <1> 	lvar dword,	dst
    93 000001DB 06                  <1> 	 push es
    94 000001DC 57                  <1> 	 push di
    95                              <1> 	lvar dword,	length_of_source
    96 000001DD 52                  <1> 	 push dx
    97 000001DE 51                  <1> 	 push cx
    98                              <1> 
    99                              <1> %if 0 ; && _PAYLOAD_KERNEL_MAX_PARAS
   100                              <1> 	cmp ax, -1		; no maximum specified ?
   101                              <1> 	je @FF			; retain -1 in ax -->
   102                              <1> 	test di, di		; do we need an additional paragraph ?
   103                              <1> 	jz @F			; no -->
   104                              <1> 	inc ax			; es + ax => paragraph after necessary part
   105                              <1> @@:
   106                              <1> 	mov dx, es
   107                              <1> 	add ax, dx		; => paragraph after necessary part
   108                              <1> 		; If the normalised destination pointer's segment grows
   109                              <1> 		;  to this segment then enough has been decompressed.
   110                              <1> d0	mov byte [bp + ?errordata], 40h
   111                              <1> 	jc .error		; should not carry
   112                              <1> @@:
   113                              <1> 	lvar word,	dst_max_segment
   114                              <1> 	 push ax
   115                              <1> %endif
   116                              <1> 
   117 000001DF 1E                  <1> 	 push ds
   118 000001E0 56                  <1> 	 push si
   119 000001E1 E88802              <1> 	call pointer_to_linear
   120                              <1> 
   121 000001E4 89D3                <1> 	mov bx, dx
   122 000001E6 91                  <1> 	xchg cx, ax		; bx:cx = source linear
   123                              <1> 
   124 000001E7 06                  <1> 	 push es
   125 000001E8 57                  <1> 	 push di
   126 000001E9 E88002              <1> 	call pointer_to_linear
   127                              <1> 
   128                              <1> %if _ALLOW_OVERLAPPING
   129 000001EC 034EE8              <1> 	add cx, word [bp + ?length_of_source]
   130 000001EF 135EEA              <1> 	adc bx, word [bp + ?length_of_source + 2]
   131                              <1> 		; In case of allowing overlapping source and destination,
   132                              <1> 		;  the ?length_of_destination variable is set to
   133                              <1> 		;  ?src + ?length_of_source - ?dst, allowing to write to
   134                              <1> 		;  all of the source buffer (with the checks already in place
   135                              <1> 		;  from the default handling). Additional checks are done by
   136                              <1> 		;  calling check_pointers_not_overlapping. This is done after
   137                              <1> 		;  every change of ?dst to verify that the write pointer stays
   138                              <1> 		;  below-or-equal the read pointer.
   139                              <1> 		; This means the remaining source data may be corrupted by a
   140                              <1> 		;  write, but nothing after the source data is written to,
   141                              <1> 		;  so the error handling (in INIT1 after the data) still works.
   142                              <1> %endif
   143                              <1> 
   144 000001F2 29C1                <1> 	sub cx, ax
   145 000001F4 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   146                              <1> 
   147                              <1> 	lvar dword,	length_of_destination
   148 000001F6 53                  <1> 	 push bx		; push into [bp + ?length_of_destination + 2]
   149 000001F7 51                  <1> 	 push cx		; push into [bp + ?length_of_destination]
   150                              <1> 
   151                              <1> %if _ALLOW_OVERLAPPING
   152 000001F8 E8FD01              <1> 	call check_pointers_not_overlapping
   153                              <1> 		; Note:	We initially check here that the write pointer is
   154                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   155                              <1> 		;	 Doing this check here (as well as after any
   156                              <1> 		;	 copied match) allows us to drop the check done
   157                              <1> 		;	 after moving literal bytes.
   158                              <1> d0	mov byte [bp + ?errordata], 1Bh
   159 000001FB 7268                <1> 	jc .error
   160                              <1> %endif
   161                              <1> 
   162 000001FD E88200              <1> 	call .lodsw
   163 00000200 3D7B9E              <1> 	cmp ax, 7Bh | (9Eh << 8)	; signature
   164 00000203 7560                <1> 	jne .error
   165 00000205 E86E00              <1> 	call .lodsb
   166 00000208 3C20                <1> 	cmp al, 1 << 5			; traits byte, check for lzsa2
   167 0000020A 7559                <1> 	jne .error
   168                              <1> 
   169                              <1> .loop:
   170 0000020C E8FD01              <1> 	call normalise_both_pointers
   171                              <1> 
   172 0000020F 31D2                <1> 	xor dx, dx
   173 00000211 E86E00              <1> 	call .lodsw			; bits 0 to 15 of length
   174 00000214 92                  <1> 	xchg ax, dx
   175 00000215 E85E00              <1> 	call .lodsb
   176 00000218 A87F                <1> 	test al, 0111_1111b		; reserved bits + bit 16 of length
   177 0000021A 7549                <1> 	jnz .error			; error if nonzero -->
   178                              <1> 
   179 0000021C E8F401              <1> 	call normalise_dssi_pointer
   180                              <1> 
   181                              <1> 		; This first check is only really relevant
   182                              <1> 		;  for uncompressed blocks.
   183 0000021F 89FB                <1> 	mov bx, di
   184 00000221 01D3                <1> 	add bx, dx			; fits in destination segment ?
   185 00000223 7240                <1> 	jc .error			;  (assuming bit 16 = 0)
   186                              <1> 		; This second check is to insure we don't
   187                              <1> 		;  have to normalise the source pointer
   188                              <1> 		;  until after the end of the block.
   189 00000225 89F3                <1> 	mov bx, si
   190 00000227 01D3                <1> 	add bx, dx			; fits in source segment ?
   191 00000229 723A                <1> 	jc .error
   192                              <1> 
   193 0000022B 84C0                <1> 	test al, al			; uncompressed ?
   194 0000022D 92                  <1> 	xchg ax, dx
   195 0000022E 7905                <1> 	jns .compressed			; no -->
   196                              <1> .uncompressed:
   197 00000230 91                  <1> 	xchg ax, cx
   198 00000231 F3A4                <1> 	rep movsb			; copy this
   199 00000233 EBD7                <1> 	jmp .loop
   200                              <1> 
   201                              <1> .compressed:
   202 00000235 8B4EE8              <1> 	mov cx, word [bp + ?length_of_source]
   203 00000238 8B5EEA              <1> 	mov bx, word [bp + ?length_of_source + 2]
   204                              <1> 
   205 0000023B 85C0                <1> 	test ax, ax
   206 0000023D 7421                <1> 	jz .end
   207                              <1> 
   208 0000023F 29C1                <1> 	sub cx, ax
   209 00000241 83DB00              <1> 	sbb bx, 0
   210 00000244 721F                <1> 	jc .error
   211 00000246 894EFA              <1> 	mov word [bp + ?length_of_source_after_block], cx
   212 00000249 895EFC              <1> 	mov word [bp + ?length_of_source_after_block + 2], bx
   213                              <1> 
   214 0000024C 06                  <1> 	push es
   215 0000024D 57                  <1> 	push di
   216 0000024E E83D00              <1> 	call lzsa2_decompress
   217 00000251 83F801              <1> 	cmp ax, 1			; CY if ax == 0
   218 00000254 91                  <1> 	xchg cx, ax
   219 00000255 19DB                <1> 	sbb bx, bx			; -1 if cx == 0, else 0
   220 00000257 F7DB                <1> 	neg bx				; 1 if cx == 0, else 0
   221 00000259 E8E101              <1> 	call normalise_pointer_with_displacement_bxcx
   222 0000025C 5F                  <1> 	pop di
   223 0000025D 07                  <1> 	pop es
   224 0000025E EBAC                <1> 	jmp .loop
   225                              <1> 
   226                              <1> .end:
   227 00000260 09CB                <1> 	or bx, cx
   228 00000262 7501                <1> 	jnz .error
   229                              <1> 
   230                              <1> .ret:
   231 00000264 A8                  <1> 	db __TEST_IMM8		; (skip stc, NC)
   232                              <1> .error:
   233 00000265 F9                  <1> 	stc
   234                              <1> 
   235                              <1> %if _COUNTER
   236 00000266 9F                  <1> 	lahf
   237 00000267 B00D                <1> 	mov al, 13
   238 00000269 E824FF              <1> 	call disp_al_for_progress
   239 0000026C B00A                <1> 	mov al, 10
   240 0000026E E81FFF              <1> 	call disp_al_for_progress
   241 00000271 9E                  <1> 	sahf
   242                              <1> %endif
   243                              <1> d0	mov bx, word [bp + ?errordata]
   244 00000272 89EC5D              <1> 	lleave code
   245 00000275 C3                  <1> 	lret
   246                              <1> 
   247                              <1> 
   248                              <1> 		; INP:	ds:si -> source data
   249                              <1> 		;	?length_of_source
   250                              <1> 		; OUT:	CY if error (source buffer too small)
   251                              <1> 		;	NC if success,
   252                              <1> 		;	 al = value read
   253                              <1> 		;	 ds:si incremented (NOT normalised)
   254                              <1> 		;	 ?length_of_source decremented
   255                              <1> .lodsb:
   256 00000276 836EE801            <1> 	sub word [bp + ?length_of_source], 1
   257 0000027A 835EEA00            <1> 	sbb word [bp + ?length_of_source + 2], 0
   258 0000027E 72E5                <1> 	jb .error
   259 00000280 AC                  <1> 	lodsb
   260                              <1> .retn:
   261 00000281 C3                  <1> 	retn
   262                              <1> 
   263                              <1> 
   264                              <1> 		; INP:	ds:si -> source data
   265                              <1> 		;	?length_of_source
   266                              <1> 		; OUT:	CY if error (source buffer too small)
   267                              <1> 		;	NC if success,
   268                              <1> 		;	 ax = value read
   269                              <1> 		;	 ds:si incremented (NOT normalised)
   270                              <1> 		;	 ?length_of_source decremented
   271                              <1> .lodsw:
   272 00000282 836EE802            <1> 	sub word [bp + ?length_of_source], 2
   273 00000286 835EEA00            <1> 	sbb word [bp + ?length_of_source + 2], 0
   274 0000028A 72D9                <1> 	jb .error
   275 0000028C AD                  <1> 	lodsw
   276 0000028D C3                  <1> 	retn
   277                              <1> 
   278                              <1> 
   279                              <1> 		; Decompress LZSA2 block
   280                              <1> 		;
   281                              <1> 		; INP:	ds:si -> LZSA2 block
   282                              <1> 		;	es:di -> output buffer
   283                              <1> 		;	?length_of_source
   284                              <1> 		;	?length_of_source_after_block = block end target
   285                              <1> 		;	?original_dst -> lowest valid back reference
   286                              <1> 		; OUT:	ax = decompressed size (0 means 64 KiB)
   287                              <1> 		;	ds:si -> behind source data
   288                              <1> 		;	jumps to depack.error if error condition detected
   289                              <1> 		; CHG:	all except bp
   290                              <1> lzsa2_decompress:
   291                              <1> .lodsb equ depack.lodsb
   292                              <1> .lodsw equ depack.lodsw
   293                              <1> 
   294 0000028E 57                  <1>    push di                 ; remember decompression offset
   295                              <1> 
   296 0000028F BB0001              <1>    mov bx,0100H
   297 00000292 8366F800            <1>    and word [bp + ?matchlength], 0
   298                              <1> 
   299                              <1> .decode_token_clear_cx:
   300 00000296 31C9                <1>    xor cx,cx
   301                              <1> .decode_token:
   302                              <1> %if _COUNTER
   303 00000298 FE46FE              <1> 	inc byte [bp + ?counter]
   304 0000029B F646FE7F            <1> 	test byte [bp + ?counter], _COUNTER - 1
   305 0000029F 7505                <1> 	jnz @F
   306 000002A1 B02E                <1> 	mov al, '.'
   307 000002A3 E88FFD              <1> 	call disp_al_counter
   308                              <1> @@:
   309                              <1> %endif
   310 000002A6 8B46E8              <1> 	mov ax, word [bp + ?length_of_source]
   311 000002A9 8B56EA              <1> 	mov dx, word [bp + ?length_of_source + 2]
   312                              <1> 
   313 000002AC 3956FC              <1> 	cmp word [bp + ?length_of_source_after_block + 2], dx
   314 000002AF 7503                <1> 	jne @F
   315 000002B1 3946FA              <1> 	cmp word [bp + ?length_of_source_after_block], ax
   316                              <1> @@:
   317 000002B4 7503E91B01          <1> 	je .end
   318 000002B9 77AA                <1> 	ja depack.error
   319                              <1> 
   320 000002BB 89C8                <1>    mov ax,cx               ; clear ah - cx is zero from above or from after rep movsb in .copy_match
   321 000002BD E8B6FF              <1> 	call .lodsb		; read token byte: XYZ|LL|MMMM
   322 000002C0 89C2                <1>    mov dx,ax               ; keep token in dl
   323                              <1>    
   324 000002C2 2418                <1>    and al,018H             ; isolate literals length in token (LL)
   325 000002C4 B103                <1>    mov cl,3
   326 000002C6 D2E8                <1>    shr al,cl               ; shift literals length into place
   327                              <1> 
   328 000002C8 3C03                <1>    cmp al,03H              ; LITERALS_RUN_LEN_V2?
   329 000002CA 7513                <1>    jne .got_literals       ; no, we have the full literals count from the token, go copy
   330                              <1> 
   331 000002CC E81701              <1>    call .get_nibble        ; get extra literals length nibble
   332 000002CF 00C8                <1>    add al,cl               ; add len from token to nibble 
   333 000002D1 3C12                <1>    cmp al,012H             ; LITERALS_RUN_LEN_V2 + 15 ?
   334 000002D3 750A                <1>    jne .got_literals       ; if not, we have the full literals count, go copy
   335                              <1> 
   336 000002D5 E89EFF              <1> 	call .lodsb		; grab extra length byte
   337 000002D8 0412                <1>    add al,012H             ; overflow?
   338 000002DA 7303                <1>    jnc .got_literals       ; if not, we have the full literals count, go copy
   339                              <1> 
   340 000002DC E8A3FF              <1> 	call .lodsw		; grab 16-bit extra length
   341                              <1> 
   342                              <1> .got_literals:
   343 000002DF 91                  <1>    xchg cx,ax
   344 000002E0 294EE8              <1> 	sub word [bp + ?length_of_source], cx
   345 000002E3 835EEA00            <1> 	sbb word [bp + ?length_of_source + 2], 0
   346 000002E7 7303E979FF          <1> 	jb depack.error
   347 000002EC 294EE4              <1> 	sub word [bp + ?length_of_destination], cx
   348 000002EF 835EE600            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   349 000002F3 7303E96DFF          <1> 	jb depack.error
   350 000002F8 F3A4                <1>    rep movsb               ; copy cx literals from ds:si to es:di
   351                              <1> 
   352 000002FA 52                  <1> 	push dx
   353 000002FB 50                  <1> 	push ax
   354 000002FC 8B46E8              <1> 	mov ax, word [bp + ?length_of_source]
   355 000002FF 8B56EA              <1> 	mov dx, word [bp + ?length_of_source + 2]
   356                              <1> 
   357 00000302 3956FC              <1> 	cmp word [bp + ?length_of_source_after_block + 2], dx
   358 00000305 7503                <1> 	jne @F
   359 00000307 3946FA              <1> 	cmp word [bp + ?length_of_source_after_block], ax
   360                              <1> @@:
   361 0000030A 58                  <1> 	pop ax
   362 0000030B 5A                  <1> 	pop dx
   363 0000030C 7503E9C300          <1> 	je .end
   364 00000311 7603E94FFF          <1> 	ja depack.error
   365                              <1> 
   366 00000316 F6C2C0              <1>    test dl,0C0h            ; check match offset mode in token (X bit)
   367 00000319 7819                <1>    js .rep_match_or_large_offset
   368                              <1> 
   369                              <1>    ;;cmp dl,040H             ; check if this is a 5 or 9-bit offset (Y bit)
   370                              <1>                            ; discovered via the test with bit 6 set
   371 0000031B 91                  <1>    xchg cx,ax              ; clear ah - cx is zero from the rep movsb above
   372 0000031C 7508                <1>    jne .offset_9_bit
   373                              <1> 
   374                              <1>                            ; 5 bit offset
   375 0000031E 80FA20              <1>    cmp dl,020H             ; test bit 5
   376 00000321 E8B500              <1>    call .get_nibble_x
   377 00000324 EB0A                <1>    jmp short .dec_offset_top
   378                              <1> 
   379                              <1> .offset_9_bit:             ; 9 bit offset
   380 00000326 E84DFF              <1> 	call .lodsb		; get 8 bit offset from stream in A
   381 00000329 FECC                <1>    dec ah                  ; set offset bits 15-8 to 1
   382 0000032B F6C220              <1>    test dl,020H            ; test bit Z (offset bit 8)
   383 0000032E 741F                <1>    je .get_match_length
   384                              <1> .dec_offset_top:
   385 00000330 FECC                <1>    dec ah                  ; clear bit 8 if Z bit is clear
   386                              <1>                            ; or set offset bits 15-8 to 1
   387 00000332 EB1B                <1>    jmp short .get_match_length
   388                              <1> 
   389                              <1> .rep_match_or_large_offset:
   390                              <1>    ;;cmp dl,0c0H             ; check if this is a 13-bit offset or a 16-bit offset/rep match (Y bit)
   391 00000334 7A0C                <1>    jpe .rep_match_or_16_bit
   392                              <1> 
   393                              <1>                            ; 13 bit offset
   394                              <1> 
   395 00000336 80FAA0              <1>    cmp dl,0A0H             ; test bit 5 (knowing that bit 7 is also set)
   396 00000339 86E0                <1>    xchg ah,al
   397 0000033B E89B00              <1>    call .get_nibble_x
   398 0000033E 2C02                <1>    sub al,2                ; substract 512
   399 00000340 EB08                <1>    jmp short .get_match_length_1
   400                              <1> 
   401                              <1> .rep_match_or_16_bit:
   402 00000342 F6C220              <1>    test dl,020H            ; test bit Z (offset bit 8)
   403 00000345 750B                <1>    jne .repeat_match       ; rep-match
   404                              <1> 
   405                              <1>                            ; 16 bit offset
   406 00000347 E82CFF              <1> 	call .lodsb		; Get 2-byte match offset
   407                              <1> 
   408                              <1> .get_match_length_1:
   409 0000034A 86E0                <1>    xchg ah,al
   410 0000034C E827FF              <1> 	call .lodsb		; load match offset bits 0-7
   411                              <1> 
   412                              <1> .get_match_length:
   413 0000034F 8746F8              <1> 	xchg word [bp + ?matchlength], ax
   414                              <1> 			; bp: offset
   415                              <1> .repeat_match:
   416 00000352 92                  <1>    xchg ax,dx              ; ax: original token
   417 00000353 2407                <1>    and al,07H              ; isolate match length in token (MMM)
   418 00000355 0402                <1>    add al,2                ; add MIN_MATCH_SIZE_V2
   419                              <1> 
   420 00000357 3C09                <1>    cmp al,09H              ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2?
   421 00000359 7518                <1>    jne .got_matchlen       ; no, we have the full match length from the token, go copy
   422                              <1> 
   423 0000035B E88800              <1>    call .get_nibble        ; get extra literals length nibble
   424 0000035E 00C8                <1>    add al,cl               ; add len from token to nibble 
   425 00000360 3C18                <1>    cmp al,018H             ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15?
   426 00000362 750F                <1>    jne .got_matchlen       ; no, we have the full match length from the token, go copy
   427                              <1> 
   428 00000364 E80FFF              <1> 	call .lodsb		; grab extra length byte
   429 00000367 0418                <1>    add al,018H             ; overflow?
   430 00000369 7308                <1>    jnc .got_matchlen       ; if not, we have the entire length
   431 0000036B 7503E9F5FE          <1> 	je depack.error		; detect EOD code
   432                              <1> 
   433 00000370 E80FFF              <1> 	call .lodsw		; grab 16-bit length
   434                              <1> 
   435                              <1> .got_matchlen:
   436 00000373 91                  <1>    xchg cx,ax              ; copy match length into cx
   437 00000374 1E                  <1>    push ds                 ; save ds:si (current pointer to compressed data)
   438 00000375 96                  <1>    xchg si,ax          
   439 00000376 06                  <1>    push es
   440 00000377 1F                  <1>    pop ds
   441 00000378 89FE                <1> 	mov si, di
   442 0000037A 0376F8              <1> 	add si, word [bp + ?matchlength]
   443                              <1> 			; ds:si now points at back reference in output data
   444 0000037D 7225                <1> 	jc @FF		; simple case branches here -->
   445 0000037F 53                  <1> 	push bx
   446 00000380 51                  <1> 	push cx
   447 00000381 8B4EF8              <1> 	mov cx, word [bp + ?matchlength]
   448 00000384 BBFFFF              <1> 	mov bx, -1
   449 00000387 06                  <1> 	 push es
   450 00000388 57                  <1> 	 push di
   451 00000389 E8B100              <1> 	call normalise_pointer_with_displacement_bxcx
   452 0000038C 5E                  <1> 	 pop si
   453 0000038D 5B                  <1> 	 pop bx
   454 0000038E 7203E9D2FE          <1> 	jnc depack.error
   455 00000393 3B5EF2              <1> 	cmp bx, word [bp + ?original_dst + 2]
   456 00000396 7503                <1> 	jne @F
   457 00000398 3B76F0              <1> 	cmp si, word [bp + ?original_dst]
   458                              <1> @@:
   459 0000039B 7303E9C5FE          <1> 	jb depack.error
   460 000003A0 8EDB                <1> 	mov ds, bx
   461 000003A2 59                  <1> 	pop cx
   462 000003A3 5B                  <1> 	pop bx
   463                              <1> @@:
   464 000003A4 294EE4              <1> 	sub word [bp + ?length_of_destination], cx
   465 000003A7 835EE600            <1> 	sbb word [bp + ?length_of_destination + 2], 0
   466 000003AB 7303E9B5FE          <1> 	jb depack.error
   467 000003B0 F3A4                <1>    rep movsb               ; copy match
   468 000003B2 96                  <1>    xchg si,ax              ; restore ds:si
   469 000003B3 1F                  <1>    pop ds
   470                              <1> %if _ALLOW_OVERLAPPING
   471 000003B4 53                  <1> 	push bx
   472 000003B5 85FF                <1> 	test di, di
   473 000003B7 740C                <1> 	jz .zero
   474 000003B9 E83C00              <1> 	call check_pointers_not_overlapping
   475                              <1> .waszero:
   476 000003BC 5B                  <1> 	pop bx
   477 000003BD 7303E9A3FE          <1> 	jc depack.error
   478 000003C2 E9D1FE              <1> 	jmp .decode_token_clear_cx
   479                              <1> 				; go decode another token
   480                              <1> 
   481                              <1> .zero:
   482 000003C5 06                  <1> 	push es
   483 000003C6 8CC3                <1> 	mov bx, es		; => our block
   484 000003C8 81C30010            <1> 	add bx, 1000h		; => next 64 KiB block
   485 000003CC 8EC3                <1> 	mov es, bx		; es:di -> after our block
   486 000003CE E82700              <1> 	call check_pointers_not_overlapping
   487 000003D1 07                  <1> 	pop es
   488 000003D2 EBE8                <1> 	jmp .waszero
   489                              <1> %else
   490                              <1> 	jmp .decode_token
   491                              <1> 				; go decode another token
   492                              <1> %endif
   493                              <1> 
   494                              <1> .end:
   495 000003D4 58                  <1>    pop ax                  ; retrieve the original decompression offset
   496 000003D5 97                  <1>    xchg di,ax              ; compute decompressed size
   497 000003D6 29F8                <1>    sub ax,di
   498 000003D8 C3                  <1>    ret                     ; done
   499                              <1> 
   500                              <1> .get_nibble_x:
   501 000003D9 F5                  <1>    cmc                     ; carry set if bit 4 was set
   502 000003DA D0D8                <1>    rcr al,1
   503 000003DC E80700              <1>    call .get_nibble        ; get nibble for offset bits 0-3
   504 000003DF 08C8                <1>    or al,cl                ; merge nibble
   505 000003E1 D0C0                <1>    rol al,1
   506 000003E3 34E1                <1>    xor al,0E1H             ; set offset bits 7-5 to 1
   507 000003E5 C3                  <1>    ret
   508                              <1> 
   509                              <1> .get_nibble:
   510 000003E6 F6DF                <1>    neg bh                  ; nibble ready?
   511 000003E8 7905                <1>    jns .has_nibble
   512                              <1>    
   513 000003EA 93                  <1>    xchg bx,ax
   514 000003EB E888FE              <1> 	call .lodsb		; load two nibbles
   515 000003EE 93                  <1>    xchg bx,ax
   516                              <1> 
   517                              <1> .has_nibble:
   518 000003EF B104                <1>    mov cl,4                ; swap 4 high and low bits of nibble
   519 000003F1 D2CB                <1>    ror bl,cl
   520 000003F3 B10F                <1>    mov cl,0FH
   521 000003F5 20D9                <1>    and cl,bl
   522 000003F7 C3                  <1>    ret
  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                                  	 push word [bp + ?dst + 2]
  1783                                  	 push word [bp + ?dst]
  1784                                  %else
  1785 000003F8 06                      	 push es
  1786 000003F9 57                      	 push di
  1787                                  %endif
  1788 000003FA E86F00                  	call pointer_to_linear
  1789                                  
  1790 000003FD 91                      	xchg cx, ax
  1791 000003FE 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1792                                  
  1793                                  %if CHECK_POINTERS_VARIABLE_SRC
  1794                                  	 push word [bp + ?src + 2]
  1795                                  	 push word [bp + ?src]
  1796                                  %else
  1797 00000400 1E                      	 push ds
  1798 00000401 56                      	 push si
  1799                                  %endif
  1800 00000402 E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1801                                  
  1802 00000405 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1803 00000407 7502                    	jne @F
  1804 00000409 39C8                    	cmp ax, cx
  1805                                  @@:
  1806                                  					; (CY) if error (src < dst)
  1807                                  					; (NC) if no error
  1808 0000040B 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 0000040C 06                      	 push es
  1824 0000040D 57                      	 push di
  1825 0000040E E80A00                  	call normalise_pointer
  1826 00000411 5F                      	 pop di
  1827 00000412 07                      	 pop es
  1828                                  %endif
  1829                                  
  1830                                  normalise_dssi_pointer:
  1831 00000413 1E                      	 push ds
  1832 00000414 56                      	 push si
  1833 00000415 E80300                  	call normalise_pointer
  1834 00000418 5E                      	 pop si
  1835 00000419 1F                      	 pop ds
  1836 0000041A 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 0000041B 5589E5                  	lenter
  1851                                  
  1852 0000041E 837E040F                	cmp word [bp + ?offset], 15
  1853 00000422 7617                    	jbe .ret
  1854                                  
  1855 00000424 53                      	push bx
  1856 00000425 51                      	push cx
  1857                                  
  1858 00000426 31DB                    	xor bx, bx
  1859 00000428 31C9                    	xor cx, cx
  1860 0000042A FF7606                  	 push word [bp + ?segment]
  1861 0000042D FF7604                  	 push word [bp + ?offset]
  1862 00000430 E80A00                  	call normalise_pointer_with_displacement_bxcx
  1863 00000433 8F4604                  	 pop word [bp + ?offset]
  1864 00000436 8F4606                  	 pop word [bp + ?segment]
  1865                                  
  1866 00000439 59                      	pop cx
  1867 0000043A 5B                      	pop bx
  1868                                  .ret:
  1869 0000043B 5D                      	lleave
  1870 0000043C 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 0000043D 5589E5                  	lenter
  1885                                  
  1886                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1887                                  	cmp word [bp + ?offset], 15
  1888                                  	jbe .ret
  1889                                  %endif
  1890                                  
  1891 00000440 50                      	push ax
  1892 00000441 51                      	push cx
  1893 00000442 52                      	push dx
  1894                                  
  1895 00000443 FF7606                  	 push word [bp + ?segment]
  1896 00000446 FF7604                  	 push word [bp + ?offset]
  1897 00000449 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 0000044C 01C1                    	add cx, ax
  1907 0000044E 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1908                                  	; pop bx
  1909 00000450 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 00000451 53                      	push bx
  1929 00000452 89CB                    	mov bx, cx
  1930 00000454 83E10F                  	and cx, 15
  1931 00000457 894E04                  	mov word [bp + ?offset], cx
  1932                                  
  1933 0000045A B104                    	mov cl, 4
  1934                                  @@:
  1935 0000045C D1EA                    	shr dx, 1
  1936 0000045E D1DB                    	rcr bx, 1
  1937 00000460 E2FA                    	loop @B
  1938                                  
  1939 00000462 895E06                  	mov word [bp + ?segment], bx
  1940 00000465 5B                      	pop bx
  1941                                  
  1942                                  	; test dx, dx
  1943                                  	; jnz .error
  1944                                  
  1945                                  .return:
  1946                                  
  1947                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1948 00000466 9E                      	sahf				; restore flags from ah
  1949                                  %endif
  1950 00000467 5A                      	pop dx
  1951 00000468 59                      	pop cx
  1952 00000469 58                      	pop ax
  1953                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1954                                  .ret:
  1955                                  %endif
  1956 0000046A 5D                      	lleave
  1957 0000046B 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 0000046C 5589E5                  	lenter
  1968                                  
  1969 0000046F 8B4606                  	mov ax, word [bp + ?segment]
  1970 00000472 31D2                    	xor dx, dx
  1971 00000474 51                      	push cx
  1972 00000475 B90400                  	mov cx, 4
  1973                                  @@:
  1974 00000478 D1E0                    	shl ax, 1
  1975 0000047A D1D2                    	rcl dx, 1
  1976 0000047C E2FA                    	loop @B
  1977                                  
  1978 0000047E 034604                  	add ax, word [bp + ?offset]
  1979 00000481 11CA                    	adc dx, cx			; cx = 0 here
  1980 00000483 59                      	pop cx
  1981                                  
  1982 00000484 5D                      	lleave
  1983 00000485 C20400                  	lret
  1984                                  
  1985                                  
  1986                                  %if _PASSLCFG
  1987 00000488 90<rep 8h>              	align 16
  1988                                  transfer_lcfg_block:
  1989 00000490 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: inilzsa2: 1424 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                                  
