     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, "bC"
     3                              <1> %assign _DEVICE 1
     4                              <1> %assign _DEVICE_ZERO_ENTRYPOINT 1
     5                              <1> %assign _DEVICE_ATTRIBUTE 8800h
     6                              <1> %define _DEVICE_NAME "LDEBUG$$"
     7                              <1> %define _PROGRESSVARNAME "LDEBUGPROGRESS"
     8                              <1> %assign _LOADERSUPPORT 1
   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 00000000 EB3E                    	fill 2, -1, jmp strict short j_zero_entrypoint
   192 00000002 FFFF                    	dw -1
   193                                   %else
   194                                  	dd -1				; link to next device
   195                                   %endif
   196                                  .attributes:
   197 00000004 0088                    	dw _DEVICE_ATTRIBUTE		; attributes
   198                                  .strategy:
   199 00000006 [1200]                  	dw .strategy_entry		; -> strategy entry
   200                                  .interrupt:
   201 00000008 [1600]                  	dw .interrupt_entry		; -> interrupt entry
   202                                  .name:
   203 0000000A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME	; character device name,
   204                                  					;  or block device number of units
   205                                  					;  + optional name
   206                                  .strategy_entry:
   207 00000012 EB7C90<rep 2h>          	fill 4, 90h, jmp device_entrypoint
   208                                  .interrupt_entry:
   209 00000016 CB90<rep 3h>            	fill 4, 90h, retf
   210                                  .pass_lcfg:
   211                                  %endif
   212                                  
   213                                  
   214                                  %if _IMAGE_EXE || _DEVICE
   215 0000001A 90                      	nop
   216 0000001B 90<rep 5h>              	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 00000020 31DB                    	xor bx, bx		; 0 = kernel mode
   234 00000022 50                      	push ax
   235 00000023 8CC8                    	mov ax, cs
   236 00000025 83C01F                  	add ax, (init0_end - init0_start) >> 4
   237 00000028 8B56E2                  	mov dx, word [ bp + ldLoadTop ]	; => after end of available space
   238 0000002B BE6000                  	mov si, 60h		; => destination
   239 0000002E EB20                    	jmp init0_common
   240                                  %endif
   241                                  
   242                                   %if _IMAGE_EXE
   243 00000030 90<rep 10h>             	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 00000040 BB0100                  	mov bx, 1		; EXE mode
   262 00000043 50                      	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 00000044 8CD2                    	mov dx, ss		; => after end of available space
   328 00000046 8CC8                    	mov ax, cs
   329 00000048 83C02F                  	add ax, (256 + (init0_end - init0_start)) >> 4	; => source
   330 0000004B 8CCE                    	mov si, cs
   331 0000004D 83C610                  	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 00000050 FC                      	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 00000051 B94E15                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   367                                  				; cx = amount paragraphs in INIT0B + payload + INIT1
   368 00000054 29CA                    	sub dx, cx		; => destination for INIT0B + payload + INIT1
   369                                  				;  (highest possible spot in available memory)
   370                                  %endif
   371 00000056 56                      	push si			; preserve destination
   372 00000057 E80701                  	call init0_movp		; move up payload + INIT1
   373 0000005A 5E                      	pop si
   374                                  %else
   375                                  	cld
   376                                  	mov ax, cs
   377                                  	add ax, (init0_end - init0_start) >> 4
   378                                  	mov cx, ( 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		) >> 4
   383                                  	mov dx, word [ bp + ldLoadTop ]
   384                                  	sub dx, cx
   385                                  	call init0_movp
   386                                  %endif
   387                                  
   388                                  %if _LCFG && ! _TEST_PROGRAM
   389 0000005B 0E                      	push cs
   390 0000005C E80000                  	call @F			; position-independent far pointer
   391                                  @@:
   392 0000005F 58                      	pop ax
   393 00000060 83C011                  	add ax, lcfg - @B	; -> lCFG block
   394 00000063 50                      	push ax
   395                                  %endif
   396                                  
   397 00000064 89D0                    	mov ax, dx		; => INIT0B
   398                                  				;  (same as => payload if INIT0B is empty)
   399                                  %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM
   400 00000066 83C211                  	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 00000069 31C9                    	xor cx, cx
   418 0000006B 50                      	push ax
   419 0000006C 51                      	push cx
   420 0000006D 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 0000006E 90<rep 2h>              	align 16
   474                                  lcfg:
   475 00000070 EB1E                    .:		jmp strict short .end
   476 00000072 6C434647                lcfgoption 2,,	db "lCFG"
   477 00000076 3030                    lcfgoption 6,,	db "00"
   478 00000078 FCFF070000000000        lcfgoption 8,,	dq .inuse
   479                                   %if _PROGRESS && _PROGRESSMULTI
   480                                    %if _IMAGE_EXE
   481 00000080 00                      lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP
   482                                    %endif
   483                                    %if _DEVICE
   484 00000081 00                      lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE
   485                                    %endif
   486                                    %if _BOOTLDR
   487 00000082 01                      lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT
   488                                    %endif
   489                                   %endif
   490                                  
   491                                  %ifnidn _LCFG_CFG, ""
   492                                   %include _LCFG_CFG
   493                                  %endif
   494                                  
   495 00000083 00<rep Dh>              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 00000090 26807F0200              	cmp byte [es:bx + 2], 0		; command code 0 (init) ?
   512 00000095 7407                    	je @F
   513                                  
   514 00000097 26C747030381            	mov word [es:bx + 3], 8103h	; error, done, code: unknown command
   515 0000009D CB                      	retf
   516                                  
   517                                  @@:
   518 0000009E 2E830E[0000]FF          	or word [cs:device_header.next], -1
   519 000000A4 0E                      	push cs
   520 000000A5 2EFF36[0600]            	push word [cs:device_header.strategy]
   521                                  					; -> far return to payload's strategy
   522 000000AA 55                      	push bp
   523 000000AB 1E                      	push ds
   524 000000AC 56                      	push si
   525 000000AD 57                      	push di
   526 000000AE 52                      	push dx
   527 000000AF 51                      	push cx
   528 000000B0 50                      	push ax
   529 000000B1 53                      	push bx
   530 000000B2 06                      	push es
   531                                  
   532 000000B3 268B570E                	mov dx, word [es:bx + 14]
   533 000000B7 B104                    	mov cl, 4
   534 000000B9 D3EA                    	shr dx, cl		; = how many full paragraphs (rounded down)
   535 000000BB 26035710                	add dx, word [es:bx + 14 + 2]
   536                                  				; ax => behind end
   537                                  
   538 000000BF 8CCF                    	mov di, cs
   539                                  image_size: equ  ( 		+ (init0_end - init0_start) 		+ (init0b_end - init0b_start) 		+ (payload_end - payload) 		+ (init1_end - init1_start) 		)
   545 000000C1 81C76D15                	add di, image_size >> 4		; di => end of image
   546                                  
   547 000000C5 39FA                    	cmp dx, di			; enough memory to hold all of us ?
   548 000000C7 720E                    	jb @F				; no -->
   549                                  				; yes
   550                                  .have_some_memory:
   551                                  				; dx => after end of memory
   552 000000C9 BB0200                  	mov bx, 2		; device mode
   553 000000CC 50                      	push ax
   554 000000CD 8CC8                    	mov ax, cs
   555 000000CF 83C01F                  	add ax, (init0_end - init0_start) >> 4
   556 000000D2 8CCE                    	mov si, cs		; => destination
   557 000000D4 E979FF                  	jmp init0_common
   558                                  
   559                                  
   560                                  @@:
   561 000000D7 0E                      	push cs
   562 000000D8 1F                      	pop ds
   563 000000D9 BA[1801]                	mov dx, .msg_no_memory
   564 000000DC B409                    	mov ah, 09h
   565 000000DE CD21                    	int 21h
   566                                  
   567 000000E0 B80030                  	mov ax, 3000h
   568 000000E3 CD21                    	int 21h
   569 000000E5 3C05                    	cmp al, 5
   570 000000E7 7307                    	jae @F
   571 000000E9 BA[3701]                	mov dx, .msg_dos_below_5
   572 000000EC B409                    	mov ah, 09h
   573 000000EE CD21                    	int 21h
   574                                  @@:
   575                                  
   576 000000F0 BA[5E01]                	mov dx, .msg_linebreak
   577 000000F3 B409                    	mov ah, 09h
   578 000000F5 CD21                    	int 21h
   579                                  
   580                                  		; tear down the stack frame and modify the request header
   581 000000F7 07                      	pop es
   582 000000F8 5B                      	pop bx
   583 000000F9 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
   584 000000FF 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
   585 00000104 268C4F10                	mov word [es:bx + 14 + 2], cs
   586 00000108 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
   587 0000010D 58                      	pop ax
   588 0000010E 59                      	pop cx
   589 0000010F 5A                      	pop dx
   590 00000110 5F                      	pop di
   591 00000111 5E                      	pop si
   592 00000112 1F                      	pop ds
   593 00000113 5D                      	pop bp
   594 00000114 83C404                  	add sp, 4		; discard far return to payload's strategy
   595 00000117 CB                      	retf			; return to DOS
   596                                  
   597                                  
   598 00000118 4C6F6164206572726F-     .msg_no_memory:		ascic "Load error: Not enough memory."
   598 00000121 723A204E6F7420656E-
   598 0000012A 6F756768206D656D6F-
   598 00000133 72792E24           
   599 00000137 204E6F74653A20444F-     .msg_dos_below_5:	ascic " Note: DOS must be at least version 5."
   599 00000140 53206D757374206265-
   599 00000149 206174206C65617374-
   599 00000152 2076657273696F6E20-
   599 0000015B 352E24             
   600 0000015E 0D0A24                  .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 00000161 39D0                    	cmp ax, dx		; source above destination ?
   615 00000163 770A                    	ja .up			; yes, move up (forwards) -->
   616 00000165 747B                    	je .return		; same, no need to move -->
   617 00000167 50                      	push ax
   618 00000168 01C8                    	add ax, cx		; (expected not to carry)
   619 0000016A 39D0                    	cmp ax, dx		; end of source is above destination ?
   620 0000016C 58                      	pop ax
   621 0000016D 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 0000016F 50                      	push ax
   627 00000170 52                      	push dx
   628                                  .uploop:
   629 00000171 8ED8                    	mov ds, ax
   630 00000173 8EC2                    	mov es, dx
   631 00000175 31FF                    	xor di, di
   632 00000177 31F6                    	xor si, si		; -> start of segment
   633 00000179 81E90010                	sub cx, 1000h		; 64 KiB left ?
   634 0000017D 7610                    	jbe .uplast		; no -->
   635 0000017F 51                      	push cx
   636 00000180 B90080                  	mov cx, 10000h /2
   637 00000183 F3A5                    	rep movsw		; move 64 KiB
   638 00000185 59                      	pop cx
   639 00000186 050010                  	add ax, 1000h
   640 00000189 81C20010                	add dx, 1000h		; -> next segment
   641 0000018D EBE2                    	jmp short .uploop	; proceed for more -->
   642                                  .uplast:
   643 0000018F 81C10010                	add cx, 1000h		; restore counter
   644 00000193 D1E1                    	shl cx, 1
   645 00000195 D1E1                    	shl cx, 1
   646 00000197 D1E1                    	shl cx, 1		; *8, paragraphs to words
   647 00000199 F3A5                    	rep movsw		; move last part
   648 0000019B 5A                      	pop dx
   649 0000019C 58                      	pop ax
   650 0000019D EB43                    	jmp short .return
   651                                  
   652                                  .down:
   653 0000019F FD                      	std			; _AMD_ERRATUM_109_WORKAROUND as below
   654                                  .dnloop:
   655 000001A0 81E90010                	sub cx, 1000h		; 64 KiB left ?
   656 000001A4 761A                    	jbe .dnlast		; no -->
   657 000001A6 50                      	push ax
   658 000001A7 52                      	push dx
   659 000001A8 01C8                    	add ax, cx
   660 000001AA 01CA                    	add dx, cx
   661 000001AC 8ED8                    	mov ds, ax		; -> 64 KiB not yet moved
   662 000001AE 8EC2                    	mov es, dx
   663 000001B0 5A                      	pop dx
   664 000001B1 58                      	pop ax
   665 000001B2 BFFEFF                  	mov di, -2
   666 000001B5 89FE                    	mov si, di		; moved from last word down
   667 000001B7 51                      	push cx
   668 000001B8 B90080                  	mov cx, 10000h /2
   669 000001BB F3A5                    	rep movsw		; move 64 KiB
   670 000001BD 59                      	pop cx
   671 000001BE EBE0                    	jmp short .dnloop	; proceed for more -->
   672                                  .dnlast:
   673 000001C0 81C10010                	add cx, 1000h		; restore counter
   674 000001C4 D1E1                    	shl cx, 1
   675 000001C6 D1E1                    	shl cx, 1
   676 000001C8 D1E1                    	shl cx, 1		; *8, paragraphs to words
   677 000001CA 89CF                    	mov di, cx
   678 000001CC 4F                      	dec di
   679 000001CD D1E7                    	shl di, 1		; words to offset, -> last word
   680 000001CF 89FE                    	mov si, di
   681 000001D1 8ED8                    	mov ds, ax
   682 000001D3 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 000001D5 E308                    	jcxz @FF
   723 000001D7 83F914                  	cmp cx, 20
   724 000001DA 7703                    	ja @FF
   725                                  @@:
   726 000001DC A5                      	movsw
   727 000001DD E2FD                    	loop @B
   728                                  @@:
   729                                  %endif
   730 000001DF F3A5                    	rep movsw		; move first part
   731 000001E1 FC                      	cld
   732                                  .return:
   733 000001E2 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 05FA14                  	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                                  	pop si
   757                                  	pop ds			; -> lCFG block
   758                                  	mov es, ax
   759                                  	mov di, transfer_lcfg_block
   760                                  				; -> destination
   761                                   %if (_IMAGE_EXE || _DEVICE)
   762                                  	push cx
   763                                   %endif
   764                                  	push di
   765                                  	mov cx, words(lcfg.size)
   766                                  	rep movsw		; cx = 0
   767                                  	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 00000003 5F                      	pop di
   773 00000004 07                      	pop es			; es:di -> (original) lCFG block
   774                                  %endif
   775                                  
   776 00000005 50                      	push ax
   777 00000006 51                      	push cx			; -> far return address to init1_start
   778                                  
   779                                  %if _PROGRESS && _PROGRESSMULTI
   780                                   %if (_IMAGE_EXE || _DEVICE)
   781 00000007 56                      	push si
   782 00000008 53                      	push bx
   783                                   %endif
   784                                   %if _BOOTLDR
   785                                    %if _LCFG
   786 00000009 31C0                    	xor ax, ax
   787 0000000B 268A4512                	mov al, byte [es:di + lcfg.progress_boot - lcfg]
   788 0000000F 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 00000010 85DB                    	test bx, bx
   797 00000012 7503E9AC00              	jz .default
   798                                    %endif		; _BOOTLDR
   799                                    %if _LCFG
   800 00000017 06                      	push es
   801                                     %if _BOOTLDR
   802 00000018 50                      	push ax			; -> lCFG block
   803                                     %else		; _BOOTLDR
   804                                  	push di
   805                                     %endif		; _BOOTLDR
   806                                    %endif		; _LCFG
   807                                    %if _PROGRESSVAR
   808 00000019 B451                    	mov ah, 51h
   809 0000001B CD21                    	int 21h
   810                                  @@:
   811 0000001D 8EDB                    	mov ds, bx
   812 0000001F A12C00                  	mov ax, word [2Ch]
   813 00000022 85C0                    	test ax, ax
   814 00000024 7510                    	jnz .gotenv
   815 00000026 A11600                  	mov ax, word [16h]
   816 00000029 40                      	inc ax
   817 0000002A 7469                    	jz .default_nonboot
   818 0000002C 48                      	dec ax
   819 0000002D 7466                    	jz .default_nonboot
   820 0000002F 39C3                    	cmp bx, ax
   821 00000031 7462                    	je .default_nonboot
   822 00000033 93                      	xchg bx, ax
   823 00000034 EBE7                    	jmp @B
   824                                  
   825                                  .gotenv:
   826 00000036 0E                      	push cs
   827 00000037 1F                      	pop ds				; => cs
   828 00000038 8EC0                    	mov es, ax			; => environment
   829                                   %ifnidni _PROGRESSVARNAME, ""
   830 0000003A BB[F000]                	mov bx, progressvarname1
   831 0000003D E80C00                  	call .findenv
   832 00000040 732E                    	jnc .foundenv			; match -->
   833 00000042 BB[0001]                	mov bx, progressvarname2
   834                                   %endif
   835 00000045 E80400                  	call .findenv
   836 00000048 7326                    	jnc .foundenv			; match -->
   837 0000004A EB49                    	jmp .default_nonboot
   838                                  
   839                                  .findenv:
   840 0000004C 31FF                    	xor di, di
   841                                  @@:
   842                                   %ifnidni _PROGRESSVARNAME, ""
   843 0000004E 89DE                    	mov si, bx			; -> variable name
   844                                   %else
   845                                  	mov si, progressvarname2	; -> variable name
   846                                   %endif
   847 00000050 31C0                    	xor ax, ax
   848 00000052 AC                      	lodsb				; get length
   849 00000053 91                      	xchg cx, ax			; cx = length
   850 00000054 57                      	push di
   851 00000055 F3A6                    	repe cmpsb			; match ?
   852 00000057 7415                    	je .findret_pop			; (NC) yes -->
   853 00000059 5F                      	pop di
   854 0000005A B90080                  	mov cx, 8000h			; maximum env size
   855 0000005D 29F9                    	sub cx, di			; any left ?
   856 0000005F 760B                    	jbe .findret_CY			; no -->
   857 00000061 B000                    	mov al, 0
   858 00000063 F2AE                    	repne scasb			; find next NUL
   859 00000065 7505                    	jne .findret_CY
   860 00000067 263805                  	cmp byte [es:di], al		; double NUL ?
   861 0000006A 75E2                    	jne @B				; no, loop -->
   862                                  .findret_CY:
   863 0000006C F9                      	stc				; not found
   864 0000006D C3                      	retn
   865                                  
   866                                  .findret_pop:
   867 0000006E 59                      	pop cx
   868 0000006F C3                      	retn
   869                                  
   870                                  .foundenv:
   871                                  %if _LCFG
   872 00000070 5E                      	pop si
   873 00000071 5E                      	pop si				; discard far pointer to lCFG
   874                                  %endif
   875 00000072 89FE                    	mov si, di			; es:si -> var content
   876 00000074 31FF                    	xor di, di			; = 0
   877 00000076 31C0                    	xor ax, ax			; ah = 0
   878                                  @@:
   879 00000078 26AC                    	es lodsb			; next candidate digit
   880 0000007A 2C30                    	sub al, '0'			; digit ?
   881 0000007C 7212                    	jb @F				; no -->
   882 0000007E 3C09                    	cmp al, 9
   883 00000080 770E                    	ja @F				; no -->
   884 00000082 01FF                    	add di, di			; times 2
   885 00000084 89FB                    	mov bx, di
   886 00000086 01FF                    	add di, di			; times 4
   887 00000088 01FF                    	add di, di			; times 8
   888 0000008A 01DF                    	add di, bx			; times 8 + times 2 = times 10
   889 0000008C 01C7                    	add di, ax			; add in next digit
   890 0000008E EBE8                    	jmp @B				; and loop
   891                                  
   892                                  @@:
   893 00000090 83E71F                  	and di, 31			; mask to low 5 bits
   894 00000093 EB10                    	jmp @F
   895                                    %endif	; _PROGRESSVAR
   896                                  
   897                                  .default_nonboot:
   898                                  %if _LCFG
   899 00000095 5F                      	pop di
   900 00000096 07                      	pop es			; -> lCFG block
   901 00000097 5B                      	pop bx			; = 1 if app, = 2 if device
   902 00000098 53                      	push bx
   903 00000099 268B4510                	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 0000009D 4B                      	dec bx
   910 0000009E 7402                    	jz .default_app
   911 000000A0 86C4                    	xchg al, ah		; al = device
   912                                  .default_app:
   913                                   %endif			; _DEVICE
   914 000000A2 B400                    	mov ah, 0		; ax = default
   915 000000A4 97                      	xchg di, ax		; di = default
   916                                  %else			; _LCFG
   917                                  	mov di, _PROGRESSDEFAULT
   918                                  %endif			; _LCFG
   919                                  @@:
   920 000000A5 F7C71000                	test di, 16
   921 000000A9 7405                    	jz @F
   922 000000AB 83E7EF                  	and di, ~16
   923 000000AE EB13                    	jmp .outputdevice	; if 16 set skip device check
   924                                  @@:
   925 000000B0 52                      	push dx
   926 000000B1 B80044                  	mov ax, 4400h		; IOCTL get device information
   927 000000B4 BB0100                  	mov bx, 1		; StdOut
   928 000000B7 B283                    	mov dl, 83h		; default if 21.4400 fails
   929 000000B9 CD21                    	int 21h
   930 000000BB F6C280                  	test dl, 80h
   931 000000BE 5A                      	pop dx
   932 000000BF 7502                    	jnz .outputdevice
   933 000000C1 31FF                    	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 000000C3 5B                      	pop bx
   940 000000C4 5E                      	pop si
   941                                   %endif
   942 000000C5 83FF05                  	cmp di, step_progress_table.amount
   943                                  					; valid ?
   944 000000C8 7202                    	jb @F				; yes -->
   945 000000CA 31FF                    	xor di, di			; disable
   946                                  @@:
   947 000000CC D1E7                    	shl di, 1			; = word index
   948 000000CE 59                      	pop cx				; = 0
   949 000000CF 1F                      	pop ds				; ds => INIT1
   950                                  
   951 000000D0 2E8B85[E600]            	mov ax, word [cs:step_progress_table + di]
   952                                  					; ax = rel16 for step progress handler
   953 000000D5 1E                      	push ds
   954 000000D6 51                      	push cx				; -> init1_start
   955 000000D7 A3[BA00]                	mov word [step_progress.handler], ax
   956                                  					; patch it
   957                                  
   958 000000DA 83FF04                  	cmp di, 2 * 2			; none or dots ?
   959 000000DD 7305                    	jae @F				; no, skip -->
   960 000000DF C606[0600]A9            	mov byte [..@empty_step_progress], __TEST_IMM16
   961                                  					; for none and dots do not call here
   962                                  @@:
   963                                  %endif			;  _PROGRESS && _PROGRESSMULTI
   964 000000E4 CB                      	retf
   965                                  %endif
   966                                  
   967                                  %if _PROGRESS && _PROGRESSMULTI
   968 000000E5 00                      		align 2, db 0
   969                                  step_progress_table:
   970                                  .:
   971 000000E6 1600                    		dw step_progress.0_step - step_progress.base
   972 000000E8 3B00                    		dw step_progress.1_step - step_progress.base
   973 000000EA 0000                    		dw step_progress.2_step - step_progress.base
   974 000000EC 4100                    		dw step_progress.3_step - step_progress.base
   975 000000EE 8600                    		dw step_progress.4_step - step_progress.base
   976                                  .amount equ ($ - .) / 2
   977                                  
   978                                   %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE)
   979                                    %ifnidni _PROGRESSVARNAME, ""
   980 000000F0 0F4C44454255475052-     progressvarname1:	counted _PROGRESSVARNAME, '='
   980 000000F9 4F47524553533D     
   981                                    %endif
   982 00000100 0D4C444F5350524F47-     progressvarname2:	counted "LDOSPROGRESS="
   982 00000109 524553533D         
   983                                   %endif
   984                                  %endif
   985                                  
   986 0000010E 90<rep 2h>              	align 16
   987                                  init0b_end:
   988                                  
   989                                  
   990                                  	addsection PAYLOAD, align=16 follows=INIT0B
   991                                  payload:
   992 00000000 <bin 14E89h>            	incbin _PAYLOAD_FILE
   993                                  .end:
   994 00014E89 26<rep 7h>              	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
  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 00000000 5589E5                  	lenter
  1037                                  	lvar word,	exemode		; must be bp - 2!
  1038 00000003 53                      	 push bx
  1039                                   %if ?exemode != -2
  1040                                    %error exemode variable must be directly below bp
  1041                                   %endif
  1042 00000004 56                      	push si
  1043                                   %if _PROGRESS
  1044 00000005 F8                      	clc			; NC
  1045                                   %endif
  1046                                  %else
  1047                                  	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 00000006 E89F00                  	call step_progress.CF	; display empty / 0.0%
  1057                                   %endif
  1058                                  @@:
  1059                                  %endif
  1060                                  
  1061                                  %if _IMAGE_EXE || _DEVICE
  1062 00000009 8EC6                    	mov es, si		; es => destination
  1063                                  %else
  1064                                  	mov ax, 60h
  1065                                  	mov es, ax		; es => destination
  1066                                  %endif
  1067 0000000B 31FF                    	xor di, di		; -> destination
  1068                                  
  1069 0000000D 8EDA                    	mov ds, dx
  1070 0000000F 31F6                    	xor si, si		; -> source
  1071                                  
  1072 00000011 B9894E                  	mov cx, (payload.end - payload) & 0FFFFh
  1073                                  %if (payload.end - payload) >> 16
  1074 00000014 BA0100                  	mov dx, (payload.end - payload) >> 16	; = length of source
  1075                                  %else
  1076                                  	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 00000017 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 0000001A E85602                  	call depack
  1099                                  %ifn _TEST_PROGRAM
  1100 0000001D 7234                    	jc strict short error	; -2 (replaced by retf \ nop)
  1101                                  %endif
  1102                                  %if _IMAGE_EXE || _DEVICE
  1103 0000001F 5E                      	pop si			; si
  1104                                   %if _TEST_PROGRAM
  1105                                  	pop ax			; (discard ?exemode, leave bx as returned)
  1106                                   %else
  1107 00000020 5B                      	pop bx			; ?exemode
  1108                                   %endif
  1109 00000021 5D                      	pop bp			; bp
  1110 00000022 58                      	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 00000023 F6C302                  	test bl, 2
  1120 00000026 7411                    	jz .jmp_exe_or_kernel_mode
  1121                                  
  1122                                  .jmp_device_mode:
  1123 00000028 8EDE                    	mov ds, si
  1124 0000002A 830E[0000]FF            	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 0000002F 07                      	pop es
  1130 00000030 5B                      	pop bx
  1131 00000031 58                      	pop ax
  1132 00000032 59                      	pop cx
  1133 00000033 5A                      	pop dx
  1134 00000034 5F                      	pop di
  1135 00000035 5E                      	pop si
  1136 00000036 1F                      	pop ds
  1137 00000037 5D                      	pop bp
  1138 00000038 CB                      	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 00000039 F6C301                  	test bl, 1
  1146 0000003C 7410                    	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 0000003E 31C9                    	xor cx, cx
  1175 00000040 51                      	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 00000041 B94001                  	mov cx, _IMAGE_EXE_IP
  1183                                  %endif
  1184                                  
  1185                                  %if _IMAGE_EXE_CS == -16
  1186 00000044 83C6F0                  	add si, -16
  1187 00000047 8EDE                    	mov ds, si
  1188 00000049 8EC6                    	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 0000004B 56                      	push si
  1198 0000004C 51                      	push cx
  1199                                  %if _LCFG && _PASSLCFG
  1200                                  	mov di, transfer_lcfg_block
  1201                                  	mov cx, cs
  1202                                  %endif
  1203 0000004D CB                      	retf			; jump to EXE mode of image
  1204                                  
  1205                                  %endif
  1206                                  .jmp_kernel_mode:
  1207                                  %if _LCFG && _PASSLCFG
  1208                                  	mov di, transfer_lcfg_block
  1209                                  	mov cx, cs
  1210                                  %endif
  1211 0000004E EA20006000              	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 00000053 0E                      	push cs
  1232 00000054 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 00000055 BE[4E02]                	mov si, msg.error
  1245                                   %endif
  1246                                  %endif
  1247                                   %ifn _TEST_PROGRAM		; 3 bytes, total 2 + 3 + 3 = 8
  1248 00000058 E8C901                  	call disp_error
  1249                                   %endif
  1250                                  %if _DEVICE
  1251 0000005B F646FE02                	test byte [bp - 2], 2
  1252 0000005F 7435                    	jz .exit_app_or_kernel
  1253                                  
  1254 00000061 5E                      	pop si				; => device segment
  1255 00000062 5B                      	pop bx				; mode word
  1256 00000063 5D                      	pop bp
  1257 00000064 58                      	pop ax
  1258 00000065 8EC6                    	mov es, si
  1259 00000067 31FF                    	xor di, di			; -> device header
  1260 00000069 0E                      	 push cs
  1261 0000006A 1F                      	 pop ds
  1262 0000006B BE[0002]                	mov si, device_header_copy	; -> to reset header
  1263 0000006E B91100                  	mov cx, words(device_header_copy.length)
  1264 00000071 F3A5                    	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 00000073 06                      	 push es
  1269 00000074 1F                      	 pop ds				; -> device segment
  1270 00000075 07                      	pop es
  1271 00000076 5B                      	pop bx
  1272 00000077 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1273 0000007D 26C6470D00              	mov byte [es:bx + 13], 0	; set number of units = 0
  1274 00000082 268C5F10                	mov word [es:bx + 14 + 2], ds
  1275 00000086 2683670E00              	and word [es:bx + 14], 0	; -> after end of memory to allocate
  1276 0000008B 58                      	pop ax
  1277 0000008C 59                      	pop cx
  1278 0000008D 5A                      	pop dx
  1279 0000008E 5F                      	pop di
  1280 0000008F 5E                      	pop si
  1281 00000090 1F                      	pop ds
  1282 00000091 5D                      	pop bp
  1283 00000092 83C404                  	add sp, 4		; discard far return to payload's strategy
  1284 00000095 CB                      	retf			; return to DOS
  1285                                  
  1286                                  
  1287                                  .exit_app_or_kernel:
  1288                                  %endif
  1289                                  
  1290                                  %if _IMAGE_EXE
  1291                                  %if _BOOTLDR
  1292 00000096 F646FE01                	test byte [bp - 2], 1
  1293 0000009A 7405                    	jz .exit_kernel_mode
  1294                                  %endif
  1295                                  
  1296 0000009C B87F4C                  	mov ax, 4C7Fh
  1297 0000009F CD21                    	int 21h
  1298                                  
  1299                                  .exit_kernel_mode:
  1300                                  %endif
  1301                                  %if _BOOTLDR
  1302 000000A1 31C0                    	xor ax, ax
  1303 000000A3 CD16                    	int 16h
  1304 000000A5 CD19                    	int 19h
  1305                                  %endif
  1306                                  
  1307                                  
  1308                                  %if _PROGRESS
  1309                                  step_progress:
  1310 000000A7 F9                      	stc
  1311                                  .CF:
  1312 000000A8 53                      	push bx
  1313 000000A9 51                      	push cx
  1314 000000AA 52                      	push dx
  1315 000000AB 1E                      	push ds
  1316 000000AC 56                      	push si
  1317 000000AD 57                      	push di
  1318 000000AE 50                      	push ax
  1319                                  
  1320 000000AF 0E                      	push cs
  1321 000000B0 1F                      	pop ds
  1322                                  
  1323 000000B1 8316[E201]00            	adc word [.counter], 0
  1324 000000B6 A1[E201]                	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 000000B9 E91600                  	jmp strict near . %+ defaultprogresshandler %+ _step
  1333                                  .handler: equ $ - 2		; SMC, patched to dispatch to handler
  1334                                  .base:
  1335                                   %endif
  1336                                  
  1337                                  .2_step:
  1338 000000BC BAE803                  	mov dx, 1000
  1339 000000BF F7E2                    	mul dx			; dx:ax = counter times 1000
  1340                                  %if _PROGRESSAMOUNT
  1341 000000C1 B9E400                  	mov cx, _PROGRESSAMOUNT
  1342 000000C4 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 000000C6 BE[EB01]                	mov si, .message_number_end - 1
  1354 000000C9 E80E00                  	call .format_percentage
  1355                                  
  1356 000000CC BE[E401]                	mov si, .message
  1357 000000CF E85201                  	call disp_error
  1358                                  
  1359                                  .ret:
  1360 000000D2 58                      	pop ax
  1361                                  .ret_ax:
  1362 000000D3 5F                      	pop di
  1363 000000D4 5E                      	pop si
  1364 000000D5 1F                      	pop ds
  1365 000000D6 5A                      	pop dx
  1366 000000D7 59                      	pop cx
  1367 000000D8 5B                      	pop bx
  1368                                  .retn:
  1369 000000D9 C3                      	retn
  1370                                  
  1371                                  
  1372                                  .format_percentage:
  1373 000000DA BB0200                  	mov bx, 2		; skip dot
  1374                                  
  1375 000000DD B90A00                  	mov cx, 10		; base
  1376                                  @@:
  1377 000000E0 31D2                    	xor dx, dx		; dx:ax = current number
  1378 000000E2 F7F1                    	div cx			; dl = remainder, ax = next number
  1379 000000E4 80C230                  	add dl, '0'		; make decit
  1380 000000E7 8814                    	mov byte [si], dl	; store
  1381 000000E9 29DE                    	sub si, bx		; -> next digit slot
  1382 000000EB 80FB02                  	cmp bl, 2		; did we just store fractional ?
  1383 000000EE B301                    	mov bl, 1		; ! next iteration do not skip dot
  1384 000000F0 74EE                    	je @B			; yes, loop always -->
  1385 000000F2 85C0                    	test ax, ax		; nonzero left ?
  1386 000000F4 75EA                    	jnz @B			; yes, loop if so -->
  1387 000000F6 C3                      	retn
  1388                                  
  1389                                  
  1390                                   %if _PROGRESSMULTI
  1391                                  .0_step: equ .ret
  1392                                  
  1393                                  .1_step:
  1394 000000F7 58                      	pop ax
  1395 000000F8 E83701                  	call disp_al
  1396 000000FB EBD6                    	jmp .ret_ax
  1397                                  
  1398                                  .3_step:
  1399 000000FD BB4B00                  	mov bx, 80 - 1 - 4
  1400 00000100 F7E3                    	mul bx			; dx:ax = counter times 75
  1401                                  %if _PROGRESSAMOUNT
  1402 00000102 B9E400                  	mov cx, _PROGRESSAMOUNT
  1403 00000105 F7F1                    	div cx			; ax = 0..75
  1404                                  %else
  1405                                   %warning Progress amount is zero
  1406                                  	mov ax, 1
  1407                                  %endif
  1408                                  
  1409 00000107 3906[E001]              	cmp word [.display], ax
  1410 0000010B 74C5                    	je .ret
  1411 0000010D A3[E001]                	mov word [.display], ax
  1412                                  
  1413 00000110 50                      	push ax
  1414 00000111 91                      	xchg cx, ax
  1415 00000112 B00D                    	mov al, 13
  1416 00000114 E81B01                  	call disp_al
  1417 00000117 B05B                    	mov al, '['
  1418 00000119 E81601                  	call disp_al
  1419 0000011C B020                    	mov al, 32
  1420 0000011E E81101                  	call disp_al
  1421                                  
  1422 00000121 B023                    	mov al, '#'
  1423 00000123 E305                    	jcxz @FF
  1424                                  @@:
  1425 00000125 E80A01                  	call disp_al
  1426 00000128 E2FB                    	loop @B
  1427                                  @@:
  1428                                  
  1429 0000012A B020                    	mov al, 32
  1430 0000012C 59                      	pop cx
  1431 0000012D 29CB                    	sub bx, cx
  1432 0000012F 7607                    	jbe @FF
  1433 00000131 89D9                    	mov cx, bx
  1434                                  @@:
  1435 00000133 E8FC00                  	call disp_al
  1436 00000136 E2FB                    	loop @B
  1437                                  @@:
  1438                                  
  1439                                  .m4done:
  1440 00000138 E8F700                  	call disp_al
  1441 0000013B B05D                    	mov al, ']'
  1442 0000013D E8F200                  	call disp_al
  1443 00000140 EB90                    	jmp .ret
  1444                                  
  1445                                  
  1446                                  .4_step:
  1447 00000142 50                      	push ax
  1448                                  
  1449 00000143 BAE803                  	mov dx, 1000
  1450 00000146 F7E2                    	mul dx			; dx:ax = counter times 1000
  1451                                  %if _PROGRESSAMOUNT
  1452 00000148 B9E400                  	mov cx, _PROGRESSAMOUNT
  1453 0000014B F7F1                    	div cx			; ax = 0..1000
  1454                                  %else
  1455                                   %warning Progress amount is zero
  1456                                  	mov ax, 1
  1457                                  %endif
  1458                                  
  1459 0000014D BE[F501]                	mov si, .message_4_number_end - 1
  1460 00000150 E887FF                  	call .format_percentage
  1461                                  
  1462 00000153 58                      	pop ax
  1463 00000154 BB4B00                  	mov bx, 80 - 1 - 4
  1464 00000157 F7E3                    	mul bx			; dx:ax = counter times 75
  1465                                  %if _PROGRESSAMOUNT
  1466 00000159 B9E400                  	mov cx, _PROGRESSAMOUNT
  1467 0000015C F7F1                    	div cx			; ax = 0..75
  1468                                  %else
  1469                                   %warning Progress amount is zero
  1470                                  	mov ax, 1
  1471                                  %endif
  1472                                  
  1473 0000015E 50                      	push ax
  1474 0000015F 91                      	xchg cx, ax
  1475 00000160 B00D                    	mov al, 13
  1476 00000162 E8CD00                  	call disp_al
  1477 00000165 B05B                    	mov al, '['
  1478 00000167 E8C800                  	call disp_al
  1479 0000016A B020                    	mov al, 32
  1480 0000016C E8C300                  	call disp_al
  1481                                  
  1482 0000016F 31FF                    	xor di, di
  1483 00000171 BA2200                  	mov dx, (80 - 1 - 4 - .message_4_length) / 2
  1484 00000174 803E[F101]20            	cmp byte [.message_4_number], 32
  1485 00000179 7401                    	je @F
  1486 0000017B 47                      	inc di
  1487                                  @@:
  1488 0000017C 29FA                    	sub dx, di
  1489                                  
  1490 0000017E B023                    	mov al, '#'
  1491 00000180 E306                    	jcxz @FF
  1492                                  @@:
  1493 00000182 E8AD00                  	call disp_al
  1494 00000185 4A                      	dec dx
  1495 00000186 E0FA                    	loopnz @B
  1496                                  @@:
  1497                                  
  1498 00000188 85D2                    	test dx, dx
  1499 0000018A 752E                    	jnz .notyetm4
  1500                                  
  1501 0000018C BE[F101]                	mov si, .message_4
  1502 0000018F 29FE                    	sub si, di
  1503 00000191 E89000                  	call disp_error
  1504                                  
  1505 00000194 29F9                    	sub cx, di
  1506 00000196 760E                    	jbe @FF
  1507 00000198 83E907                  	sub cx, .message_4_length
  1508 0000019B 7609                    	jbe @FF
  1509 0000019D 89CA                    	mov dx, cx
  1510 0000019F B023                    	mov al, '#'
  1511                                  @@:
  1512 000001A1 E88E00                  	call disp_al
  1513 000001A4 E2FB                    	loop @B
  1514                                  @@:
  1515 000001A6 59                      	pop cx
  1516 000001A7 B020                    	mov al, 32
  1517 000001A9 83EB29                  	sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length
  1518 000001AC 29D3                    	sub bx, dx
  1519 000001AE 7607                    	jbe @FF
  1520 000001B0 89D9                    	mov cx, bx
  1521                                  @@:
  1522 000001B2 E87D00                  	call disp_al
  1523 000001B5 E2FB                    	loop @B
  1524                                  @@:
  1525 000001B7 E97EFF                  	jmp .m4done
  1526                                  
  1527                                  .notyetm4:
  1528 000001BA B020                    	mov al, 32
  1529 000001BC 59                      	pop cx
  1530 000001BD 29CB                    	sub bx, cx
  1531 000001BF 7608                    	jbe @FF
  1532 000001C1 89D9                    	mov cx, bx
  1533                                  @@:
  1534 000001C3 E86C00                  	call disp_al
  1535 000001C6 4A                      	dec dx
  1536 000001C7 E0FA                    	loopnz @B
  1537                                  @@:
  1538                                  
  1539 000001C9 BE[F101]                	mov si, .message_4
  1540 000001CC 29FE                    	sub si, di
  1541 000001CE E85300                  	call disp_error
  1542                                  
  1543 000001D1 B020                    	mov al, 32
  1544 000001D3 29F9                    	sub cx, di
  1545 000001D5 83E907                  	sub cx, .message_4_length
  1546                                  	; jbe @FF
  1547                                  @@:
  1548 000001D8 E85700                  	call disp_al
  1549 000001DB E2FB                    	loop @B
  1550                                  @@:
  1551 000001DD E958FF                  	jmp .m4done
  1552                                  %endif
  1553                                  
  1554                                  	align 2, db 0
  1555                                   %if _PROGRESSMULTI
  1556 000001E0 FFFF                    .display:	dw -1
  1557                                   %endif
  1558 000001E2 0000                    .counter:	dw 0
  1559 000001E4 0D5B20                  .message:	db 13,"[ "
  1560 000001E7 2020312E30              .message_number:db "  1.0"	; enough digit slots for 100.0%,
  1561                                  				;  blanks are pre-init until written
  1562                                  .message_number_end:
  1563 000001EC 25205D00                		db "% ]",0
  1564                                   %if _PROGRESSMULTI
  1565 000001F0 20                      		db " "
  1566                                  .message_4:
  1567 000001F1 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 000001F6 252000                  		db "% ",0
  1571                                  .message_4_length: equ $ - 1 - .message_4
  1572                                   %endif
  1573                                  %endif
  1574                                  
  1575                                  
  1576                                  %if _DEVICE
  1577 000001F9 90<rep 7h>              	align 16
  1578                                  device_header_copy:
  1579                                  .:
  1580                                  .next:
  1581 00000200 FFFFFFFF                	dd -1				; already initialised
  1582                                  .attributes:
  1583 00000204 0088                    	dw _DEVICE_ATTRIBUTE
  1584                                  .strategy:
  1585 00000206 1200                    	dw .strategy_entry - .		; -> strategy entry
  1586                                  .interrupt:
  1587 00000208 1600                    	dw .interrupt_entry - .		; -> interrupt entry
  1588                                  .name:
  1589 0000020A 4C44454255472424        	fill 8, 32, db _DEVICE_NAME
  1590                                  
  1591                                  .strategy_entry:
  1592 00000212 EB0690<rep 2h>          	fill 4, 90h, jmp .set_error	; rel8 or rel16 jump, not minus .
  1593                                  .interrupt_entry:
  1594 00000216 CB90<rep 3h>            	fill 4, 90h, retf
  1595                                  
  1596                                  .set_error:
  1597 0000021A 26C747030381            	mov word [es:bx + 3], 8103h	; set error, done, invalid command
  1598 00000220 CB                      	retf
  1599                                  .length: equ $ - .
  1600                                  %endif
  1601                                  
  1602                                  
  1603                                  disp_error.loop:
  1604 00000221 E80E00                  	call disp_al
  1605                                  disp_error:
  1606 00000224 AC                      	lodsb
  1607 00000225 84C0                    	test al, al
  1608 00000227 75F8                    	jnz .loop
  1609 00000229 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 0000022A 2E833E[BA00]16          	cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base
  1641 00000230 741B                    	je disp_al.retn
  1642                                  %endif
  1643                                  disp_al:
  1644                                  %if _TEST_PROGRAM
  1645                                  	retn
  1646                                  %else
  1647 00000232 50                      	push ax
  1648                                  %endif
  1649                                  %if _BOOTLDR
  1650 00000233 53                      	push bx
  1651 00000234 55                      	push bp
  1652 00000235 B40E                    	mov ah, 0Eh
  1653 00000237 BB0700                  	mov bx, 7
  1654                                  %endif
  1655                                  %if _IMAGE_EXE || _DEVICE
  1656 0000023A 52                      	push dx
  1657                                  
  1658                                  %if _BOOTLDR
  1659 0000023B F646FE03                	test byte [bp - 2], 1 | 2
  1660 0000023F 7406                    	jz .display_kernel_mode
  1661                                  %endif
  1662                                  
  1663 00000241 92                      	xchg dx, ax				; dl = input al
  1664 00000242 B402                    	mov ah, 02h
  1665 00000244 CD21                    	int 21h
  1666                                  %if _BOOTLDR
  1667 00000246 A9                      	db __TEST_IMM16				; (skip int)
  1668                                  %endif
  1669                                  
  1670                                  .display_kernel_mode:
  1671                                  %endif
  1672                                  %if _BOOTLDR
  1673 00000247 CD10                    	int 10h
  1674                                  %endif
  1675                                  %if _IMAGE_EXE
  1676 00000249 5A                      	pop dx
  1677                                  %endif
  1678                                  %if _BOOTLDR
  1679 0000024A 5D                      	pop bp
  1680 0000024B 5B                      	pop bx
  1681                                  %endif
  1682 0000024C 58                      	pop ax
  1683                                  .retn:
  1684                                  disp_error.ret:
  1685 0000024D 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 0000024E 4C6F6164206572726F-     .error:		db "Load error: Decompression failure.",13,10,0
  1693 00000257 723A204465636F6D70-
  1693 00000260 72657373696F6E2066-
  1693 00000269 61696C7572652E0D0A-
  1693 00000272 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"
     1                              <1> 
     2                              <1> %if 0
     3                              <1> 
     4                              <1> 8086 Assembly lDOS iniload payload exomizer raw depacker
     5                              <1>  by E. C. Masloch, 2020
     6                              <1> 
     7                              <1> Copyright (c) 2005-2017 Magnus Lind.
     8                              <1> 
     9                              <1> This software is provided 'as-is', without any express or implied warranty.
    10                              <1> In no event will the authors be held liable for any damages arising from
    11                              <1> the use of this software.
    12                              <1> 
    13                              <1> Permission is granted to anyone to use this software for any purpose,
    14                              <1> including commercial applications, and to alter it and redistribute it
    15                              <1> freely, subject to the following restrictions:
    16                              <1> 
    17                              <1>   1. The origin of this software must not be misrepresented * you must not
    18                              <1>   claim that you wrote the original software. If you use this software in a
    19                              <1>   product, an acknowledgment in the product documentation would be
    20                              <1>   appreciated but is not required.
    21                              <1> 
    22                              <1>   2. Altered source versions must be plainly marked as such, and must not
    23                              <1>   be misrepresented as being the original software.
    24                              <1> 
    25                              <1>   3. This notice may not be removed or altered from any distribution.
    26                              <1> 
    27                              <1> %endif
    28                              <1> 
    29                              <1> 	numdef P, 7, 7
    30                              <1> %if _P > 63
    31                              <1>  %error Too large P value, not supported
    32                              <1> %endif
    33                              <1> 	numdef COUNTER,		0, 256
    34                              <1> %if (_COUNTER - 1) & _COUNTER
    35                              <1>  %error COUNTER must be a power of two
    36                              <1> %endif
    37                              <1> 
    38                              <1> 
    39                              <1> 	struc exo_table_entry
    40 00000000 ??                  <1> eteBits:	resb 1
    41 00000001 ????                <1> eteBase:	resw 1
    42                              <1> 	endstruc
    43                              <1> 
    44                              <1> 		; INP:	ds:si -> source
    45                              <1> 		;	dx:cx = length of source
    46                              <1> 		;	es:di -> destination (below source)
    47                              <1> 		;	if _IMAGE_EXE:
    48                              <1> 		;	 bx = EXE mode flag (bit 0)
    49                              <1> 		;	else:
    50                              <1> 		;	 bx = 0
    51                              <1> 		;	if _PAYLOAD_KERNEL_MAX_PARAS:
    52                              <1> 		;	 ax = maximum amount in paragraphs of destination needed
    53                              <1> 		;	 (-1 if full source should be decompressed)
    54                              <1> 		;	else:
    55                              <1> 		;	 ax = -1
    56                              <1> 		; OUT:	NC if success
    57                              <1> 		;	CY if error,
    58                              <1> 		;	 bx = ?errordata (if _DEBUG0)
    59                              <1> 		; CHG:	ax, (bx), cx, dx, es, ds, si, di
    60                              <1> 		; STT:	UP
    61                              <1> 		;
    62                              <1> 		; Note:	The destination reaches up to below the source.
    63                              <1> 		; Note:	The input pointers need not be normalised yet.
    64                              <1> 		;	 Normalised means that the offset part is below 16.
    65                              <1> depack:
    66                              <1> 	lframe near
    67 00000273 5589E5              <1> 	lenter
    68                              <1>  %if _IMAGE_EXE
    69                              <1> 	lvar word,	exemode	; must be bp - 2!
    70 00000276 53                  <1> 	 push bx
    71                              <1>   %if ?exemode != -2
    72                              <1>    %error exemode variable must be directly below bp
    73                              <1>   %endif
    74                              <1>  %endif
    75 00000277 31DB                <1> 	xor bx, bx
    76                              <1>  %if _DEBUG0
    77                              <1> 	lvar word,	errordata
    78                              <1> 	 push bx
    79                              <1>  %endif
    80                              <1> 	lvar word, bit_buffer_and_counter
    81                              <1> 	lequ ?bit_buffer_and_counter, bit_buffer
    82                              <1> 	lequ ?bit_buffer_and_counter + 1, counter
    83 00000279 53                  <1> 	 push bx		; initialise counter (high byte) to zero
    84                              <1> 				; if _P & 8: initialise bit_buffer to zero
    85                              <1> %if _P & 32
    86                              <1> 	lvar dword, offset
    87 0000027A 53                  <1> 	 push bx
    88 0000027B 53                  <1> 	 push bx
    89                              <1> 	lvar word, reuse_offset_state_and_RCL_carry_in
    90                              <1> 	lequ ?reuse_offset_state_and_RCL_carry_in, reuse_offset_state
    91 0000027C 43                  <1> 	inc bx			; = 1
    92 0000027D 53                  <1> 	 push bx
    93                              <1> %endif
    94                              <1> 
    95 0000027E E83902              <1> 	call normalise_both_pointers
    96                              <1> 
    97                              <1> 	lvar dword,	src
    98 00000281 1E                  <1> 	 push ds
    99 00000282 56                  <1> 	 push si
   100                              <1> 	lvar dword,	original_dst
   101 00000283 06                  <1> 	 push es
   102 00000284 57                  <1> 	 push di
   103                              <1> 	lvar dword,	dst
   104 00000285 06                  <1> 	 push es
   105 00000286 57                  <1> 	 push di
   106                              <1> 	lvar dword,	src_remaining
   107 00000287 52                  <1> 	 push dx
   108 00000288 51                  <1> 	 push cx
   109                              <1> 
   110                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
   111                              <1> 	cmp ax, -1		; no maximum specified ?
   112                              <1> 	je @FF			; retain -1 in ax -->
   113                              <1> 	test di, di		; do we need an additional paragraph ?
   114                              <1> 	jz @F			; no -->
   115                              <1> 	inc ax			; es + ax => paragraph after necessary part
   116                              <1> @@:
   117                              <1> 	mov dx, es
   118                              <1> 	add ax, dx		; => paragraph after necessary part
   119                              <1> 		; If the normalised destination pointer's segment grows
   120                              <1> 		;  to this segment then enough has been decompressed.
   121                              <1> d0	mov byte [bp + ?errordata], 40h
   122                              <1> 	jc .error_CY_8		; should not carry
   123                              <1> @@:
   124                              <1> 	lvar word,	dst_max_segment
   125                              <1> 	 push ax
   126                              <1> %endif
   127                              <1> 
   128 00000289 1E                  <1> 	 push ds
   129 0000028A 56                  <1> 	 push si
   130 0000028B E88C02              <1> 	call pointer_to_linear
   131                              <1> 
   132 0000028E 89D3                <1> 	mov bx, dx
   133 00000290 91                  <1> 	xchg cx, ax		; bx:cx = source linear
   134                              <1> 
   135 00000291 06                  <1> 	 push es
   136 00000292 57                  <1> 	 push di
   137 00000293 E88402              <1> 	call pointer_to_linear
   138                              <1> 
   139                              <1> %if _ALLOW_OVERLAPPING
   140 00000296 034EE6              <1> 	add cx, word [bp + ?src_remaining]
   141 00000299 135EE8              <1> 	adc bx, word [bp + ?src_remaining + 2]
   142                              <1> 		; In case of allowing overlapping source and destination,
   143                              <1> 		;  the ?dst_remaining variable is set to
   144                              <1> 		;  ?src + ?src_remaining - ?dst, allowing to write to
   145                              <1> 		;  all of the source buffer (with the checks already in place
   146                              <1> 		;  from the default handling). Additional checks are done by
   147                              <1> 		;  calling check_pointers_not_overlapping. This is done after
   148                              <1> 		;  every change of ?dst to verify that the write pointer stays
   149                              <1> 		;  below-or-equal the read pointer.
   150                              <1> 		; This means the remaining source data may be corrupted by a
   151                              <1> 		;  write, but nothing after the source data is written to,
   152                              <1> 		;  so the error handling (in INIT1 after the data) still works.
   153                              <1> %endif
   154                              <1> 
   155 0000029C 29C1                <1> 	sub cx, ax
   156 0000029E 19D3                <1> 	sbb bx, dx		; bx:cx = source linear - destination linear
   157                              <1> 
   158                              <1> 	lvar dword,	dst_remaining
   159 000002A0 53                  <1> 	 push bx		; push into [bp + ?dst_remaining + 2]
   160 000002A1 51                  <1> 	 push cx		; push into [bp + ?dst_remaining]
   161                              <1> 
   162                              <1> %if _ALLOW_OVERLAPPING
   163 000002A2 E8F901              <1> 	call check_pointers_not_overlapping
   164                              <1> 		; Note:	We initially check here that the write pointer is
   165                              <1> 		;	 low enough, ie below-or-equal the read pointer.
   166                              <1> 		;	 Doing this check here (as well as after any
   167                              <1> 		;	 copied match) allows us to drop the check done
   168                              <1> 		;	 after moving literal bytes.
   169                              <1> d0	mov byte [bp + ?errordata], 1Bh
   170 000002A5 7212                <1> 	jc .error_CY_8
   171                              <1> %endif
   172                              <1> 
   173                              <1> 	lequ fromwords(words(4 * exo_table_entry_size)), 4tablesize
   174                              <1> 	lvar ?4tablesize, offsets1
   175                              <1> 	lequ fromwords(words(16 * exo_table_entry_size)), 16tablesize
   176                              <1> 	lvar ?16tablesize, offsets2
   177                              <1> 	lvar ?16tablesize, offsets3
   178                              <1> %if _P & 16
   179                              <1> 	lvar ?16tablesize, offsets4
   180                              <1> %endif
   181                              <1> 	lvar ?16tablesize, lengths
   182 000002A7 8DA646FF            <1> 	lreserve
   183                              <1> 
   184                              <1> %ifn _P & 8
   185 000002AB E84401              <1> 	call read_byte
   186 000002AE 8846FC              <1> 	mov byte [bp + ?bit_buffer], al
   187                              <1> d0	mov byte [bp + ?errordata], 30h
   188 000002B1 7206                <1> 	jc .error_CY_8
   189                              <1> %endif
   190                              <1> 
   191 000002B3 BF46FF              <1> 	mov di, ?lengths
   192 000002B6 E88801              <1> 	call generate_table_16
   193                              <1> d0	mov byte [bp + ?errordata], 41h
   194                              <1> .error_CY_8:
   195 000002B9 721C                <1> 	jc .error_CY_7
   196                              <1> %if _P & 16
   197                              <1> 	; mov di, ?offsets4		; already pointed to from ?lengths + 48
   198                              <1> 	call generate_table_16
   199                              <1> d0	mov byte [bp + ?errordata], 49h
   200                              <1> 	jc .error_CY_7
   201                              <1> %endif
   202                              <1> 	; mov di, ?offsets3		; already pointed to from ?lengths + 48
   203                              <1> 					;  or ?offsets4 + 48
   204 000002BB E88301              <1> 	call generate_table_16
   205                              <1> d0	mov byte [bp + ?errordata], 42h
   206 000002BE 7217                <1> 	jc .error_CY_7
   207                              <1> 	; mov di, ?offsets2		; already pointed to from ?offsets3 + 48
   208 000002C0 E87E01              <1> 	call generate_table_16
   209                              <1> d0	mov byte [bp + ?errordata], 43h
   210 000002C3 7212                <1> 	jc .error_CY_7
   211                              <1> 	; mov di, ?offsets1		; already pointed to from ?offsets2 + 48
   212 000002C5 B104                <1> 	mov cl, 4
   213 000002C7 E87A01              <1> 	call generate_table_cx		; cx = 0 if NC
   214                              <1> d0	mov byte [bp + ?errordata], 44h
   215 000002CA 720B                <1> 	jc .error_CY_7
   216                              <1> 
   217                              <1> %ifn _P & 4
   218                              <1> 	jmp .STATE_NEXT_BYTE
   219                              <1> %endif
   220                              <1> 
   221                              <1> 		; cx = 0
   222                              <1> .STATE_IMPLICIT_FIRST_LITERAL_BYTE:
   223                              <1> 		; ! cx = 0
   224                              <1> 		; All paths to this label must have cx = 0.
   225                              <1> .literal:
   226 000002CC 41                  <1> 	inc cx				; cx = 1
   227                              <1> .STATE_NEXT_LITERAL_BYTE_increment_counter:
   228 000002CD C576F2              <1> 	lds si, [bp + ?src]
   229 000002D0 294EE6              <1> 	sub word [bp + ?src_remaining], cx
   230 000002D3 835EE800            <1> 	sbb word [bp + ?src_remaining + 2], 0
   231                              <1> d0	mov byte [bp + ?errordata], 45h
   232                              <1> .error_CY_7:
   233 000002D7 7220                <1> 	jc .error_CY_6
   234 000002D9 E89601              <1> 	call copy_data
   235                              <1> d0	mov byte [bp + ?errordata], 46h
   236 000002DC 721B                <1> 	jc .error_CY_6
   237 000002DE 8976F2              <1> 	mov word [bp + ?src], si
   238 000002E1 8C5EF4              <1> 	mov word [bp + ?src + 2], ds
   239                              <1> %if _P & 32
   240 000002E4 F9                  <1> 	stc
   241                              <1> .STATE_NEXT_BYTE_rcl:
   242 000002E5 D056F6              <1> 	rcl byte [bp + ?reuse_offset_state], 1
   243                              <1> %endif
   244                              <1> 
   245                              <1> 	; jmp .STATE_NEXT_BYTE
   246                              <1> 
   247                              <1> .STATE_NEXT_BYTE:
   248                              <1> %if _COUNTER
   249 000002E8 FE46FD              <1> 	inc byte [bp + ?counter]
   250 000002EB F646FDFF            <1> 	test byte [bp + ?counter], _COUNTER - 1
   251 000002EF 7505                <1> 	jnz @F
   252 000002F1 B02E                <1> 	mov al, '.'
   253 000002F3 E8B1FD              <1> 	call disp_al_counter
   254                              <1> @@:
   255                              <1> %endif
   256 000002F6 E81101              <1> 	call read_bits_1		; cx = 0 if NC
   257                              <1> d0	mov byte [bp + ?errordata], 32h
   258                              <1> .error_CY_6:
   259 000002F9 720F                <1> 	jc .error_CY_5
   260 000002FB 85C0                <1> 	test ax, ax
   261 000002FD 75CD                <1> 	jnz .literal			; (cx = 0 still)
   262                              <1> 
   263                              <1> 		; cx = ax = 0
   264                              <1> .not_literal:
   265                              <1> 
   266                              <1> 	; call get_gamma_code
   267                              <1> 		; INP:	-
   268                              <1> 		; OUT:	CY if error
   269                              <1> 		;	NC if success,
   270                              <1> 		;	 bx:dx = gamma
   271                              <1> 		;	 ax = cx = 0
   272                              <1> 		; CHG:	ds, si
   273                              <1> 		; STT:	bp -> depack stack frame
   274                              <1> 		;	UP
   275                              <1> .get_gamma_code:
   276 000002FF 31D2                <1> 	xor dx, dx
   277 00000301 31DB                <1> 	xor bx, bx		; bx:dx = gamma = 0
   278                              <1> .ggc_loop:
   279                              <1> 		; cx = 0. ax = 0 initially, else = 1
   280 00000303 01C2                <1> 	add dx, ax
   281 00000305 11CB                <1> 	adc bx, cx		; ++gamma (except initially)
   282 00000307 E80001              <1> 	call read_bits_1	; read_bits(1)
   283                              <1> d0	mov byte [bp + ?errordata], 33h
   284                              <1> .error_CY_5:
   285 0000030A 7252                <1> 	jc .error_CY_4
   286 0000030C 3401                <1> 	xor al, 1		; returned == 0 ?
   287 0000030E 75F3                <1> 	jnz .ggc_loop		; yes, loop --> (ax = 1 if looping)
   288                              <1> 				; no, end of loop
   289                              <1> 
   290 00000310 85DB                <1> 	test bx, bx
   291                              <1> d0	mov byte [bp + ?errordata], 34h
   292 00000312 7528                <1> 	jnz .error
   293 00000314 83FA11              <1> 	cmp dx, 17
   294                              <1> d0	mov byte [bp + ?errordata], 38h
   295 00000317 7211                <1> 	jb .not_literal_data_block
   296 00000319 7721                <1> 	ja .error
   297                              <1> 
   298                              <1> .literal_data_block:
   299                              <1> %if _P & 2
   300 0000031B E8D400              <1> 	call read_byte
   301                              <1> d0	mov byte [bp + ?errordata], 35h
   302 0000031E 723E                <1> 	jc .error_CY_4
   303 00000320 88C4                <1> 	mov ah, al
   304 00000322 E8CD00              <1> 	call read_byte
   305                              <1> d0	mov byte [bp + ?errordata], 36h
   306 00000325 7237                <1> 	jc .error_CY_4
   307                              <1> %else
   308                              <1> 	mov cx, 16
   309                              <1> 	call read_bits
   310                              <1> d0	mov byte [bp + ?errordata], 48h
   311                              <1> 	jc .error_CY_4
   312                              <1> %endif
   313 00000327 91                  <1> 	xchg ax, cx
   314 00000328 EBA3                <1> 	jmp .STATE_NEXT_LITERAL_BYTE_increment_counter
   315                              <1> 
   316                              <1> .not_literal_data_block:
   317 0000032A 80FA10              <1> 	cmp dl, 16
   318 0000032D 751E                <1> 	jne .sequence
   319                              <1> 
   320                              <1> .end_check:
   321                              <1> d0	mov byte [bp + ?errordata], 40h
   322 0000032F 837EE800            <1> 	cmp word [bp + ?src_remaining + 2], 0
   323 00000333 7507                <1> 	jne .error
   324 00000335 837EE60F            <1> 	cmp word [bp + ?src_remaining], 15
   325 00000339 7701                <1> 	ja .error
   326                              <1> .end:
   327 0000033B A8                  <1> 	db __TEST_IMM8			; (NC)
   328                              <1> .error:
   329 0000033C F9                  <1> 	stc
   330                              <1> 
   331                              <1> %if _COUNTER
   332 0000033D 9F                  <1> 	lahf
   333 0000033E B00D                <1> 	mov al, 13
   334 00000340 E8E7FE              <1> 	call disp_al_for_progress
   335 00000343 B00A                <1> 	mov al, 10
   336 00000345 E8E2FE              <1> 	call disp_al_for_progress
   337 00000348 9E                  <1> 	sahf
   338                              <1> %endif
   339                              <1> d0	mov bx, word [bp + ?errordata]
   340 00000349 89EC5D              <1> 	lleave code
   341 0000034C C3                  <1> 	lret
   342                              <1> 
   343                              <1> 
   344                              <1> .sequence:
   345 0000034D 89D7                <1> 	mov di, dx
   346 0000034F 01D2                <1> 	add dx, dx
   347 00000351 01D7                <1> 	add di, dx		; * 3 = * exo_table_entry_size
   348                              <1> 
   349 00000353 8B9B47FF            <1> 	mov bx, word [bp + ?lengths + di + eteBase]
   350                              <1> 	; xor cx, cx		; cx = 0 already after get_gamma_code NC
   351 00000357 8A8B46FF            <1> 	mov cl, byte [bp + ?lengths + di + eteBits]
   352 0000035B E8AF00              <1> 	call read_bits		; cx = 0 if NC
   353                              <1> d0	mov byte [bp + ?errordata], 39h
   354                              <1> .error_CY_4:
   355 0000035E 72DC                <1> 	jc .error
   356 00000360 01C3                <1> 	add bx, ax		; bx = length
   357                              <1> 
   358                              <1> %if _P & 32
   359 00000362 8A46F6              <1> 	mov al, byte [bp + ?reuse_offset_state]
   360 00000365 2403                <1> 	and al, 3
   361 00000367 3C01                <1> 	cmp al, 1
   362 00000369 7512                <1> 	jne @F
   363 0000036B E89C00              <1> 	call read_bits_1	; cx = 0 if NC
   364                              <1> d0	mov byte [bp + ?errordata], 4Ch
   365 0000036E 72EE                <1> 	jc .error_CY_4
   366 00000370 48                  <1> 	dec ax			; = -1 if was 0, = 0 if was 1
   367 00000371 750A                <1> 	jnz @F			; jump if now -1, ie was 0
   368 00000373 89D9                <1> 	mov cx, bx
   369 00000375 8B56F8              <1> 	mov dx, word [bp + ?offset]
   370 00000378 8B5EFA              <1> 	mov bx, word [bp + ?offset + 2]
   371 0000037B EB43                <1> 	jmp .use_prior_offset
   372                              <1> @@:
   373                              <1> %endif
   374                              <1> 
   375                              <1> d0	mov byte [bp + ?errordata], 3Bh
   376 0000037D B6FF                <1> 	mov dh, (?offsets1 >> 8) & 0FFh
   377 0000037F 85DB                <1> 	test bx, bx
   378 00000381 7410                <1> 	jz .switch_default
   379                              <1> %ifn _P & 16
   380 00000383 83FB02              <1> 	cmp bx, 2
   381 00000386 7408                <1> 	je .switch_case2
   382 00000388 7709                <1> 	ja .switch_default
   383                              <1> %else
   384                              <1> 	cmp bx, 4
   385                              <1> 	jae .switch_default
   386                              <1> 	cmp bl, 2
   387                              <1> 	je .switch_case2
   388                              <1> 	; jb .switch_case1
   389                              <1> 	ja .switch_case3
   390                              <1> %endif
   391                              <1> .switch_case1:
   392 0000038A B102                <1> 	mov cl, 2		; cx = 2
   393 0000038C B2D6                <1> 	mov dl, ?offsets1 & 0FFh
   394                              <1> d0	mov byte [bp + ?errordata], 3Ah
   395 0000038E EB07                <1> 	jmp .switch_common
   396                              <1> 
   397                              <1> .switch_case2:
   398                              <1>  %if (?offsets1 >> 8) == (?offsets2 >> 8)
   399 00000390 B2A6                <1> 	mov dl, ?offsets2 & 0FFh
   400                              <1>  %else
   401                              <1> 	mov dx, ?offsets2
   402                              <1>  %endif
   403                              <1>  %if (?offsets1 >> 8) == (?offsets3 >> 8)
   404 00000392 A9                  <1> 	db __TEST_IMM16		; skip mov dl
   405                              <1>  %else
   406                              <1> 	jmp .switch_common_cl_4
   407                              <1>  %endif
   408                              <1> 
   409                              <1> %ifn _P & 16
   410                              <1> .switch_default:
   411                              <1>  %if (?offsets1 >> 8) == (?offsets3 >> 8)
   412 00000393 B276                <1> 	mov dl, ?offsets3 & 0FFh
   413                              <1>  %else
   414                              <1> 	mov dx, ?offsets3
   415                              <1>  %endif
   416                              <1> %else
   417                              <1> .switch_case3:
   418                              <1>  %if (?offsets1 >> 8) == (?offsets3 >> 8)
   419                              <1> 	mov dl, ?offsets3 & 0FFh
   420                              <1>  %else
   421                              <1> 	mov dx, ?offsets3
   422                              <1>  %endif
   423                              <1>  %if (?offsets1 >> 8) == (?offsets4 >> 8)
   424                              <1> 	db __TEST_IMM16		; skip mov dl
   425                              <1>  %else
   426                              <1> 	jmp .switch_common_cl_4
   427                              <1>  %endif
   428                              <1> 
   429                              <1> .switch_default:
   430                              <1>  %if (?offsets1 >> 8) == (?offsets4 >> 8)
   431                              <1> 	mov dl, ?offsets4 & 0FFh
   432                              <1>  %else
   433                              <1> 	mov dx, ?offsets4
   434                              <1>  %endif
   435                              <1> %endif
   436                              <1> 	; jmp .switch_common_cl_4
   437                              <1> 
   438                              <1> .switch_common_cl_4:
   439 00000395 B104                <1> 	mov cl, 4		; cx = 4
   440                              <1> 
   441                              <1> .switch_common:
   442 00000397 E87300              <1> 	call read_bits
   443                              <1> .error_CY_3:
   444 0000039A 72C2                <1> 	jc .error_CY_4
   445                              <1> 				; ax = next index, dx -> next table
   446 0000039C 89C7                <1> 	mov di, ax
   447 0000039E 01C0                <1> 	add ax, ax
   448 000003A0 01C7                <1> 	add di, ax		; di = offset into table
   449 000003A2 01D7                <1> 	add di, dx		; -> table entry
   450                              <1> 	; xor cx, cx		; cx already = 0 after read_bits NC
   451 000003A4 8A0B                <1> 	mov cl, byte [bp + di + eteBits]
   452 000003A6 E86400              <1> 	call read_bits		; leaves cx = 0 if NC
   453                              <1> d0	mov byte [bp + ?errordata], 3Dh
   454                              <1> .error_CY_2:
   455 000003A9 72EF                <1> 	jc .error_CY_3
   456 000003AB 87CB                <1> 	xchg cx, bx		; cx = length that we remembered in bx
   457                              <1> 				; bx = 0
   458 000003AD 92                  <1> 	xchg dx, ax		; bx:dx = read bits
   459                              <1> 
   460 000003AE 035301              <1> 	add dx, word [bp + di + eteBase]
   461 000003B1 11DB                <1> 	adc bx, bx		; bx:dx = offset
   462                              <1> 
   463                              <1> 	; test bx, bx		; offset 0 ?
   464 000003B3 7505                <1> 	jnz @F			; no -->
   465 000003B5 85D2                <1> 	test dx, dx		; offset 0 ?
   466                              <1> d0	mov byte [bp + ?errordata], 3Eh
   467 000003B7 F9                  <1> 	stc			; CY
   468 000003B8 74EF                <1> 	jz .error_CY_2		; yes, invalid -->
   469                              <1> @@:
   470                              <1> 
   471                              <1> %if _P & 32
   472 000003BA 8956F8              <1> 	mov word [bp + ?offset], dx
   473 000003BD 895EFA              <1> 	mov word [bp + ?offset + 2], bx
   474                              <1> 
   475                              <1> .use_prior_offset:
   476                              <1> %endif
   477 000003C0 51                  <1> 	push cx
   478 000003C1 89D1                <1> 	mov cx, dx
   479 000003C3 F7DB                <1>         neg bx
   480 000003C5 F7D9                <1>         neg cx
   481 000003C7 83DB00              <1>         sbb bx, byte 0          ; neg bx:cx
   482 000003CA FF76EC              <1> 	 push word [bp + ?dst + 2]
   483 000003CD FF76EA              <1> 	 push word [bp + ?dst]
   484 000003D0 E81801              <1> 	call normalise_pointer_with_displacement_bxcx
   485 000003D3 5E                  <1> 	 pop si
   486 000003D4 5B                  <1> 	 pop bx			; bx:si = pointer into decompressed data
   487 000003D5 59                  <1> 	pop cx			; restore match length
   488                              <1> d0	mov byte [bp + ?errordata], 47h
   489 000003D6 F5                  <1> 	cmc
   490 000003D7 72D0                <1> 	jc .error_CY_2
   491                              <1> 
   492 000003D9 3B5EF0              <1> 	cmp bx, word [bp + ?original_dst + 2]
   493                              <1> 				; is ?dst below source of matching ?
   494 000003DC 7503                <1> 	jne @F			; if segment unequal -->
   495 000003DE 3B76EE              <1> 	cmp si, word [bp + ?original_dst]
   496                              <1> d0	mov byte [bp + ?errordata], 17h
   497                              <1> @@:
   498 000003E1 72C6                <1> 	jb .error_CY_2		; yes, ?dst is below ?original_dst -->
   499 000003E3 8EDB                <1> 	mov ds, bx		; -> match source data
   500 000003E5 E88A00              <1> 	call copy_data
   501                              <1> d0	mov byte [bp + ?errordata], 3Fh
   502                              <1> .error_CY_1:
   503 000003E8 72BF                <1> 	jc .error_CY_2
   504                              <1> 				; NC
   505                              <1> %if _ALLOW_OVERLAPPING
   506 000003EA E8B100              <1> 	call check_pointers_not_overlapping
   507                              <1> d0	mov byte [bp + ?errordata], 1Ch
   508 000003ED 72F9                <1> 	jc .error_CY_1
   509                              <1> 				; NC
   510                              <1> %endif
   511                              <1> %if _P & 32
   512                              <1> 	; clc			; (already NC)
   513 000003EF E9F3FE              <1> 	jmp .STATE_NEXT_BYTE_rcl
   514                              <1> %else
   515                              <1> 	jmp .STATE_NEXT_BYTE
   516                              <1> %endif
   517                              <1> 
   518                              <1> 
   519                              <1> 		; INP:	?src
   520                              <1> 		;	?src_remaining
   521                              <1> 		; OUT:	CY if error (source exhausted)
   522                              <1> 		;	NC if success,
   523                              <1> 		;	 al = byte read from source
   524                              <1> 		;	 ?src
   525                              <1> 		;	 ?src_remaining
   526                              <1> 		; CHG:	ds, si
   527                              <1> 		; STT:	bp -> depack stack frame
   528                              <1> 		;	UP
   529                              <1> read_byte:
   530 000003F2 C576F2              <1> 	lds si, [bp + ?src]
   531 000003F5 AC                  <1> 	lodsb
   532 000003F6 1E                  <1> 	 push ds
   533 000003F7 56                  <1> 	 push si
   534 000003F8 E8CE00              <1> 	call normalise_pointer
   535 000003FB 8F46F2              <1> 	 pop word [bp + ?src]
   536 000003FE 8F46F4              <1> 	 pop word [bp + ?src + 2]
   537 00000401 836EE601            <1> 	sub word [bp + ?src_remaining], 1
   538 00000405 835EE800            <1> 	sbb word [bp + ?src_remaining + 2], 0
   539 00000409 C3                  <1> 	retn
   540                              <1> 
   541                              <1> 
   542                              <1> read_bits_1:
   543 0000040A B90100              <1> 	mov cx, 1
   544                              <1> 
   545                              <1> 		; INP:	cl = cx = number of bits to read (0..15)
   546                              <1> 		; OUT:	CY if error (cx too high or source exhausted)
   547                              <1> 		;	NC if success,
   548                              <1> 		;	 ax = read data
   549                              <1> 		;	 cx = 0
   550                              <1> 		; CHG:	ds, si
   551                              <1> 		; STT:	bp -> depack stack frame
   552                              <1> 		;	UP
   553                              <1> read_bits:
   554                              <1> %if _P & 2
   555 0000040D 83F910              <1> 	cmp cx, 16		; CY if valid
   556                              <1> %else
   557                              <1> 	cmp cx, 17		; CY if valid
   558                              <1> %endif
   559 00000410 F5                  <1> 	cmc			; NC if valid
   560 00000411 722D                <1> 	jc .ret			; if error --> (CY)
   561                              <1> %if _P & 2
   562 00000413 88C8                <1> 	mov al, cl
   563 00000415 88CC                <1> 	mov ah, cl
   564 00000417 250708              <1> 	and ax, (8 << 8) | 7	; al = bit_count, ah = byte_copy
   565 0000041A 88C1                <1> 	mov cl, al		; cl = cx = bit_count
   566 0000041C B000                <1> 	mov al, 0		; al = bits
   567                              <1> %else
   568                              <1> 	xor ax, ax		; ax = bits
   569                              <1> %endif
   570 0000041E E317                <1> 	jcxz .end
   571                              <1> .loop:
   572                              <1> %if _P & 1
   573 00000420 D066FC              <1> 	shl byte [bp + ?bit_buffer], 1
   574                              <1> %else
   575                              <1> 	shr byte [bp + ?bit_buffer], 1
   576                              <1> %endif				; shl/shr both set ZF
   577 00000423 750E                <1> 	jnz .notzero
   578 00000425 50                  <1> 	push ax
   579 00000426 E8C9FF              <1> 	call read_byte
   580 00000429 8846FC              <1> 	mov byte [bp + ?bit_buffer], al
   581 0000042C 58                  <1> 	pop ax
   582 0000042D 7211                <1> 	jc .ret			; if error --> (CY)
   583 0000042F F9                  <1> 	stc
   584                              <1> %if _P & 1
   585 00000430 D056FC              <1> 	rcl byte [bp + ?bit_buffer], 1
   586                              <1> %else
   587                              <1> 	rcr byte [bp + ?bit_buffer], 1
   588                              <1> %endif
   589                              <1> .notzero:
   590                              <1> %if _P & 2
   591 00000433 D0D0                <1> 	rcl al, 1		; bits <<= 1; bits |= carry;
   592                              <1> %else
   593                              <1> 	rcl ax, 1
   594                              <1> %endif
   595 00000435 E2E9                <1> 	loop .loop
   596                              <1> .end:
   597                              <1> %if _P & 2
   598 00000437 84E4                <1> 	test ah, ah		; NC
   599 00000439 7405                <1> 	jz .byte_copy_zero	; (NC)
   600 0000043B 88C4                <1> 	mov ah, al		; bits <<= 8;
   601 0000043D E8B2FF              <1> 	call read_byte		; bits |= read_byte()
   602                              <1> 				; pass CF to caller
   603                              <1> .byte_copy_zero:		; ax = bits
   604                              <1> %endif
   605                              <1> .ret:
   606 00000440 C3                  <1> 	retn
   607                              <1> 
   608                              <1> 
   609                              <1> generate_table_16:
   610 00000441 B91000              <1> 	mov cx, 16
   611                              <1> 		; INP:	cx = amount of table entries, < 256 (ch = 0)
   612                              <1> 		;	bp + di -> start of table
   613                              <1> 		; OUT:	CY if error
   614                              <1> 		;	NC if success,
   615                              <1> 		;	 cx = 0
   616                              <1> 		;	 di = INP:di + INP:cx * exo_table_entry_size
   617                              <1> 		; CHG:	ax, bx, ds, si
   618                              <1> 		; STT:	bp -> depack stack frame
   619                              <1> 		;	UP
   620                              <1> generate_table_cx:
   621 00000444 BB0100              <1> 	mov bx, 1
   622                              <1> .loop:
   623 00000447 895B01              <1> 	mov word [bp + di + eteBase], bx
   624 0000044A 51                  <1> 	push cx
   625                              <1> %if _P & 2
   626 0000044B B103                <1> 	mov cl, 3
   627 0000044D E8BDFF              <1> 	call read_bits
   628 00000450 721E                <1> 	jc .ret_pop
   629 00000452 8803                <1> 	mov byte [bp + di + eteBits], al
   630 00000454 E8B3FF              <1> 	call read_bits_1
   631 00000457 7217                <1> 	jc .ret_pop
   632 00000459 D0E0                <1> 	shl al, 1
   633 0000045B D0E0                <1> 	shl al, 1
   634 0000045D D0E0                <1> 	shl al, 1
   635 0000045F 0803                <1> 	or byte [bp + di + eteBits], al
   636 00000461 B80100              <1> 	mov ax, 1
   637 00000464 8A0B                <1> 	mov cl, byte [bp + di + eteBits]
   638                              <1> %else
   639                              <1> 	mov cl, 4
   640                              <1> 	call read_bits
   641                              <1> 	jc .ret_pop
   642                              <1> 	mov byte [bp + di + eteBits], al
   643                              <1> 	xchg cx, ax		; cl = al
   644                              <1> 	mov ax, 1
   645                              <1> %endif
   646 00000466 D3E0                <1> 	shl ax, cl
   647 00000468 01C3                <1> 	add bx, ax
   648 0000046A 59                  <1> 	pop cx
   649                              <1> %if exo_table_entry_size != 3
   650                              <1>  %error Unexpected size
   651                              <1> %endif
   652 0000046B AF                  <1> 	scasw			; (di must never equal 0FFFFh here)
   653 0000046C 47                  <1> 	inc di			; like add di, 3
   654 0000046D E2D8                <1> 	loop .loop
   655 0000046F A8                  <1> 	db __TEST_IMM8		; (skip pop, NC)
   656                              <1> .ret_pop:
   657 00000470 59                  <1> 	pop cx
   658 00000471 C3                  <1> 	retn
   659                              <1> 
   660                              <1> 
   661                              <1> 		; INP:	ds:si -> data (normalised and in bounds)
   662                              <1> 		;	?dst (normalised), ?dst_remaining
   663                              <1> 		;	cx = number of bytes (entire range valid)
   664                              <1> 		; OUT:	CY if error (destination exhausted)
   665                              <1> 		;	NC if success,
   666                              <1> 		;	 ds:si -> behind copied source (normalised)
   667                              <1> 		;	 ?dst -> behind copied destination (normalised)
   668                              <1> 		;	 ?dst_remaining decremented
   669                              <1> 		;	 ax = cx = 0
   670                              <1> 		;	Instead of returning, this may jump to depack.end
   671                              <1> 		;	 if the destination segment grows up to the value
   672                              <1> 		;	 stored in the ?dst_max_segment variable. It is
   673                              <1> 		;	 assumed that this will use the stack frame to leave
   674                              <1> 		;	 the function, therefore discarding any of the stack
   675                              <1> 		;	 contents between the frame and the stack top.
   676                              <1> 		; CHG:	es, di
   677                              <1> 		; STT:	bp -> depack stack frame
   678                              <1> 		;	UP
   679                              <1> copy_data:
   680                              <1> d0	inc byte [bp + ?errordata + 1]
   681                              <1> 
   682 00000472 294EE2              <1> 	sub word [bp + ?dst_remaining], cx
   683 00000475 835EE400            <1> 	sbb word [bp + ?dst_remaining + 2], 0
   684 00000479 7222                <1> 	jc .ret
   685 0000047B C47EEA              <1> 	les di, [bp + ?dst]
   686                              <1> 
   687 0000047E 31C0                <1> 	xor ax, ax			; initialise second step length
   688 00000480 83F9F0              <1> 	cmp cx, 0FFF0h			; can copy in one step ?
   689 00000483 760C                <1> 	jbe @F				; yes -->
   690 00000485 88C8                <1> 	mov al, cl
   691 00000487 240F                <1> 	and al, 15			; second step length
   692 00000489 B1F0                <1> 	mov cl, 0F0h			; maximum first step = 0FFF0h
   693 0000048B F3A4                <1> 	rep movsb			; move first step of two steps
   694 0000048D E82A00              <1> 	call normalise_both_pointers	; normalise pointers after
   695 00000490 91                  <1> 	xchg ax, cx			; cx = second step length
   696                              <1> @@:
   697 00000491 F3A4                <1> 	rep movsb			; move last step
   698 00000493 E82400              <1> 	call normalise_both_pointers	; normalise (again)
   699 00000496 897EEA              <1> 	mov word [bp + ?dst], di
   700 00000499 8C46EC              <1> 	mov word [bp + ?dst + 2], es	; store to ?dst
   701                              <1> %if _PAYLOAD_KERNEL_MAX_PARAS
   702                              <1> 	mov di, es			; ! this is the *segment*
   703                              <1> 	cmp di, word [bp + ?dst_max_segment]
   704                              <1> 	jae depack.end
   705                              <1> %endif
   706 0000049C F8                  <1> 	clc
   707                              <1> .ret:
   708 0000049D C3                  <1> 	retn
  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"
  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 0000049E FF76EC                  	 push word [bp + ?dst + 2]
  1783 000004A1 FF76EA                  	 push word [bp + ?dst]
  1784                                  %else
  1785                                  	 push es
  1786                                  	 push di
  1787                                  %endif
  1788 000004A4 E87300                  	call pointer_to_linear
  1789                                  
  1790 000004A7 91                      	xchg cx, ax
  1791 000004A8 87DA                    	xchg bx, dx			; bx:cx = linear ?dst after write
  1792                                  
  1793                                  %if CHECK_POINTERS_VARIABLE_SRC
  1794 000004AA FF76F4                  	 push word [bp + ?src + 2]
  1795 000004AD FF76F2                  	 push word [bp + ?src]
  1796                                  %else
  1797                                  	 push ds
  1798                                  	 push si
  1799                                  %endif
  1800 000004B0 E86700                  	call pointer_to_linear		; dx:ax = linear ?src before next read
  1801                                  
  1802 000004B3 39DA                    	cmp dx, bx			; ?src >= ?dst ?
  1803 000004B5 7502                    	jne @F
  1804 000004B7 39C8                    	cmp ax, cx
  1805                                  @@:
  1806                                  					; (CY) if error (src < dst)
  1807                                  					; (NC) if no error
  1808 000004B9 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 000004BA 06                      	 push es
  1824 000004BB 57                      	 push di
  1825 000004BC E80A00                  	call normalise_pointer
  1826 000004BF 5F                      	 pop di
  1827 000004C0 07                      	 pop es
  1828                                  %endif
  1829                                  
  1830                                  normalise_dssi_pointer:
  1831 000004C1 1E                      	 push ds
  1832 000004C2 56                      	 push si
  1833 000004C3 E80300                  	call normalise_pointer
  1834 000004C6 5E                      	 pop si
  1835 000004C7 1F                      	 pop ds
  1836 000004C8 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 000004C9 5589E5                  	lenter
  1851                                  
  1852 000004CC 837E040F                	cmp word [bp + ?offset], 15
  1853 000004D0 7617                    	jbe .ret
  1854                                  
  1855 000004D2 53                      	push bx
  1856 000004D3 51                      	push cx
  1857                                  
  1858 000004D4 31DB                    	xor bx, bx
  1859 000004D6 31C9                    	xor cx, cx
  1860 000004D8 FF7606                  	 push word [bp + ?segment]
  1861 000004DB FF7604                  	 push word [bp + ?offset]
  1862 000004DE E80A00                  	call normalise_pointer_with_displacement_bxcx
  1863 000004E1 8F4604                  	 pop word [bp + ?offset]
  1864 000004E4 8F4606                  	 pop word [bp + ?segment]
  1865                                  
  1866 000004E7 59                      	pop cx
  1867 000004E8 5B                      	pop bx
  1868                                  .ret:
  1869 000004E9 5D                      	lleave
  1870 000004EA 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 000004EB 5589E5                  	lenter
  1885                                  
  1886                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1887                                  	cmp word [bp + ?offset], 15
  1888                                  	jbe .ret
  1889                                  %endif
  1890                                  
  1891 000004EE 50                      	push ax
  1892 000004EF 51                      	push cx
  1893 000004F0 52                      	push dx
  1894                                  
  1895 000004F1 FF7606                  	 push word [bp + ?segment]
  1896 000004F4 FF7604                  	 push word [bp + ?offset]
  1897 000004F7 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 000004FA 01C1                    	add cx, ax
  1907 000004FC 11DA                    	adc dx, bx			; dx:cx = dx:ax + bx:cx
  1908                                  	; pop bx
  1909 000004FE 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 000004FF 53                      	push bx
  1929 00000500 89CB                    	mov bx, cx
  1930 00000502 83E10F                  	and cx, 15
  1931 00000505 894E04                  	mov word [bp + ?offset], cx
  1932                                  
  1933 00000508 B104                    	mov cl, 4
  1934                                  @@:
  1935 0000050A D1EA                    	shr dx, 1
  1936 0000050C D1DB                    	rcr bx, 1
  1937 0000050E E2FA                    	loop @B
  1938                                  
  1939 00000510 895E06                  	mov word [bp + ?segment], bx
  1940 00000513 5B                      	pop bx
  1941                                  
  1942                                  	; test dx, dx
  1943                                  	; jnz .error
  1944                                  
  1945                                  .return:
  1946                                  
  1947                                  %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1948 00000514 9E                      	sahf				; restore flags from ah
  1949                                  %endif
  1950 00000515 5A                      	pop dx
  1951 00000516 59                      	pop cx
  1952 00000517 58                      	pop ax
  1953                                  %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT
  1954                                  .ret:
  1955                                  %endif
  1956 00000518 5D                      	lleave
  1957 00000519 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 0000051A 5589E5                  	lenter
  1968                                  
  1969 0000051D 8B4606                  	mov ax, word [bp + ?segment]
  1970 00000520 31D2                    	xor dx, dx
  1971 00000522 51                      	push cx
  1972 00000523 B90400                  	mov cx, 4
  1973                                  @@:
  1974 00000526 D1E0                    	shl ax, 1
  1975 00000528 D1D2                    	rcl dx, 1
  1976 0000052A E2FA                    	loop @B
  1977                                  
  1978 0000052C 034604                  	add ax, word [bp + ?offset]
  1979 0000052F 11CA                    	adc dx, cx			; cx = 0 here
  1980 00000531 59                      	pop cx
  1981                                  
  1982 00000532 5D                      	lleave
  1983 00000533 C20400                  	lret
  1984                                  
  1985                                  
  1986                                  %if _PASSLCFG
  1987                                  	align 16
  1988                                  transfer_lcfg_block:
  1989                                  	times lcfg.size nop
  1990                                  %endif
  1991 00000536 90<rep Ah>              	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 000001E3 90<rep Dh>              	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: iniexo: 1840 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                                  
