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 SCAN, 0 52 53 numdef DEBUG0 ; use errordata to generate an error code 54 numdef DEBUG1 ; dump_stack_frame after an error occurred 55 numdef DEBUG2 ; dump_stack_frame before blz_depack_safe call 56 numdef DEBUG3 ; dump_stack_frame at start of blz_depack_safe 57 58 numdef OPTIMISE_INPUT_SMALL, 0 59 numdef OPTIMISE_OUYPUT_SMALL, 0 60 numdef ALLOW_OVERLAPPING, 1 ; allow overlapping src and dst 61 numdef TEST_PROGRAM, 0 62 numdef TEST_PROGRAM_DECOMPRESSED_SIZE, 0,0 63 %if _TEST_PROGRAM && ! _TEST_PROGRAM_DECOMPRESSED_SIZE 64 %error Test program has to learn of decompressed size. 65 %endif 66 numdef TEST_PROGRESS, 0 67 68 numdef INCLUDE_UNCOMPRESSED 69 numdef INCLUDE_UNCOMPRESSED_IN_IMAGE, 1 70 numdef WRITE_WRONG_FILE 71 numdef RELOAD_XMS, 0 72 numdef RELOAD_FILE, 0 73 74 numdef EXEC_OFFSET, 0 75 numdef EXEC_SEGMENT, 0 76 numdef IMAGE_EXE, 0 77 %if ! _IMAGE_EXE && _TEST_PROGRAM 78 %error Test program can only be used as EXE. 79 %endif 80 numdef IMAGE_EXE_CS, -16 ; relative-segment for CS 81 numdef IMAGE_EXE_IP, 256 +64 ; value for IP 82 ; The next two are only used if _IMAGE_EXE_AUTO_STACK is 0. 83 numdef IMAGE_EXE_SS, -16 ; relative-segment for SS 84 numdef IMAGE_EXE_SP, 0FFFEh ; value for SP (0 underflows) 85 numdef IMAGE_EXE_AUTO_STACK, 0, 2048 ; use stack behind image 86 ; _IMAGE_EXE_AUTO_STACK here differs from iniload's def of 87 ; the same name. This one is only used as a flag; if non-zero, 88 ; keep the stack given to us by iniload; if zero, set up the 89 ; stack specified by _IMAGE_EXE_SS and _IMAGE_EXE_SP. 90 numdef IMAGE_EXE_GET_COM_STACK, 0 91 ; set up stack for flat .COM style entry 92 numdef DEVICE, 0 93 gendef DEVICE_NAME, "" 94 numdef DEVICE_ATTRIBUTE, 8000h 95 numdef DEVICE_ZERO_ENTRYPOINT, 0 96 numdef BOOTLDR, 1 ; support boot loaded entrypoint 97 98 numdef BRIEFLZ, 0 99 numdef LZ4, 0 100 numdef SNAPPY, 0 101 numdef EXODECR, 0 102 numdef X, 0 103 numdef HEATSHRINK, 0 104 numdef LZD, 0 105 numdef LZO, 0 106 numdef LZSA2, 0 107 numdef APL, 0 108 numdef BZP, 0 109 numdef ZEROCOMP, 0 110 numdef MVCOMP, 0 111 numdef LZEXEDAT, 0 112 numdef ZX0, 0 113 %if (!!_BRIEFLZ + !!_LZ4 + !!_SNAPPY + !!_EXODECR + !!_X + !!_HEATSHRINK + !!_LZD + !!_LZO + !!_LZSA2 + !!_APL + !!_BZP + !!_ZEROCOMP + !!_MVCOMP + !!_LZEXEDAT + !!_ZX0) != 1 116 %fatal Exactly one compression method must be selected. 117 %endif 118 %assign ADDITIONAL_MEMORY 0 119 %if _BRIEFLZ 120 strdef PAYLOAD_FILE, "lDOSLOAD.BLZ" 121 %elif _LZ4 122 strdef PAYLOAD_FILE, "lDOSLOAD.LZ4" 123 %elif _SNAPPY 124 strdef PAYLOAD_FILE, "lDOSLOAD.SZ" 125 %elif _EXODECR 126 strdef PAYLOAD_FILE, "lDOSLOAD.EXO" 127 %elif _X 128 strdef PAYLOAD_FILE, "lDOSLOAD.X" 129 %elif _HEATSHRINK 130 strdef PAYLOAD_FILE, "lDOSLOAD.HS" 131 %elif _LZD 132 strdef PAYLOAD_FILE, "lDOSLOAD.LZ" 133 %elif _LZO 134 strdef PAYLOAD_FILE, "lDOSLOAD.LZO" 135 %elif _LZSA2 136 strdef PAYLOAD_FILE, "lDOSLOAD.SA2" 137 %elif _APL 138 strdef PAYLOAD_FILE, "lDOSLOAD.APL" 139 %elif _BZP 140 strdef PAYLOAD_FILE, "lDOSLOAD.BZP" 141 %elif _ZEROCOMP 142 strdef PAYLOAD_FILE, "lDOSLOAD.ZER" 143 %elif _MVCOMP 144 strdef PAYLOAD_FILE, "lDOSLOAD.MV" 145 %elif _LZEXEDAT 146 strdef PAYLOAD_FILE, "lDOSLOAD.LZE" 147 %elif _ZX0 148 strdef PAYLOAD_FILE, "lDOSLOAD.ZX0" 149 %endif 150 numdef PAYLOAD_KERNEL_MAX_PARAS, 0, 0 151 %if _PAYLOAD_KERNEL_MAX_PARAS && ! (_IMAGE_EXE || _DEVICE) 152 %error Kernel mode max paras requires building dual-mode or triple-mode executable 153 %endif 154 numdef COUNTER, 0, 32 155 %if (_COUNTER - 1) & _COUNTER 156 %error COUNTER must be a power of two 157 %endif 158 numdef PROGRESS, 0, 1 159 numdef PROGRESSAMOUNT, 0, 0 160 numdef PROGRESSMULTI, 1 161 numdef PROGRESSVAR, 1 162 numdef PROGRESSVARNAME, "" 163 numdef PROGRESSDEFAULT, 0 164 numdef PROGRESSDEFAULTAPP, _PROGRESSDEFAULT 165 numdef PROGRESSDEFAULTDEVICE, _PROGRESSDEFAULT 166 numdef PROGRESSDEFAULTBOOT,1 167 numdef PASSLCFG, 0 168 numdef LCFG, (_PROGRESS && _PROGRESSMULTI) || _PASSLCFG 169 170 171 %define MODULE inicomp 172 strdef INILOAD_CFG, "" 173 %ifnidn _INILOAD_CFG, "" 174 %include _INILOAD_CFG 1 <1> ; File auto-generated, do not edit. 2 <1> strdef INILOAD_SIGNATURE, "TR" 3 <1> %assign _DEVICE 0 4 <1> %ifidni MODULE, directpl 5 <1> %define _PAYLOAD_FILE "testrand.bin" 6 <1> %endif 7 <1> %ifn _TEST_PROGRAM 8 <1> numdef IMAGE_EXE, 0 9 <1> numdef SECOND_PAYLOAD_EXE, 0 10 <1> %endif 175 %endif 176 strdef LCFG_CFG, "" 177 178 %if _DEVICE 179 %ifidn _DEVICE_NAME, "" 180 %error Device name must be set 181 %endif 182 %endif 183 184 struc XMSM 185 00000000 ???????? .size_: resd 1 186 00000004 ???? .srchdl: resw 1 187 00000006 ???????? .srcadr: resd 1 188 0000000A ???? .dsthdl: resw 1 189 0000000C ???????? .dstadr: resd 1 190 endstruc 191 192 193 cpu 8086 194 %ifn _SCAN 195 196 addsection INIT0, start=0 vstart=0 197 init0_start: 198 %if _DEVICE 199 ; The device header is of a fixed format. 200 ; For our purposes, the 4-byte code for 201 ; each the strategy entry and the 202 ; interrupt entry is part of this format. 203 ; (DOS may read the attributes or entrypoint 204 ; offsets before calling either, so in the inicomp 205 ; stage we need to recreate in the entrypoints part 206 ; exactly what the application has here.) 207 ; _PASSLCFG: The lCFG block is passed in the dword 208 ; behind the interrupt entry. 209 device_header: 210 .next: 211 %if _DEVICE_ZERO_ENTRYPOINT 212 fill 2, -1, jmp strict short j_zero_entrypoint 213 dw -1 214 %else 215 dd -1 ; link to next device 216 %endif 217 .attributes: 218 dw _DEVICE_ATTRIBUTE ; attributes 219 .strategy: 220 dw .strategy_entry ; -> strategy entry 221 .interrupt: 222 dw .interrupt_entry ; -> interrupt entry 223 .name: 224 fill 8, 32, db _DEVICE_NAME ; character device name, 225 ; or block device number of units 226 ; + optional name 227 .strategy_entry: 228 fill 4, 90h, jmp device_entrypoint 229 .interrupt_entry: 230 fill 4, 90h, retf 231 .pass_lcfg: 232 %endif 233 234 235 %if _IMAGE_EXE || _DEVICE 236 00000000 90 nop 237 00000001 90 align 32, nop 238 init0_kernel_entry: 239 ; cs:ip = load seg : 32 here 240 %if ($ - $$) != 32 241 %error Wrong kernel mode entrypoint 242 %endif 243 %if _TEST_PROGRAM 244 @@: 245 00000020 CC int3 246 00000021 FB sti 247 00000022 F4 hlt 248 00000023 EBFB jmp @B 249 %endif 250 %if _BOOTLDR 251 %if ! _IMAGE_EXE 252 j_zero_entrypoint: 253 %endif 254 00000025 31DB xor bx, bx ; 0 = kernel mode 255 00000027 50 push ax 256 00000028 8CC8 mov ax, cs 257 0000002A 83C040 add ax, (init0_end - init0_start) >> 4 258 0000002D 8B56E2 mov dx, word [ bp + ldLoadTop ] ; => after end of available space 259 00000030 BE6000 mov si, 60h ; => destination 260 00000033 E9AF00 jmp init0_common 261 %endif 262 263 %if _IMAGE_EXE 264 00000036 90 align 64, nop 265 j_zero_entrypoint: 266 init0_exe_entry: 267 ; NOTE: This part is called with ip = 256 + 64, cs = PSP. 268 %if ($ - $$) != 64 269 %error Wrong EXE mode entrypoint 270 %endif 271 %if _IMAGE_EXE_GET_COM_STACK 272 mov bx, ds ; => PSP 273 dec bx ; => MCB 274 mov ds, bx 275 add bx, word [3] ; add size of memory block 276 sub bx, -1 + paras(512) ; add one, then subtract enough paragraphs 277 cli 278 mov ss, bx 279 mov sp, 512 ; -> new stack 280 sti 281 %endif 282 00000040 BB0100 mov bx, 1 ; EXE mode 283 00000043 50 push ax 284 %if _TEST_PROGRAM 285 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 286 00000044 1E push ds 287 00000045 A12C00 mov ax, word [2Ch] ; => environment 288 00000048 85C0 test ax, ax 289 0000004A 7503 jnz @F 290 .errorfile: 291 0000004C E9EC00 jmp init0_error_file 292 @@: 293 0000004F 8ED8 mov ds, ax 294 00000051 B90080 mov cx, 8000h 295 00000054 31F6 xor si, si ; -> environment 296 @@: 297 00000056 AC lodsb 298 00000057 84C0 test al, al 299 00000059 E0FB loopnz @B ; si -> past one NUL 300 0000005B E3EF jcxz .errorfile 301 0000005D 803C00 cmp byte [si], 0 ; -> another NUL ? 302 00000060 E0F4 loopne @B ; no, skip next variable --> 303 00000062 E3E8 jcxz .errorfile 304 00000064 46 inc si ; skip double NUL 305 00000065 AD lodsw ; load amount strings after environment 306 00000066 83F801 cmp ax, 1 ; 1 ? 307 00000069 75E1 jne .errorfile ; no --> 308 0000006B 89F2 mov dx, si ; ds:dx -> executable pathname 309 0000006D B8203D mov ax, 3D00h + 0_010_0_000b ; deny write, read only 310 00000070 CD21 int 21h ; open 311 00000072 72D8 jc .errorfile 312 00000074 1F pop ds ; restore => PSP 313 00000075 50 push ax ; push into ?handle 314 %endif 315 316 00000076 BE8100 mov si, 81h 317 00000079 31D2 xor dx, dx 318 0000007B 31C0 xor ax, ax 319 cmdline: 320 .: 321 0000007D AC lodsb 322 0000007E 3C09 cmp al, 9 323 00000080 74FB je . 324 00000082 3C20 cmp al, 32 325 00000084 74F7 je . 326 00000086 3C0D cmp al, 13 327 00000088 744E je .end 328 0000008A 3C30 cmp al, '0' 329 0000008C 721E jb .notdigit 330 0000008E 3C39 cmp al, '9' 331 00000090 771A ja .notdigit 332 .digit: 333 00000092 2C30 sub al, '0' 334 00000094 89D1 mov cx, dx ; times 1 335 00000096 01D2 add dx, dx 336 00000098 722A jc .invalid 337 0000009A 01D2 add dx, dx ; times 4 338 0000009C 7226 jc .invalid 339 0000009E 01CA add dx, cx ; times 5 340 000000A0 7222 jc .invalid 341 000000A2 01D2 add dx, dx ; times 10 342 000000A4 721E jc .invalid 343 000000A6 01C2 add dx, ax ; add in low digit 344 000000A8 721A jc .invalid 345 000000AA EBD1 jmp . 346 347 .notdigit: 348 000000AC 3C41 cmp al, 'A' 349 000000AE 7419 je .a 350 000000B0 3C61 cmp al, 'a' 351 000000B2 7415 je .a 352 000000B4 3C42 cmp al, 'B' 353 000000B6 7416 je .b 354 000000B8 3C62 cmp al, 'b' 355 000000BA 7412 je .b 356 000000BC 3C43 cmp al, 'C' 357 000000BE 7413 je .c 358 000000C0 3C63 cmp al, 'c' 359 000000C2 740F je .c 360 .invalid: 361 000000C4 BAFFFF mov dx, -1 ; invalid 362 000000C7 EB0F jmp .end 363 364 .a: 365 000000C9 80E77F and bh, ~ 80h ; A mode. determine min alloc size 366 000000CC EBAF jmp . 367 368 .b: 369 000000CE 80CF80 or bh, 80h ; B mode. repeat depack, counter in command line 370 000000D1 EBAA jmp . 371 372 .c: 373 000000D3 80CF40 or bh, 40h ; C mode. how often would the counter be called 374 000000D6 EBA5 jmp . 375 376 .end: 377 ; bx for ?whichtest 378 000000D8 52 push dx ; for ?repetitions 379 %endif 380 000000D9 8CD2 mov dx, ss ; => after end of available space 381 000000DB 8CC8 mov ax, cs 382 000000DD 83C050 add ax, (256 + (init0_end - init0_start)) >> 4 ; => source 383 000000E0 8CCE mov si, cs 384 000000E2 83C610 add si, 256 >> 4 ; => destination 385 %endif 386 387 init0_common: 388 ; REM: This part must be position-independent, as it is 389 ; called either with ip = init0_common (kernel mode 390 ; or device mode) 391 ; or ip = init0_common + 256 (application mode). 392 ; INP: si => depack destination 393 ; ax => source of payload + INIT1 394 ; dx => behind available memory 395 ; OUT: cs:ip -> init1_start: 396 ; ax => INIT1 397 ; dx => payload source 398 ; si => depack destination 399 ; bx = mode 400 000000E5 FC cld 401 %if _TEST_PROGRAM 402 %ifn _RELOAD_XMS || _RELOAD_FILE 403 000000E6 81EA0420 sub dx, ( (payload_end - payload) ) >> 4 404 000000EA 721A jc .error 405 %endif 406 000000EC B99E20 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) + (init2_end - init2_start) ) >> 4 412 000000EF 29CA sub dx, cx 413 000000F1 7213 jc .error 414 000000F3 39C2 cmp dx, ax 415 000000F5 720F jb .error 416 %else 417 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 422 ; cx = amount paragraphs in INIT0B + payload + INIT1 423 sub dx, cx ; => destination for INIT0B + payload + INIT1 424 ; (highest possible spot in available memory) 425 %endif 426 000000F7 56 push si ; preserve destination 427 000000F8 E88500 call init0_movp ; move up payload + INIT1 428 000000FB 5E pop si 429 %else 430 cld 431 mov ax, cs 432 add ax, (init0_end - init0_start) >> 4 433 mov cx, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 438 mov dx, word [ bp + ldLoadTop ] 439 sub dx, cx 440 call init0_movp 441 %endif 442 443 %if _LCFG && ! _TEST_PROGRAM 444 push cs 445 call @F ; position-independent far pointer 446 @@: 447 pop ax 448 add ax, lcfg - @B ; -> lCFG block 449 push ax 450 %endif 451 452 000000FC 89D0 mov ax, dx ; => INIT0B 453 ; (same as => payload if INIT0B is empty) 454 %if (_LCFG || _PROGRESS) && ! _TEST_PROGRAM 455 add dx, ( + (init0b_end - init0b_start) ) >> 4 ; => payload 458 %else 459 %if _TEST_PROGRAM 460 000000FE 056320 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) >> 4 ; => INIT2 465 %else 466 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 470 %endif 471 %endif 472 00000101 31C9 xor cx, cx 473 00000103 50 push ax 474 00000104 51 push cx 475 00000105 CB retf ; jump to relocated 476 ; INIT0B:init0b_start 477 ; or INIT1:init1_start 478 ; or INIT2:init2_start 479 480 481 %if _TEST_PROGRAM 482 .error: 483 00000106 89DF mov di, bx ; whichtest 484 485 00000108 0E push cs 486 00000109 1F pop ds 487 0000010A BA[2E03] mov dx, init0_msg.error_stderr + 256 488 0000010D B92500 mov cx, init0_msg.error_stderr.length 489 00000110 BB0200 mov bx, 2 490 00000113 B440 mov ah, 40h 491 00000115 CD21 int 21h 492 493 00000117 F7C70040 test di, 4000h ; whichtest 494 0000011B 7408 jz @F 495 0000011D BA[5303] mov dx, init0_msg.error_c_stdout + 256 496 00000120 B90300 mov cx, init0_msg.error_c_stdout.length 497 00000123 EB0A jmp @FF 498 @@: 499 00000125 85FF test di, di ; whichtest 500 00000127 780D js @FF 501 00000129 BA[5303] mov dx, init0_msg.error_stdout + 256 502 0000012C B90300 mov cx, init0_msg.error_stdout.length 503 @@: 504 0000012F BB0100 mov bx, 1 505 00000132 B440 mov ah, 40h 506 00000134 CD21 int 21h 507 @@: 508 00000136 B8FF4C mov ax, 4CFFh 509 00000139 CD21 int 21h 510 511 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 512 init0_error_file: 513 0000013B BA[0203] mov dx, init0_msg.error_stderr_file + 256 514 0000013E B92C00 mov cx, init0_msg.error_stderr_file.length 515 00000141 0E push cs 516 00000142 1F pop ds 517 00000143 BB0200 mov bx, 2 518 00000146 B440 mov ah, 40h 519 00000148 CD21 int 21h 520 521 0000014A BA[5303] mov dx, init0_msg.error_stdout + 256 522 0000014D B90300 mov cx, init0_msg.error_stdout.length 523 00000150 BB0100 mov bx, 1 524 00000153 B440 mov ah, 40h 525 00000155 CD21 int 21h 526 00000157 B8FF4C mov ax, 4CFFh 527 0000015A CD21 int 21h 528 %endif 529 530 %endif 531 532 533 %if _LCFG 534 %imacro lcfgoption 3+.nolist 535 _fill %1, 0, lcfg 536 %%start: 537 %2 538 %3 539 %%end: 540 %assign %%index %%start - lcfg 541 %rep %%end - %%start 542 %assign LCFGINUSE LCFGINUSE | (1 << %%index) 543 %assign %%index %%index + 1 544 %endrep 545 %endmacro 546 %assign LCFGINUSE 0 547 548 0000015C 90 align 16 549 lcfg: 550 00000160 EB1E .: jmp strict short .end 551 00000162 6C434647 lcfgoption 2,, db "lCFG" 552 00000166 3030 lcfgoption 6,, db "00" 553 00000168 FCFF050000000000 lcfgoption 8,, dq .inuse 554 %if _PROGRESS && _PROGRESSMULTI 555 %if _IMAGE_EXE 556 00000170 00 lcfgoption 16, .progress_app:, db _PROGRESSDEFAULTAPP 557 %endif 558 %if _DEVICE 559 lcfgoption 17, .progress_dev:, db _PROGRESSDEFAULTDEVICE 560 %endif 561 %if _BOOTLDR 562 00000171 0001 lcfgoption 18, .progress_boot:, db _PROGRESSDEFAULTBOOT 563 %endif 564 %endif 565 566 %ifnidn _LCFG_CFG, "" 567 %include _LCFG_CFG 1 <1> ; File auto-generated, do not edit. 568 %endif 569 570 00000173 00 lcfgoption 32,, 571 .end: 572 .size: equ .end - . 573 .inuse equ LCFGINUSE 574 %endif 575 576 577 %if _DEVICE 578 device_entrypoint: 579 %if _TEST_PROGRAM 580 @@: 581 int3 582 sti 583 hlt 584 jmp @B 585 %endif 586 cmp byte [es:bx + 2], 0 ; command code 0 (init) ? 587 je @F 588 589 mov word [es:bx + 3], 8103h ; error, done, code: unknown command 590 retf 591 592 @@: 593 or word [cs:device_header.next], -1 594 push cs 595 push word [cs:device_header.strategy] 596 ; -> far return to payload's strategy 597 push bp 598 push ds 599 push si 600 push di 601 push dx 602 push cx 603 push ax 604 push bx 605 push es 606 607 mov dx, word [es:bx + 14] 608 mov cl, 4 609 shr dx, cl ; = how many full paragraphs (rounded down) 610 add dx, word [es:bx + 14 + 2] 611 ; ax => behind end 612 613 mov di, cs 614 image_size: equ ( + (init0_end - init0_start) + (init0b_end - init0b_start) + (payload_end - payload) + (init1_end - init1_start) ) 620 add di, image_size >> 4 ; di => end of image 621 622 cmp dx, di ; enough memory to hold all of us ? 623 jb @F ; no --> 624 ; yes 625 .have_some_memory: 626 ; dx => after end of memory 627 mov bx, 2 ; device mode 628 push ax 629 mov ax, cs 630 add ax, (init0_end - init0_start) >> 4 631 mov si, cs ; => destination 632 jmp init0_common 633 634 635 @@: 636 push cs 637 pop ds 638 mov dx, .msg_no_memory 639 mov ah, 09h 640 int 21h 641 642 mov ax, 3000h 643 int 21h 644 cmp al, 5 645 jae @F 646 mov dx, .msg_dos_below_5 647 mov ah, 09h 648 int 21h 649 @@: 650 651 mov dx, .msg_linebreak 652 mov ah, 09h 653 int 21h 654 655 ; tear down the stack frame and modify the request header 656 pop es 657 pop bx 658 mov word [es:bx + 3], 8103h ; set error, done, invalid command 659 mov byte [es:bx + 13], 0 ; set number of units = 0 660 mov word [es:bx + 14 + 2], cs 661 and word [es:bx + 14], 0 ; -> after end of memory to allocate 662 pop ax 663 pop cx 664 pop dx 665 pop di 666 pop si 667 pop ds 668 pop bp 669 add sp, 4 ; discard far return to payload's strategy 670 retf ; return to DOS 671 672 673 .msg_no_memory: ascic "Load error: Not enough memory." 674 .msg_dos_below_5: ascic " Note: DOS must be at least version 5." 675 .msg_linebreak: ascic 13,10 676 %endif 677 678 679 ; Move paragraphs 680 ; 681 ; INP: ax => source 682 ; dx => destination 683 ; cx = number of paragraphs 684 ; CHG: cx, ds, si, es, di 685 ; OUT: ax and dx unchanged 686 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 687 ; Do not provide a wrapped/HMA source or destination! 688 init0_movp: 689 00000180 39D0 cmp ax, dx ; source above destination ? 690 00000182 770A ja .up ; yes, move up (forwards) --> 691 00000184 747B je .return ; same, no need to move --> 692 00000186 50 push ax 693 00000187 01C8 add ax, cx ; (expected not to carry) 694 00000189 39D0 cmp ax, dx ; end of source is above destination ? 695 0000018B 58 pop ax 696 0000018C 7730 ja .down ; yes, move from top down --> 697 ; Here, the end of source is below-or-equal the destination, 698 ; so they do not overlap. In this case we prefer moving up. 699 700 .up: 701 0000018E 50 push ax 702 0000018F 52 push dx 703 .uploop: 704 00000190 8ED8 mov ds, ax 705 00000192 8EC2 mov es, dx 706 00000194 31FF xor di, di 707 00000196 31F6 xor si, si ; -> start of segment 708 00000198 81E90010 sub cx, 1000h ; 64 KiB left ? 709 0000019C 7610 jbe .uplast ; no --> 710 0000019E 51 push cx 711 0000019F B90080 mov cx, 10000h /2 712 000001A2 F3A5 rep movsw ; move 64 KiB 713 000001A4 59 pop cx 714 000001A5 050010 add ax, 1000h 715 000001A8 81C20010 add dx, 1000h ; -> next segment 716 000001AC EBE2 jmp short .uploop ; proceed for more --> 717 .uplast: 718 000001AE 81C10010 add cx, 1000h ; restore counter 719 000001B2 D1E1 shl cx, 1 720 000001B4 D1E1 shl cx, 1 721 000001B6 D1E1 shl cx, 1 ; *8, paragraphs to words 722 000001B8 F3A5 rep movsw ; move last part 723 000001BA 5A pop dx 724 000001BB 58 pop ax 725 000001BC EB43 jmp short .return 726 727 .down: 728 000001BE FD std ; _AMD_ERRATUM_109_WORKAROUND as below 729 .dnloop: 730 000001BF 81E90010 sub cx, 1000h ; 64 KiB left ? 731 000001C3 761A jbe .dnlast ; no --> 732 000001C5 50 push ax 733 000001C6 52 push dx 734 000001C7 01C8 add ax, cx 735 000001C9 01CA add dx, cx 736 000001CB 8ED8 mov ds, ax ; -> 64 KiB not yet moved 737 000001CD 8EC2 mov es, dx 738 000001CF 5A pop dx 739 000001D0 58 pop ax 740 000001D1 BFFEFF mov di, -2 741 000001D4 89FE mov si, di ; moved from last word down 742 000001D6 51 push cx 743 000001D7 B90080 mov cx, 10000h /2 744 000001DA F3A5 rep movsw ; move 64 KiB 745 000001DC 59 pop cx 746 000001DD EBE0 jmp short .dnloop ; proceed for more --> 747 .dnlast: 748 000001DF 81C10010 add cx, 1000h ; restore counter 749 000001E3 D1E1 shl cx, 1 750 000001E5 D1E1 shl cx, 1 751 000001E7 D1E1 shl cx, 1 ; *8, paragraphs to words 752 000001E9 89CF mov di, cx 753 000001EB 4F dec di 754 000001EC D1E7 shl di, 1 ; words to offset, -> last word 755 000001EE 89FE mov si, di 756 000001F0 8ED8 mov ds, ax 757 000001F2 8EC2 mov es, dx ; first segment correct 758 759 760 numdef AMD_ERRATUM_109_WORKAROUND, 1 761 %if 0 762 763 Jack R. Ellis pointed out this erratum: 764 765 Quoting from https://www.amd.com/system/files/TechDocs/25759.pdf page 69: 766 767 109 Certain Reverse REP MOVS May Produce Unpredictable Behavior 768 769 Description 770 771 In certain situations a REP MOVS instruction may lead to 772 incorrect results. An incorrect address size, data size 773 or source operand segment may be used or a succeeding 774 instruction may be skipped. This may occur under the 775 following conditions: 776 777 * EFLAGS.DF=1 (the string is being moved in the reverse direction). 778 779 * The number of items being moved (RCX) is between 1 and 20. 780 781 * The REP MOVS instruction is preceded by some microcoded instruction 782 that has not completely retired by the time the REP MOVS begins 783 execution. The set of such instructions includes BOUND, CLI, LDS, 784 LES, LFS, LGS, LSS, IDIV, and most microcoded x87 instructions. 785 786 Potential Effect on System 787 788 Incorrect results may be produced or the system may hang. 789 790 Suggested Workaround 791 792 Contact your AMD representative for information on a BIOS update. 793 794 %endif 795 796 %if _AMD_ERRATUM_109_WORKAROUND 797 000001F4 E308 jcxz @FF 798 000001F6 83F914 cmp cx, 20 799 000001F9 7703 ja @FF 800 @@: 801 000001FB A5 movsw 802 000001FC E2FD loop @B 803 @@: 804 %endif 805 000001FE F3A5 rep movsw ; move first part 806 00000200 FC cld 807 .return: 808 00000201 C3 retn 809 810 811 addsection INIT0B, align=16 vstart=0 follows=INIT0 812 ; INP: ax:cx = cs:ip = cs:0 813 ; ax => INIT0B 814 ; dx => payload source 815 ; ss:sp -> (dword pointer to lCFG block) 816 ; if app/device mode supported: 817 ; si => depack destination 818 ; bx = mode 819 init0b_start: 820 %if _LCFG || _PROGRESS 821 822 00000000 051420 add ax, ( + (init0b_end - init0b_start) + (payload_end - payload) ) >> 4 ; => INIT1 826 827 %if _LCFG && _PASSLCFG 828 %if (_IMAGE_EXE || _DEVICE) 829 mov cx, si ; preserve si 830 %endif 831 pop si 832 pop ds ; -> lCFG block 833 mov es, ax 834 mov di, transfer_lcfg_block 835 ; -> destination 836 %if (_IMAGE_EXE || _DEVICE) 837 push cx 838 %endif 839 push di 840 mov cx, words(lcfg.size) 841 rep movsw ; cx = 0 842 pop di ; es:di -> relocated lCFG block, same difference 843 %if (_IMAGE_EXE || _DEVICE) 844 pop si ; preserve si 845 %endif 846 %elif _LCFG 847 00000003 5F pop di 848 00000004 07 pop es ; es:di -> (original) lCFG block 849 %endif 850 851 00000005 50 push ax 852 00000006 51 push cx ; -> far return address to init1_start 853 854 %if _PROGRESS && _PROGRESSMULTI 855 %if (_IMAGE_EXE || _DEVICE) 856 00000007 56 push si 857 00000008 53 push bx 858 %endif 859 %if _BOOTLDR 860 %if _LCFG 861 00000009 31C0 xor ax, ax 862 0000000B 268A4512 mov al, byte [es:di + lcfg.progress_boot - lcfg] 863 0000000F 97 xchg di, ax ; di = boot default progress 864 ; es:ax -> lCFG block 865 %else ; _LCFG 866 mov di, _PROGRESSDEFAULTBOOT 867 %endif ; _LCFG 868 %endif ; _BOOTLDR 869 %if (_IMAGE_EXE || _DEVICE) 870 %if _BOOTLDR 871 00000010 85DB test bx, bx 872 00000012 7503E9A700 jz .default 873 %endif ; _BOOTLDR 874 %if _LCFG 875 00000017 06 push es 876 %if _BOOTLDR 877 00000018 50 push ax ; -> lCFG block 878 %else ; _BOOTLDR 879 push di 880 %endif ; _BOOTLDR 881 %endif ; _LCFG 882 %if _PROGRESSVAR 883 00000019 B451 mov ah, 51h 884 0000001B CD21 int 21h 885 @@: 886 0000001D 8EDB mov ds, bx 887 0000001F A12C00 mov ax, word [2Ch] 888 00000022 85C0 test ax, ax 889 00000024 7510 jnz .gotenv 890 00000026 A11600 mov ax, word [16h] 891 00000029 40 inc ax 892 0000002A 7469 jz .default_nonboot 893 0000002C 48 dec ax 894 0000002D 7466 jz .default_nonboot 895 0000002F 39C3 cmp bx, ax 896 00000031 7462 je .default_nonboot 897 00000033 93 xchg bx, ax 898 00000034 EBE7 jmp @B 899 900 .gotenv: 901 00000036 0E push cs 902 00000037 1F pop ds ; => cs 903 00000038 8EC0 mov es, ax ; => environment 904 %ifnidni _PROGRESSVARNAME, "" 905 0000003A BB[EA00] mov bx, progressvarname1 906 0000003D E80C00 call .findenv 907 00000040 732E jnc .foundenv ; match --> 908 00000042 BB[ED00] mov bx, progressvarname2 909 %endif 910 00000045 E80400 call .findenv 911 00000048 7326 jnc .foundenv ; match --> 912 0000004A EB49 jmp .default_nonboot 913 914 .findenv: 915 0000004C 31FF xor di, di 916 @@: 917 %ifnidni _PROGRESSVARNAME, "" 918 0000004E 89DE mov si, bx ; -> variable name 919 %else 920 mov si, progressvarname2 ; -> variable name 921 %endif 922 00000050 31C0 xor ax, ax 923 00000052 AC lodsb ; get length 924 00000053 91 xchg cx, ax ; cx = length 925 00000054 57 push di 926 00000055 F3A6 repe cmpsb ; match ? 927 00000057 7415 je .findret_pop ; (NC) yes --> 928 00000059 5F pop di 929 0000005A B90080 mov cx, 8000h ; maximum env size 930 0000005D 29F9 sub cx, di ; any left ? 931 0000005F 760B jbe .findret_CY ; no --> 932 00000061 B000 mov al, 0 933 00000063 F2AE repne scasb ; find next NUL 934 00000065 7505 jne .findret_CY 935 00000067 263805 cmp byte [es:di], al ; double NUL ? 936 0000006A 75E2 jne @B ; no, loop --> 937 .findret_CY: 938 0000006C F9 stc ; not found 939 0000006D C3 retn 940 941 .findret_pop: 942 0000006E 59 pop cx 943 0000006F C3 retn 944 945 .foundenv: 946 %if _LCFG 947 00000070 5E pop si 948 00000071 5E pop si ; discard far pointer to lCFG 949 %endif 950 00000072 89FE mov si, di ; es:si -> var content 951 00000074 31FF xor di, di ; = 0 952 00000076 31C0 xor ax, ax ; ah = 0 953 @@: 954 00000078 26AC es lodsb ; next candidate digit 955 0000007A 2C30 sub al, '0' ; digit ? 956 0000007C 7212 jb @F ; no --> 957 0000007E 3C09 cmp al, 9 958 00000080 770E ja @F ; no --> 959 00000082 01FF add di, di ; times 2 960 00000084 89FB mov bx, di 961 00000086 01FF add di, di ; times 4 962 00000088 01FF add di, di ; times 8 963 0000008A 01DF add di, bx ; times 8 + times 2 = times 10 964 0000008C 01C7 add di, ax ; add in next digit 965 0000008E EBE8 jmp @B ; and loop 966 967 @@: 968 00000090 83E71F and di, 31 ; mask to low 5 bits 969 00000093 EB0B jmp @F 970 %endif ; _PROGRESSVAR 971 972 .default_nonboot: 973 %if _LCFG 974 00000095 5F pop di 975 00000096 07 pop es ; -> lCFG block 976 00000097 5B pop bx ; = 1 if app, = 2 if device 977 00000098 53 push bx 978 00000099 268B4510 mov ax, word [es:di + lcfg.progress_app - lcfg] 979 %if _DEVICE 980 %if lcfg.progress_app + 1 != lcfg.progress_dev 981 %error Unexpected layout 982 %endif 983 ; al = app, ah = device 984 dec bx 985 jz .default_app 986 xchg al, ah ; al = device 987 .default_app: 988 %endif ; _DEVICE 989 0000009D B400 mov ah, 0 ; ax = default 990 0000009F 97 xchg di, ax ; di = default 991 %else ; _LCFG 992 mov di, _PROGRESSDEFAULT 993 %endif ; _LCFG 994 @@: 995 000000A0 F7C71000 test di, 16 996 000000A4 7405 jz @F 997 000000A6 83E7EF and di, ~16 998 000000A9 EB13 jmp .outputdevice ; if 16 set skip device check 999 @@: 1000 000000AB 52 push dx 1001 000000AC B80044 mov ax, 4400h ; IOCTL get device information 1002 000000AF BB0100 mov bx, 1 ; StdOut 1003 000000B2 B283 mov dl, 83h ; default if 21.4400 fails 1004 000000B4 CD21 int 21h 1005 000000B6 F6C280 test dl, 80h 1006 000000B9 5A pop dx 1007 000000BA 7502 jnz .outputdevice 1008 000000BC 31FF xor di, di ; stdout is a file: force no progress marker 1009 .outputdevice: 1010 %endif ; (_IMAGE_EXE || _DEVICE) 1011 1012 .default: 1013 %if (_IMAGE_EXE || _DEVICE) 1014 000000BE 5B pop bx 1015 000000BF 5E pop si 1016 %endif 1017 000000C0 83FF05 cmp di, step_progress_table.amount 1018 ; valid ? 1019 000000C3 7202 jb @F ; yes --> 1020 000000C5 31FF xor di, di ; disable 1021 @@: 1022 000000C7 D1E7 shl di, 1 ; = word index 1023 000000C9 59 pop cx ; = 0 1024 000000CA 1F pop ds ; ds => INIT1 1025 1026 000000CB 2E8B85[E000] mov ax, word [cs:step_progress_table + di] 1027 ; ax = rel16 for step progress handler 1028 000000D0 1E push ds 1029 000000D1 51 push cx ; -> init1_start 1030 000000D2 A3[6900] mov word [step_progress.handler], ax 1031 ; patch it 1032 1033 000000D5 83FF04 cmp di, 2 * 2 ; none or dots ? 1034 000000D8 7305 jae @F ; no, skip --> 1035 000000DA C606[0600]A9 mov byte [..@empty_step_progress], __TEST_IMM16 1036 ; for none and dots do not call here 1037 @@: 1038 %endif ; _PROGRESS && _PROGRESSMULTI 1039 000000DF CB retf 1040 %endif 1041 1042 %if _PROGRESS && _PROGRESSMULTI 1043 align 2, db 0 1044 step_progress_table: 1045 .: 1046 000000E0 1600 dw step_progress.0_step - step_progress.base 1047 000000E2 3B00 dw step_progress.1_step - step_progress.base 1048 000000E4 0000 dw step_progress.2_step - step_progress.base 1049 000000E6 4100 dw step_progress.3_step - step_progress.base 1050 000000E8 8600 dw step_progress.4_step - step_progress.base 1051 .amount equ ($ - .) / 2 1052 1053 %if _PROGRESSVAR && (_IMAGE_EXE || _DEVICE) 1054 %ifnidni _PROGRESSVARNAME, "" 1055 000000EA 02003D progressvarname1: counted _PROGRESSVARNAME, '=' 1056 %endif 1057 000000ED 0D4C444F5350524F47- progressvarname2: counted "LDOSPROGRESS=" 1057 000000F6 524553533D 1058 %endif 1059 %endif 1060 1061 000000FB 90 align 16 1062 init0b_end: 1063 1064 1065 addsection PAYLOAD, align=16 follows=INIT0B 1066 payload: 1067 00000000 incbin _PAYLOAD_FILE 1068 .end: 1069 0002003B 26 align 16, db 38 1070 payload_end: 1071 1072 %if _OPTIMISE_INPUT_SMALL 1073 %ifn (payload_end - payload) <= 65_520 1074 %error Input declared small is not small 1075 %endif 1076 %else 1077 %if (payload_end - payload) <= 65_520 1078 %warning Input could be declared small 1079 %endif 1080 %endif 1081 1082 1083 addsection INIT1, align=16 follows=PAYLOAD vstart=0 1084 init1_start: 1085 ; INP: ax = cs = INIT1 1086 ; dx = cs - (payload_end - payload) >> 4 => source data 1087 ; if kernel mode: 1088 ; ss:bp -> LOADDATA and LOADSTACKVARS 1089 ; ss:sp -> valid stack above [bp + ldLoadTop] 1090 ; 60h => destination 1091 ; any mode: 1092 ; ss:sp -> word value for ax 1093 ; bx = 2 if device mode, 1 if EXE mode, 0 if kernel mode 1094 ; si => destination (60h for kernel mode, 1095 ; after PSP for EXE mode, 1096 ; at device header for device mode) 1097 ; (not set if only kernel mode supported) 1098 ; if EXE mode: 1099 ; ss:sp -> valid stack above INIT1 1100 ; bp = unset 1101 ; if device mode: 1102 ; ss:sp -> device entrypoint stack 1103 ; holds: es, bx, ax, cx, dx, di, si, ds, bp, 1104 ; far address of payload strategy entrypoint, 1105 ; far return address to DOS 1106 ; bp = unset 1107 ; STT: UP 1108 ; CHG: ax, bx, cx, dx, es, ds, si, di 1109 %if _IMAGE_EXE || _DEVICE 1110 lframe 1111 00000000 5589E5 lenter 1112 lvar word, exemode ; must be bp - 2! 1113 00000003 53 push bx 1114 %if ?exemode != -2 1115 %error exemode variable must be directly below bp 1116 %endif 1117 00000004 56 push si 1118 %if _PROGRESS 1119 00000005 F8 clc ; NC 1120 %endif 1121 %else 1122 xor bx, bx ; always tell them it is kernel mode (NC) 1123 %endif 1124 1125 %if _PROGRESS 1126 ; clc 1127 ..@empty_step_progress: ; SMC, byte patched to __TEST_IMM16 if none or dots 1128 %if _TEST_PROGRAM 1129 00000006 90 times 3 nop 1130 %else 1131 call step_progress.CF ; display empty / 0.0% 1132 %endif 1133 @@: 1134 %endif 1135 1136 %if _IMAGE_EXE || _DEVICE 1137 00000009 8EC6 mov es, si ; es => destination 1138 %else 1139 mov ax, 60h 1140 mov es, ax ; es => destination 1141 %endif 1142 0000000B 31FF xor di, di ; -> destination 1143 1144 0000000D 8EDA mov ds, dx 1145 0000000F 31F6 xor si, si ; -> source 1146 1147 00000011 B93B00 mov cx, (payload.end - payload) & 0FFFFh 1148 %if (payload.end - payload) >> 16 1149 00000014 BA0200 mov dx, (payload.end - payload) >> 16 ; = length of source 1150 %else 1151 xor dx, dx 1152 %endif 1153 %if _PAYLOAD_KERNEL_MAX_PARAS 1154 mov ax, _PAYLOAD_KERNEL_MAX_PARAS 1155 test bx, bx 1156 jz @F 1157 %endif 1158 00000017 B8FFFF mov ax, -1 1159 @@: 1160 1161 ; INP: ds:si -> source 1162 ; dx:cx = length of source 1163 ; es:di -> destination (below source) 1164 ; bx = EXE mode flag 1165 ; (1 if EXE mode, 0 if kernel mode) 1166 ; (always 0 if this is a build without EXE mode) 1167 ; if _PAYLOAD_KERNEL_MAX_PARAS: 1168 ; ax = maximum amount in paragraphs of destination needed 1169 ; (-1 if full source should be decompressed) 1170 ; else: 1171 ; ax = -1 1172 ; Note: The destination reaches up to below the source. 1173 0000001A E8DE01 call depack 1174 %ifn _TEST_PROGRAM 1175 jc strict short error ; -2 (replaced by retf \ nop) 1176 %endif 1177 %if _IMAGE_EXE || _DEVICE 1178 0000001D 5E pop si ; si 1179 %if _TEST_PROGRAM 1180 0000001E 58 pop ax ; (discard ?exemode, leave bx as returned) 1181 %else 1182 pop bx ; ?exemode 1183 %endif 1184 0000001F 5D pop bp ; bp 1185 00000020 58 pop ax ; ax 1186 lleave ctx 1187 %endif 1188 %if _TEST_PROGRAM 1189 00000021 CB retf ; +1 (replace jc error) 1190 00000022 90 nop ; +1 1191 %endif 1192 1193 %if _DEVICE 1194 test bl, 2 1195 jz .jmp_exe_or_kernel_mode 1196 1197 .jmp_device_mode: 1198 mov ds, si 1199 or word [device_header.next], -1 1200 %if _LCFG && _PASSLCFG 1201 mov word [device_header.pass_lcfg], transfer_lcfg_block 1202 mov word [device_header.pass_lcfg + 2], cs 1203 %endif 1204 pop es 1205 pop bx 1206 pop ax 1207 pop cx 1208 pop dx 1209 pop di 1210 pop si 1211 pop ds 1212 pop bp 1213 retf ; transfer to payload strategy entrypoint 1214 ; still on stack: far return address to DOS 1215 1216 .jmp_exe_or_kernel_mode: 1217 %endif 1218 1219 %if _IMAGE_EXE 1220 00000023 F6C301 test bl, 1 1221 00000026 7410 jz .jmp_kernel_mode 1222 1223 .jmp_exe_mode: 1224 %if ! _IMAGE_EXE_AUTO_STACK 1225 mov cx, cs 1226 lea dx, [si + _IMAGE_EXE_SS] 1227 push dx ; stack = relocated ss value 1228 add dx, (_IMAGE_EXE_SP + 2 + 15) >> 4 1229 cmp cx, dx ; INIT1 code is above intended stack ? 1230 jae @F ; yes --> 1231 1232 lframe 1233 lenter 1234 lvar word, exemode 1235 push bx 1236 %if ?exemode != -2 1237 %error exemode variable must be directly below bp 1238 %endif 1239 mov bx, -1 ; unimplemented, return error 1240 jmp error 1241 lleave ctx 1242 @@: 1243 cli 1244 pop ss ; = relocated ss value 1245 mov sp, (_IMAGE_EXE_SP + 2) & 0FFFFh ; change stack 1246 sti 1247 %endif 1248 1249 00000028 31C9 xor cx, cx 1250 0000002A 51 push cx ; put zero on top of stack 1251 1252 %if _IMAGE_EXE_IP < 256 1253 mov cl, _IMAGE_EXE_IP 1254 %elif (_IMAGE_EXE_IP & 255) == 0 1255 mov ch, _IMAGE_EXE_IP >> 8 1256 %else 1257 0000002B B94001 mov cx, _IMAGE_EXE_IP 1258 %endif 1259 1260 %if _IMAGE_EXE_CS == -16 1261 0000002E 83C6F0 add si, -16 1262 00000031 8EDE mov ds, si 1263 00000033 8EC6 mov es, si 1264 %else 1265 lea dx, [si - 10h] ; => PSP 1266 mov ds, dx 1267 mov es, dx ; ds = es => PSP 1268 %if _IMAGE_EXE_CS 1269 add si, _IMAGE_EXE_CS ; = relocated cs value 1270 %endif 1271 %endif 1272 00000035 56 push si 1273 00000036 51 push cx 1274 %if _LCFG && _PASSLCFG 1275 mov di, transfer_lcfg_block 1276 mov cx, cs 1277 %endif 1278 00000037 CB retf ; jump to EXE mode of image 1279 1280 %endif 1281 .jmp_kernel_mode: 1282 %if _LCFG && _PASSLCFG 1283 mov di, transfer_lcfg_block 1284 mov cx, cs 1285 %endif 1286 00000038 EA00006000 jmp 60h + _EXEC_SEGMENT:_EXEC_OFFSET 1287 1288 1289 %if _TEST_PROGRAM 1290 disp_al_counter: 1291 0000003D 2EFF06[4300] inc word [cs:init1_c_mode_counter] ; 5 bytes 1292 00000042 C3 retn ; 1 byte 1293 1294 00000043 0000 init1_c_mode_counter: dw 0 ; 2 bytes, total 8 1295 %else 1296 %if _PROGRESS 1297 disp_al_counter equ step_progress 1298 %else 1299 disp_al_counter equ disp_al 1300 %endif 1301 %endif 1302 1303 1304 error: 1305 %ifn _TEST_PROGRAM ; 2 bytes 1306 push cs 1307 pop ds 1308 %endif 1309 %if _DEBUG0 1310 mov si, msg.error_begin 1311 call disp_error 1312 xchg ax, bx ; ax = error code 1313 call disp_ax_hex 1314 %ifn _TEST_PROGRAM ; 3 bytes 1315 mov si, msg.error_end 1316 %endif 1317 %else 1318 %ifn _TEST_PROGRAM ; 3 bytes 1319 mov si, msg.error 1320 %endif 1321 %endif 1322 %ifn _TEST_PROGRAM ; 3 bytes, total 2 + 3 + 3 = 8 1323 call disp_error 1324 %endif 1325 %if _DEVICE 1326 test byte [bp - 2], 2 1327 jz .exit_app_or_kernel 1328 1329 pop si ; => device segment 1330 pop bx ; mode word 1331 pop bp 1332 pop ax 1333 mov es, si 1334 xor di, di ; -> device header 1335 push cs 1336 pop ds 1337 mov si, device_header_copy ; -> to reset header 1338 mov cx, words(device_header_copy.length) 1339 rep movsw ; overwrite device header with default 1340 ; (reset to a valid state after unsuccessful 1341 ; decompression, which may have partially 1342 ; written the header already) 1343 push es 1344 pop ds ; -> device segment 1345 pop es 1346 pop bx 1347 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1348 mov byte [es:bx + 13], 0 ; set number of units = 0 1349 mov word [es:bx + 14 + 2], ds 1350 and word [es:bx + 14], 0 ; -> after end of memory to allocate 1351 pop ax 1352 pop cx 1353 pop dx 1354 pop di 1355 pop si 1356 pop ds 1357 pop bp 1358 add sp, 4 ; discard far return to payload's strategy 1359 retf ; return to DOS 1360 1361 1362 .exit_app_or_kernel: 1363 %endif 1364 1365 %if _IMAGE_EXE 1366 %if _BOOTLDR 1367 00000045 F646FE01 test byte [bp - 2], 1 1368 00000049 7405 jz .exit_kernel_mode 1369 %endif 1370 1371 0000004B B87F4C mov ax, 4C7Fh 1372 0000004E CD21 int 21h 1373 1374 .exit_kernel_mode: 1375 %endif 1376 %if _BOOTLDR 1377 00000050 31C0 xor ax, ax 1378 00000052 CD16 int 16h 1379 00000054 CD19 int 19h 1380 %endif 1381 1382 1383 %if _PROGRESS 1384 step_progress: 1385 00000056 F9 stc 1386 .CF: 1387 00000057 53 push bx 1388 00000058 51 push cx 1389 00000059 52 push dx 1390 0000005A 1E push ds 1391 0000005B 56 push si 1392 0000005C 57 push di 1393 0000005D 50 push ax 1394 1395 0000005E 0E push cs 1396 0000005F 1F pop ds 1397 1398 00000060 8316[9201]00 adc word [.counter], 0 1399 00000065 A1[9201] mov ax, word [.counter] 1400 1401 %if _PROGRESSMULTI 1402 %if _IMAGE_EXE || _DEVICE 1403 %assign defaultprogresshandler _PROGRESSDEFAULT 1404 %else 1405 %assign defaultprogresshandler _PROGRESSDEFAULTBOOT 1406 %endif 1407 00000068 E91600 jmp strict near . %+ defaultprogresshandler %+ _step 1408 .handler: equ $ - 2 ; SMC, patched to dispatch to handler 1409 .base: 1410 %endif 1411 1412 .2_step: 1413 0000006B BAE803 mov dx, 1000 1414 0000006E F7E2 mul dx ; dx:ax = counter times 1000 1415 %if _PROGRESSAMOUNT 1416 00000070 B90100 mov cx, _PROGRESSAMOUNT 1417 00000073 F7F1 div cx ; ax = 0..1000 1418 %else 1419 %warning Progress amount is zero 1420 mov ax, 1 1421 %endif 1422 1423 %if 0 1424 cmp word [.display], ax 1425 je .ret 1426 mov word [.display], ax 1427 %endif 1428 00000075 BE[9B01] mov si, .message_number_end - 1 1429 00000078 E80E00 call .format_percentage 1430 1431 0000007B BE[9401] mov si, .message 1432 0000007E E82B01 call disp_error 1433 1434 .ret: 1435 00000081 58 pop ax 1436 .ret_ax: 1437 00000082 5F pop di 1438 00000083 5E pop si 1439 00000084 1F pop ds 1440 00000085 5A pop dx 1441 00000086 59 pop cx 1442 00000087 5B pop bx 1443 .retn: 1444 00000088 C3 retn 1445 1446 1447 .format_percentage: 1448 00000089 BB0200 mov bx, 2 ; skip dot 1449 1450 0000008C B90A00 mov cx, 10 ; base 1451 @@: 1452 0000008F 31D2 xor dx, dx ; dx:ax = current number 1453 00000091 F7F1 div cx ; dl = remainder, ax = next number 1454 00000093 80C230 add dl, '0' ; make decit 1455 00000096 8814 mov byte [si], dl ; store 1456 00000098 29DE sub si, bx ; -> next digit slot 1457 0000009A 80FB02 cmp bl, 2 ; did we just store fractional ? 1458 0000009D B301 mov bl, 1 ; ! next iteration do not skip dot 1459 0000009F 74EE je @B ; yes, loop always --> 1460 000000A1 85C0 test ax, ax ; nonzero left ? 1461 000000A3 75EA jnz @B ; yes, loop if so --> 1462 000000A5 C3 retn 1463 1464 1465 %if _PROGRESSMULTI 1466 .0_step: equ .ret 1467 1468 .1_step: 1469 000000A6 58 pop ax 1470 000000A7 E81001 call disp_al 1471 000000AA EBD6 jmp .ret_ax 1472 1473 .3_step: 1474 000000AC BB4B00 mov bx, 80 - 1 - 4 1475 000000AF F7E3 mul bx ; dx:ax = counter times 75 1476 %if _PROGRESSAMOUNT 1477 000000B1 B90100 mov cx, _PROGRESSAMOUNT 1478 000000B4 F7F1 div cx ; ax = 0..75 1479 %else 1480 %warning Progress amount is zero 1481 mov ax, 1 1482 %endif 1483 1484 000000B6 3906[9001] cmp word [.display], ax 1485 000000BA 74C5 je .ret 1486 000000BC A3[9001] mov word [.display], ax 1487 1488 000000BF 50 push ax 1489 000000C0 91 xchg cx, ax 1490 000000C1 B00D mov al, 13 1491 000000C3 E8F400 call disp_al 1492 000000C6 B05B mov al, '[' 1493 000000C8 E8EF00 call disp_al 1494 000000CB B020 mov al, 32 1495 000000CD E8EA00 call disp_al 1496 1497 000000D0 B023 mov al, '#' 1498 000000D2 E305 jcxz @FF 1499 @@: 1500 000000D4 E8E300 call disp_al 1501 000000D7 E2FB loop @B 1502 @@: 1503 1504 000000D9 B020 mov al, 32 1505 000000DB 59 pop cx 1506 000000DC 29CB sub bx, cx 1507 000000DE 7607 jbe @FF 1508 000000E0 89D9 mov cx, bx 1509 @@: 1510 000000E2 E8D500 call disp_al 1511 000000E5 E2FB loop @B 1512 @@: 1513 1514 .m4done: 1515 000000E7 E8D000 call disp_al 1516 000000EA B05D mov al, ']' 1517 000000EC E8CB00 call disp_al 1518 000000EF EB90 jmp .ret 1519 1520 1521 .4_step: 1522 000000F1 50 push ax 1523 1524 000000F2 BAE803 mov dx, 1000 1525 000000F5 F7E2 mul dx ; dx:ax = counter times 1000 1526 %if _PROGRESSAMOUNT 1527 000000F7 B90100 mov cx, _PROGRESSAMOUNT 1528 000000FA F7F1 div cx ; ax = 0..1000 1529 %else 1530 %warning Progress amount is zero 1531 mov ax, 1 1532 %endif 1533 1534 000000FC BE[A501] mov si, .message_4_number_end - 1 1535 000000FF E887FF call .format_percentage 1536 1537 00000102 58 pop ax 1538 00000103 BB4B00 mov bx, 80 - 1 - 4 1539 00000106 F7E3 mul bx ; dx:ax = counter times 75 1540 %if _PROGRESSAMOUNT 1541 00000108 B90100 mov cx, _PROGRESSAMOUNT 1542 0000010B F7F1 div cx ; ax = 0..75 1543 %else 1544 %warning Progress amount is zero 1545 mov ax, 1 1546 %endif 1547 1548 0000010D 50 push ax 1549 0000010E 91 xchg cx, ax 1550 0000010F B00D mov al, 13 1551 00000111 E8A600 call disp_al 1552 00000114 B05B mov al, '[' 1553 00000116 E8A100 call disp_al 1554 00000119 B020 mov al, 32 1555 0000011B E89C00 call disp_al 1556 1557 0000011E 31FF xor di, di 1558 00000120 BA2200 mov dx, (80 - 1 - 4 - .message_4_length) / 2 1559 00000123 803E[A101]20 cmp byte [.message_4_number], 32 1560 00000128 7401 je @F 1561 0000012A 47 inc di 1562 @@: 1563 0000012B 29FA sub dx, di 1564 1565 0000012D B023 mov al, '#' 1566 0000012F E306 jcxz @FF 1567 @@: 1568 00000131 E88600 call disp_al 1569 00000134 4A dec dx 1570 00000135 E0FA loopnz @B 1571 @@: 1572 1573 00000137 85D2 test dx, dx 1574 00000139 752E jnz .notyetm4 1575 1576 0000013B BE[A101] mov si, .message_4 1577 0000013E 29FE sub si, di 1578 00000140 E86900 call disp_error 1579 1580 00000143 29F9 sub cx, di 1581 00000145 760E jbe @FF 1582 00000147 83E907 sub cx, .message_4_length 1583 0000014A 7609 jbe @FF 1584 0000014C 89CA mov dx, cx 1585 0000014E B023 mov al, '#' 1586 @@: 1587 00000150 E86700 call disp_al 1588 00000153 E2FB loop @B 1589 @@: 1590 00000155 59 pop cx 1591 00000156 B020 mov al, 32 1592 00000158 83EB29 sub bx, (80 - 1 - 4 - .message_4_length) / 2 + .message_4_length 1593 0000015B 29D3 sub bx, dx 1594 0000015D 7607 jbe @FF 1595 0000015F 89D9 mov cx, bx 1596 @@: 1597 00000161 E85600 call disp_al 1598 00000164 E2FB loop @B 1599 @@: 1600 00000166 E97EFF jmp .m4done 1601 1602 .notyetm4: 1603 00000169 B020 mov al, 32 1604 0000016B 59 pop cx 1605 0000016C 29CB sub bx, cx 1606 0000016E 7608 jbe @FF 1607 00000170 89D9 mov cx, bx 1608 @@: 1609 00000172 E84500 call disp_al 1610 00000175 4A dec dx 1611 00000176 E0FA loopnz @B 1612 @@: 1613 1614 00000178 BE[A101] mov si, .message_4 1615 0000017B 29FE sub si, di 1616 0000017D E82C00 call disp_error 1617 1618 00000180 B020 mov al, 32 1619 00000182 29F9 sub cx, di 1620 00000184 83E907 sub cx, .message_4_length 1621 ; jbe @FF 1622 @@: 1623 00000187 E83000 call disp_al 1624 0000018A E2FB loop @B 1625 @@: 1626 0000018C E958FF jmp .m4done 1627 %endif 1628 1629 0000018F 00 align 2, db 0 1630 %if _PROGRESSMULTI 1631 00000190 FFFF .display: dw -1 1632 %endif 1633 00000192 0000 .counter: dw 0 1634 00000194 0D5B20 .message: db 13,"[ " 1635 00000197 2020312E30 .message_number:db " 1.0" ; enough digit slots for 100.0%, 1636 ; blanks are pre-init until written 1637 .message_number_end: 1638 0000019C 25205D00 db "% ]",0 1639 %if _PROGRESSMULTI 1640 000001A0 20 db " " 1641 .message_4: 1642 000001A1 2020312E30 .message_4_number:db " 1.0" ; enough digit slots for 100.0%, 1643 ; blanks are pre-init until written 1644 .message_4_number_end: 1645 000001A6 252000 db "% ",0 1646 .message_4_length: equ $ - 1 - .message_4 1647 %endif 1648 %endif 1649 1650 1651 %if _DEVICE 1652 align 16 1653 device_header_copy: 1654 .: 1655 .next: 1656 dd -1 ; already initialised 1657 .attributes: 1658 dw _DEVICE_ATTRIBUTE 1659 .strategy: 1660 dw .strategy_entry - . ; -> strategy entry 1661 .interrupt: 1662 dw .interrupt_entry - . ; -> interrupt entry 1663 .name: 1664 fill 8, 32, db _DEVICE_NAME 1665 1666 .strategy_entry: 1667 fill 4, 90h, jmp .set_error ; rel8 or rel16 jump, not minus . 1668 .interrupt_entry: 1669 fill 4, 90h, retf 1670 1671 .set_error: 1672 mov word [es:bx + 3], 8103h ; set error, done, invalid command 1673 retf 1674 .length: equ $ - . 1675 %endif 1676 1677 1678 disp_error.loop: 1679 000001A9 E80E00 call disp_al 1680 disp_error: 1681 000001AC AC lodsb 1682 000001AD 84C0 test al, al 1683 000001AF 75F8 jnz .loop 1684 000001B1 C3 retn 1685 1686 %if _DEBUG0 || _DEBUG1 || _DEBUG2 || _DEBUG3 1687 disp_ax_hex: ; ax 1688 xchg al,ah 1689 call disp_al_hex ; display former ah 1690 xchg al,ah ; and fall trough for al 1691 disp_al_hex: ; al 1692 push cx 1693 mov cl,4 1694 ror al,cl 1695 call disp_al_lownibble_hex ; display former high-nibble 1696 rol al,cl 1697 pop cx 1698 ; and fall trough for low-nibble 1699 disp_al_lownibble_hex: 1700 push ax ; save ax for call return 1701 and al,00001111b ; high nibble must be zero 1702 add al,'0' ; if number is 0-9, now it's the correct character 1703 cmp al,'9' 1704 jna .decimalnum ; if we get decimal number with this, ok --> 1705 add al,7 ; otherwise, add 7 and we are inside our alphabet 1706 .decimalnum: 1707 call disp_al 1708 pop ax 1709 retn 1710 %endif 1711 1712 1713 disp_al_for_progress: 1714 %if _PROGRESS && _PROGRESSMULTI 1715 000001B2 2E833E[6900]16 cmp word [cs:step_progress.handler], step_progress.0_step - step_progress.base 1716 000001B8 741B je disp_al.retn 1717 %endif 1718 disp_al: 1719 %if _TEST_PROGRAM 1720 000001BA C3 retn 1721 %else 1722 push ax 1723 %endif 1724 %if _BOOTLDR 1725 000001BB 53 push bx 1726 000001BC 55 push bp 1727 000001BD B40E mov ah, 0Eh 1728 000001BF BB0700 mov bx, 7 1729 %endif 1730 %if _IMAGE_EXE || _DEVICE 1731 000001C2 52 push dx 1732 1733 %if _BOOTLDR 1734 000001C3 F646FE03 test byte [bp - 2], 1 | 2 1735 000001C7 7406 jz .display_kernel_mode 1736 %endif 1737 1738 000001C9 92 xchg dx, ax ; dl = input al 1739 000001CA B402 mov ah, 02h 1740 000001CC CD21 int 21h 1741 %if _BOOTLDR 1742 000001CE A9 db __TEST_IMM16 ; (skip int) 1743 %endif 1744 1745 .display_kernel_mode: 1746 %endif 1747 %if _BOOTLDR 1748 000001CF CD10 int 10h 1749 %endif 1750 %if _IMAGE_EXE 1751 000001D1 5A pop dx 1752 %endif 1753 %if _BOOTLDR 1754 000001D2 5D pop bp 1755 000001D3 5B pop bx 1756 %endif 1757 000001D4 58 pop ax 1758 .retn: 1759 disp_error.ret: 1760 000001D5 C3 retn 1761 1762 1763 msg: 1764 %if _DEBUG0 1765 .error_begin: db "Load error: Decompression failure, code ",0 1766 .error_end: db "h.",13,10,0 1767 %else 1768 000001D6 4C6F6164206572726F- .error: db "Load error: Decompression failure.",13,10,0 1768 000001DF 723A204465636F6D70- 1768 000001E8 72657373696F6E2066- 1768 000001F1 61696C7572652E0D0A- 1768 000001FA 00 1769 %endif 1770 1771 1772 %endif ; _SCAN 1773 1774 %assign NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1 1775 %assign NEED_NORMALISE_BOTH_POINTERS 1 1776 %assign CHECK_POINTERS_VARIABLE_SRC 1 1777 %assign CHECK_POINTERS_VARIABLE_DST 1 1778 %assign SCAN_SUPPORTED 0 1779 1780 ; Specific depacker's file is included within label msg. 1781 ; In the file, lframe is used and lleave ctx is not used. 1782 1783 %if _BRIEFLZ 1784 %include "brieflz.asm" 1785 %endif 1786 1787 1788 %if _LZ4 1789 %include "lz4.asm" 1790 %endif 1791 1792 1793 %if _SNAPPY 1794 %include "snappy.asm" 1795 %endif 1796 1797 1798 %if _EXODECR 1799 %include "exodecr.asm" 1800 %endif 1801 1802 1803 %if _X 1804 %include "x.asm" 1805 %endif 1806 1807 1808 %if _HEATSHRINK 1809 %include "heatshr.asm" 1810 %endif 1811 1812 1813 %if _LZD 1814 %include "lzd.asm" 1815 %endif 1816 1817 1818 %if _LZO 1819 %include "lzo.asm" 1820 %endif 1821 1822 1823 %if _LZSA2 1824 %include "lzsa2.asm" 1 <1> 2 <1> ; 8086 Assembly lDOS iniload payload LZSA2 depacker 3 <1> ; by E. C. Masloch, 2021 4 <1> ; 5 <1> ; based on: 6 <1> ; decompress_small.S - space-efficient decompressor implementation for 8088 7 <1> ; 8 <1> ; Copyright (C) 2019 Emmanuel Marty 9 <1> ; 10 <1> ; This software is provided 'as-is', without any express or implied 11 <1> ; warranty. In no event will the authors be held liable for any damages 12 <1> ; arising from the use of this software. 13 <1> ; 14 <1> ; Permission is granted to anyone to use this software for any purpose, 15 <1> ; including commercial applications, and to alter it and redistribute it 16 <1> ; freely, subject to the following restrictions: 17 <1> ; 18 <1> ; 1. The origin of this software must not be misrepresented; you must not 19 <1> ; claim that you wrote the original software. If you use this software 20 <1> ; in a product, an acknowledgment in the product documentation would be 21 <1> ; appreciated but is not required. 22 <1> ; 2. Altered source versions must be plainly marked as such, and must not be 23 <1> ; misrepresented as being the original software. 24 <1> ; 3. This notice may not be removed or altered from any source distribution. 25 <1> 26 <1> 27 <1> %if _SCAN 28 <1> %assign SCAN_SUPPORTED 1 29 <1> %endif 30 <1> 31 <1> 32 <1> numdef COUNTER, 0, 128 33 <1> %if (_COUNTER - 1) & _COUNTER 34 <1> %error COUNTER must be a power of two 35 <1> %endif 36 <1> numdef M, 0 37 <1> %undef N 38 <1> numdef N, 0 39 <1> numdef INLINELOD, 1 40 <1> numdef WORDLENGTH, 1 41 <1> numdef UNSAFE, 0 42 <1> 43 <1> %assign CHECK_POINTERS_VARIABLE_SRC 0 44 <1> %assign CHECK_POINTERS_VARIABLE_DST 0 45 <1> 46 <1> ; INP: ds:si -> source 47 <1> ; dx:cx = length of source 48 <1> ; es:di -> destination (below source) 49 <1> ; if _IMAGE_EXE: 50 <1> ; bx = EXE mode flag (bit 0) 51 <1> ; else: 52 <1> ; bx = 0 53 <1> ; if _PAYLOAD_KERNEL_MAX_PARAS: 54 <1> ; ax = maximum amount in paragraphs of destination needed 55 <1> ; (-1 if full source should be decompressed) 56 <1> ; else: 57 <1> ; ax = -1 58 <1> ; OUT: NC if success 59 <1> ; CY if error, 60 <1> ; bx = ?errordata (if _DEBUG0) 61 <1> ; CHG: ax, (bx), cx, dx, es, ds, si, di 62 <1> ; STT: UP 63 <1> ; 64 <1> ; Note: The destination reaches up to below the source. 65 <1> ; Note: The input pointers need not be normalised yet. 66 <1> ; Normalised means that the offset part is below 16. 67 <1> depack: 68 <1> lframe near 69 <1> %if _SCAN 70 <1> lpar dword, progressticks 71 <1> lpar dword, depackedsize 72 <1> lpar dword, maxbytesahead 73 <1> lpar_return 74 <1> xor di, di 75 <1> mov es, di ; destination = all-zeroes (special) 76 <1> %endif 77 <1> 78 <1> %if _IMAGE_EXE || _DEBUG0 || _COUNTER 79 000001FB 5589E5 <1> lenter early 80 <1> %if _IMAGE_EXE 81 <1> lvar word, exemode ; must be bp - 2! 82 000001FE 53 <1> push bx 83 <1> %if ?exemode != -2 84 <1> %error exemode variable must be directly below bp 85 <1> %endif 86 <1> %endif 87 <1> %if _DEBUG0 || _COUNTER 88 000001FF 31DB <1> xor bx, bx 89 <1> %endif 90 <1> %if _DEBUG0 91 <1> lvar word, errordata 92 <1> push bx 93 <1> %endif 94 <1> %endif 95 <1> lvar word, counter 96 <1> %if _COUNTER 97 00000201 53 <1> push bx ; initialise counter (high byte) to zero 98 <1> %endif 99 <1> lvar word, matchlength 100 <1> %if _WORDLENGTH 101 <1> %if !_N || !_UNSAFE 102 <1> lvar word, word_length_of_source 103 <1> %endif 104 <1> %ifn _UNSAFE 105 <1> lvar word, word_length_of_destination 106 <1> lvar word, bool_not_full_destination 107 <1> %endif 108 <1> %else 109 <1> lvar dword, length_of_source_after_block 110 <1> %endif 111 00000202 8D66F4 <1> lenter 112 <1> 113 00000205 E86B02 <1> call normalise_both_pointers 114 <1> 115 <1> %if _SCAN 116 <1> lvar dword, original_src 117 <1> push ds 118 <1> push si 119 <1> %endif 120 <1> lvar dword, src 121 00000208 1E <1> push ds 122 00000209 56 <1> push si 123 <1> lvar dword, original_dst 124 0000020A 06 <1> push es 125 0000020B 57 <1> push di 126 <1> lvar dword, dst 127 0000020C 06 <1> push es 128 0000020D 57 <1> push di 129 <1> %ifn _UNSAFE 130 <1> lvar dword, length_of_source 131 0000020E 52 <1> push dx 132 0000020F 51 <1> push cx 133 <1> %endif 134 <1> 135 <1> %if 0 ; && _PAYLOAD_KERNEL_MAX_PARAS 136 <1> cmp ax, -1 ; no maximum specified ? 137 <1> je @FF ; retain -1 in ax --> 138 <1> test di, di ; do we need an additional paragraph ? 139 <1> jz @F ; no --> 140 <1> inc ax ; es + ax => paragraph after necessary part 141 <1> @@: 142 <1> mov dx, es 143 <1> add ax, dx ; => paragraph after necessary part 144 <1> ; If the normalised destination pointer's segment grows 145 <1> ; to this segment then enough has been decompressed. 146 <1> d0 mov byte [bp + ?errordata], 40h 147 <1> jc .error ; should not carry 148 <1> @@: 149 <1> lvar word, dst_max_segment 150 <1> push ax 151 <1> %endif 152 <1> 153 <1> %ifn _UNSAFE 154 <1> %if _SCAN 155 <1> LENDST equ 960 * 1024 156 <1> mov bx, LENDST >> 16 157 <1> mov cx, LENDST & 0FFFFh 158 <1> %else 159 00000210 1E <1> push ds 160 00000211 56 <1> push si 161 00000212 E8BE02 <1> call pointer_to_linear 162 <1> 163 00000215 89D3 <1> mov bx, dx 164 00000217 91 <1> xchg cx, ax ; bx:cx = source linear 165 <1> 166 00000218 06 <1> push es 167 00000219 57 <1> push di 168 0000021A E8B602 <1> call pointer_to_linear 169 <1> 170 <1> %if _ALLOW_OVERLAPPING 171 0000021D 034EE4 <1> add cx, word [bp + ?length_of_source] 172 00000220 135EE6 <1> adc bx, word [bp + ?length_of_source + 2] 173 <1> ; In case of allowing overlapping source and destination, 174 <1> ; the ?length_of_destination variable is set to 175 <1> ; ?src + ?length_of_source - ?dst, allowing to write to 176 <1> ; all of the source buffer (with the checks already in place 177 <1> ; from the default handling). Additional checks are done by 178 <1> ; calling check_pointers_not_overlapping. This is done after 179 <1> ; every change of ?dst to verify that the write pointer stays 180 <1> ; below-or-equal the read pointer. 181 <1> ; This means the remaining source data may be corrupted by a 182 <1> ; write, but nothing after the source data is written to, 183 <1> ; so the error handling (in INIT1 after the data) still works. 184 <1> %endif 185 <1> 186 00000223 29C1 <1> sub cx, ax 187 00000225 19D3 <1> sbb bx, dx ; bx:cx = source linear - destination linear 188 <1> %endif ; _SCAN 189 <1> 190 <1> lvar dword, length_of_destination 191 00000227 53 <1> push bx ; push into [bp + ?length_of_destination + 2] 192 00000228 51 <1> push cx ; push into [bp + ?length_of_destination] 193 <1> %endif 194 <1> 195 <1> %if _ALLOW_OVERLAPPING 196 00000229 E83302 <1> call check_pointers_not_overlapping 197 <1> ; Note: We initially check here that the write pointer is 198 <1> ; low enough, ie below-or-equal the read pointer. 199 <1> ; Doing this check here (as well as after any 200 <1> ; copied match) allows us to drop the check done 201 <1> ; after moving literal bytes. 202 <1> d0 mov byte [bp + ?errordata], 1Bh 203 0000022C 7303E9A900 <1> jc .error 204 <1> %endif 205 <1> 206 00000231 E8C300 <1> call .lodsw 207 00000234 3D7B9E <1> cmp ax, 7Bh | (9Eh << 8) ; signature 208 00000237 7403E99E00 <1> jne .error 209 0000023C E8AC00 <1> call .lodsb 210 0000023F 3C20 <1> cmp al, 1 << 5 ; traits byte, check for lzsa2 211 00000241 7403E99400 <1> jne .error 212 <1> 213 <1> .loop: 214 00000246 E82A02 <1> call normalise_both_pointers 215 <1> 216 00000249 31D2 <1> xor dx, dx 217 0000024B E8A900 <1> call .lodsw ; bits 0 to 15 of length 218 0000024E 92 <1> xchg ax, dx 219 0000024F E89900 <1> call .lodsb 220 00000252 A87F <1> test al, 0111_1111b ; reserved bits + bit 16 of length 221 00000254 7403E98100 <1> jnz .error ; error if nonzero --> 222 <1> 223 00000259 E81E02 <1> call normalise_dssi_pointer 224 <1> 225 <1> ; This first check is only really relevant 226 <1> ; for uncompressed blocks. 227 0000025C 89FB <1> mov bx, di 228 0000025E 01D3 <1> add bx, dx ; fits in destination segment ? 229 00000260 7278 <1> jc .error ; (assuming bit 16 = 0) 230 <1> ; This second check is to insure we don't 231 <1> ; have to normalise the source pointer 232 <1> ; until after the end of the block. 233 00000262 89F3 <1> mov bx, si 234 00000264 01D3 <1> add bx, dx ; fits in source segment ? 235 00000266 7272 <1> jc .error 236 <1> 237 00000268 84C0 <1> test al, al ; uncompressed ? 238 0000026A 92 <1> xchg ax, dx 239 0000026B 7917 <1> jns .compressed ; no --> 240 <1> .uncompressed: 241 <1> %ifn _UNSAFE 242 0000026D 2946E4 <1> sub word [bp + ?length_of_source], ax 243 00000270 835EE600 <1> sbb word [bp + ?length_of_source + 2], 0 244 00000274 7264 <1> jc .error 245 00000276 2946E0 <1> sub word [bp + ?length_of_destination], ax 246 00000279 835EE200 <1> sbb word [bp + ?length_of_destination + 2], 0 247 0000027D 725B <1> jc .error 248 <1> %endif 249 0000027F 91 <1> xchg ax, cx 250 00000280 F3A4 <1> rep movsb ; copy this 251 00000282 EBC2 <1> jmp .loop 252 <1> 253 <1> .compressed: 254 <1> %ifn _UNSAFE 255 00000284 8B4EE4 <1> mov cx, word [bp + ?length_of_source] 256 00000287 8B5EE6 <1> mov bx, word [bp + ?length_of_source + 2] 257 <1> 258 0000028A 85C0 <1> test ax, ax 259 0000028C 7447 <1> jz .end 260 <1> 261 0000028E 29C1 <1> sub cx, ax 262 00000290 83DB00 <1> sbb bx, 0 263 00000293 7245 <1> jc .error 264 <1> %else 265 <1> test ax, ax 266 <1> jz .end 267 <1> %endif 268 <1> 269 <1> %if _WORDLENGTH 270 <1> %if !_N || !_UNSAFE 271 00000295 50 <1> push ax ; remember initial word length 272 00000296 8946F8 <1> mov word [bp + ?word_length_of_source], ax 273 <1> %endif 274 <1> %ifn _UNSAFE 275 00000299 31C0 <1> xor ax, ax 276 0000029B 3946E2 <1> cmp word [bp + ?length_of_destination + 2], ax 277 <1> ; >= 64 KiB ? 278 0000029E 7505 <1> jne @F ; yes, store zeroes --> 279 000002A0 0B46E0 <1> or ax, word [bp + ?length_of_destination] 280 <1> ; ax = length left 281 000002A3 7435 <1> jz .error ; must be NZ 282 <1> @@: ; ax == 0 if full 64 KiB destination 283 000002A5 8946F6 <1> mov word [bp + ?word_length_of_destination], ax 284 000002A8 8946F4 <1> mov word [bp + ?bool_not_full_destination], ax 285 <1> %endif 286 <1> %else 287 <1> %if _UNSAFE 288 <1> %error Combination not implemented 289 <1> %endif 290 <1> mov word [bp + ?length_of_source_after_block], cx 291 <1> mov word [bp + ?length_of_source_after_block + 2], bx 292 <1> %endif 293 <1> 294 000002AB 06 <1> push es 295 000002AC 57 <1> push di 296 000002AD E85300 <1> call lzsa2_decompress 297 000002B0 83F801 <1> cmp ax, 1 ; CY if ax == 0 298 000002B3 91 <1> xchg cx, ax 299 000002B4 19DB <1> sbb bx, bx ; -1 if cx == 0, else 0 300 000002B6 F7DB <1> neg bx ; 1 if cx == 0, else 0 301 <1> %ifn _UNSAFE 302 <1> %if _WORDLENGTH 303 000002B8 294EE0 <1> sub word [bp + ?length_of_destination], cx 304 000002BB 195EE2 <1> sbb word [bp + ?length_of_destination + 2], bx 305 000002BE 721A <1> jc .error 306 <1> %endif 307 <1> %endif 308 000002C0 E8E101 <1> call normalise_pointer_with_displacement_bxcx 309 000002C3 5F <1> pop di 310 000002C4 07 <1> pop es 311 <1> %if _WORDLENGTH 312 <1> %if !_N || !_UNSAFE 313 000002C5 58 <1> pop ax ; initial word length 314 <1> %endif 315 <1> %ifn _UNSAFE 316 000002C6 2B46F8 <1> sub ax, word [bp + ?word_length_of_source] 317 <1> ; initial - left = how much processed 318 000002C9 2946E4 <1> sub word [bp + ?length_of_source], ax 319 000002CC 835EE600 <1> sbb word [bp + ?length_of_source + 2], 0 320 000002D0 7208 <1> jc .error 321 <1> %endif 322 <1> %endif 323 000002D2 E971FF <1> jmp .loop 324 <1> 325 <1> .end: 326 <1> %ifn _UNSAFE 327 000002D5 09CB <1> or bx, cx 328 000002D7 7501 <1> jnz .error 329 <1> %endif 330 <1> 331 <1> .ret: 332 000002D9 A8 <1> db __TEST_IMM8 ; (skip stc, NC) 333 <1> .error: 334 000002DA F9 <1> stc 335 <1> 336 <1> %if _SCAN 337 <1> pushf 338 <1> push es 339 <1> push di 340 <1> call pointer_to_linear 341 <1> 342 <1> mov bx, dx 343 <1> xchg cx, ax ; bx:cx = end destination linear 344 <1> 345 <1> push word [bp + ?original_dst + 2] 346 <1> push word [bp + ?original_dst] 347 <1> call pointer_to_linear ; dx:ax = start destination linear 348 <1> 349 <1> sub cx, ax 350 <1> sbb bx, dx ; bx:cx = end destination linear 351 <1> ; minus start destination linear 352 <1> 353 <1> mov word [bp + ?depackedsize], cx 354 <1> mov word [bp + ?depackedsize + 2], bx 355 <1> popf 356 <1> %endif 357 <1> %if _COUNTER 358 000002DB 9F <1> lahf 359 000002DC B00D <1> mov al, 13 360 000002DE E8D1FE <1> call disp_al_for_progress 361 000002E1 B00A <1> mov al, 10 362 000002E3 E8CCFE <1> call disp_al_for_progress 363 000002E6 9E <1> sahf 364 <1> %endif 365 <1> d0 mov bx, word [bp + ?errordata] 366 000002E7 89EC5D <1> lleave code 367 000002EA C3 <1> lret 368 <1> 369 <1> 370 <1> ; INP: ds:si -> source data 371 <1> ; ?length_of_source 372 <1> ; OUT: CY if error (source buffer too small) 373 <1> ; NC if success, 374 <1> ; al = value read 375 <1> ; ds:si incremented (NOT normalised) 376 <1> ; ?length_of_source decremented 377 <1> .lodsb: 378 <1> %ifn _UNSAFE 379 000002EB 836EE401 <1> sub word [bp + ?length_of_source], 1 380 000002EF 835EE600 <1> sbb word [bp + ?length_of_source + 2], 0 381 000002F3 72E5 <1> jb .error 382 <1> %endif 383 000002F5 AC <1> lodsb 384 <1> .retn: 385 000002F6 C3 <1> retn 386 <1> 387 <1> 388 <1> ; INP: ds:si -> source data 389 <1> ; ?length_of_source 390 <1> ; OUT: CY if error (source buffer too small) 391 <1> ; NC if success, 392 <1> ; ax = value read 393 <1> ; ds:si incremented (NOT normalised) 394 <1> ; ?length_of_source decremented 395 <1> .lodsw: 396 <1> %ifn _UNSAFE 397 000002F7 836EE402 <1> sub word [bp + ?length_of_source], 2 398 000002FB 835EE600 <1> sbb word [bp + ?length_of_source + 2], 0 399 000002FF 72D9 <1> jb .error 400 <1> %endif 401 00000301 AD <1> lodsw 402 00000302 C3 <1> retn 403 <1> 404 <1> 405 <1> %if _INLINELOD 406 <1> %imacro do_lodsb 0.nolist 407 <1> %if _WORDLENGTH 408 <1> %if !_N || !_UNSAFE 409 <1> sub word [bp + ?word_length_of_source], 1 410 <1> jb .error 411 <1> %endif 412 <1> %else 413 <1> sub word [bp + ?length_of_source], 1 414 <1> sbb word [bp + ?length_of_source + 2], 0 415 <1> jb .error 416 <1> %endif 417 <1> lodsb 418 <1> %endmacro 419 <1> %imacro do_lodsw 0.nolist 420 <1> %if _WORDLENGTH 421 <1> %if !_N || !_UNSAFE 422 <1> sub word [bp + ?word_length_of_source], 2 423 <1> jb .error 424 <1> %endif 425 <1> %else 426 <1> sub word [bp + ?length_of_source], 2 427 <1> sbb word [bp + ?length_of_source + 2], 0 428 <1> jb .error 429 <1> %endif 430 <1> lodsw 431 <1> %endmacro 432 <1> %else 433 <1> %idefine do_lodsb call .lodsb 434 <1> %idefine do_lodsw call .lodsw 435 <1> %endif 436 <1> 437 <1> %imacro noninlinelod 0 438 <1> %if !_INLINELOD 439 <1> %if !_WORDLENGTH 440 <1> .lodsb equ depack.lodsb 441 <1> .lodsw equ depack.lodsw 442 <1> %else 443 <1> .lodsb: 444 <1> %if !_N || !_UNSAFE 445 <1> sub word [bp + ?word_length_of_source], 1 446 <1> jb .error 447 <1> %endif 448 <1> lodsb 449 <1> .retn: 450 <1> retn 451 <1> 452 <1> .lodsw: 453 <1> %if !_N || !_UNSAFE 454 <1> sub word [bp + ?word_length_of_source], 2 455 <1> jb .error 456 <1> %endif 457 <1> lodsw 458 <1> retn 459 <1> %endif 460 <1> %endif 461 <1> %endmacro 462 <1> 463 <1> ; Decompress LZSA2 block 464 <1> ; 465 <1> ; INP: ds:si -> LZSA2 block 466 <1> ; es:di -> output buffer 467 <1> ; ?length_of_source 468 <1> ; ?length_of_source_after_block = block end target 469 <1> ; ?original_dst -> lowest valid back reference 470 <1> ; OUT: ax = decompressed size (0 means 64 KiB) 471 <1> ; ds:si -> behind source data 472 <1> ; jumps to depack.error if error condition detected 473 <1> ; CHG: all except bp 474 <1> lzsa2_decompress: 475 00000303 57 <1> push di ; remember decompression offset 476 <1> 477 00000304 BB0001 <1> mov bx,0100H 478 00000307 8366FA00 <1> and word [bp + ?matchlength], 0 479 <1> 480 <1> .decode_token_clear_cx: 481 0000030B 31C9 <1> xor cx,cx 482 <1> .decode_token: 483 <1> %if _SCAN 484 <1> add word [bp + ?progressticks], 1 485 <1> adc word [bp + ?progressticks + 2], 0 486 <1> %endif 487 <1> %if _COUNTER 488 0000030D FE46FC <1> inc byte [bp + ?counter] 489 00000310 F646FC7F <1> test byte [bp + ?counter], _COUNTER - 1 490 00000314 7505 <1> jnz @F 491 00000316 B02E <1> mov al, '.' 492 00000318 E822FD <1> call disp_al_counter 493 <1> @@: 494 <1> %endif 495 <1> 496 <1> %ifn _M || _N 497 <1> %if _WORDLENGTH 498 <1> cmp word [bp + ?word_length_of_source], 0 499 <1> je .end 500 <1> %else 501 <1> mov ax, word [bp + ?length_of_source + 2] 502 <1> cmp word [bp + ?length_of_source_after_block + 2], ax 503 <1> jne @F 504 <1> mov ax, word [bp + ?length_of_source] 505 <1> cmp word [bp + ?length_of_source_after_block], ax 506 <1> @@: 507 <1> je .end 508 <1> ja depack.error 509 <1> %endif 510 <1> %endif 511 <1> 512 0000031B 89C8 <1> mov ax,cx ; clear ah - cx is zero from above or from after rep movsb in .copy_match 513 0000031D 836EF801724AAC <1> do_lodsb ; read token byte: XYZ|LL|MMMM 514 00000324 89C2 <1> mov dx,ax ; keep token in dl 515 <1> 516 00000326 2418 <1> and al,018H ; isolate literals length in token (LL) 517 00000328 B103 <1> mov cl,3 518 0000032A D2E8 <1> shr al,cl ; shift literals length into place 519 <1> 520 0000032C 3C03 <1> cmp al,03H ; LITERALS_RUN_LEN_V2? 521 0000032E 751B <1> jne .got_literals ; no, we have the full literals count from the token, go copy 522 <1> 523 00000330 E86800 <1> call .get_nibble ; get extra literals length nibble 524 00000333 00C8 <1> add al,cl ; add len from token to nibble 525 00000335 3C12 <1> cmp al,012H ; LITERALS_RUN_LEN_V2 + 15 ? 526 00000337 7512 <1> jne .got_literals ; if not, we have the full literals count, go copy 527 <1> 528 00000339 836EF801722EAC <1> do_lodsb ; grab extra length byte 529 00000340 0412 <1> add al,012H ; overflow? 530 00000342 7307 <1> jnc .got_literals ; if not, we have the full literals count, go copy 531 <1> 532 00000344 836EF8027223AD <1> do_lodsw ; grab 16-bit extra length 533 <1> 534 <1> %ifn _M && !_N 535 <1> .got_literals: 536 <1> %endif 537 <1> ; code only reached if not _M or did lodsw 538 0000034B 91 <1> xchg cx,ax 539 <1> %if _WORDLENGTH 540 <1> %if !_N || !_UNSAFE 541 0000034C 294EF8 <1> sub word [bp + ?word_length_of_source], cx 542 0000034F 721C <1> jb .error 543 <1> %endif 544 <1> %ifn _UNSAFE 545 00000351 294EF6 <1> sub word [bp + ?word_length_of_destination], cx 546 00000354 7212 <1> jb .error_or_full_1 547 <1> .after_full_1: 548 <1> %endif 549 <1> %else 550 <1> sub word [bp + ?length_of_source], cx 551 <1> sbb word [bp + ?length_of_source + 2], 0 552 <1> jb .error 553 <1> sub word [bp + ?length_of_destination], cx 554 <1> sbb word [bp + ?length_of_destination + 2], 0 555 <1> jb .error 556 <1> %endif 557 00000356 F3A4 <1> rep movsb ; copy cx literals from ds:si to es:di 558 <1> 559 <1> %ifn _N 560 <1> %if _WORDLENGTH 561 <1> cmp word [bp + ?word_length_of_source], 0 562 <1> %else 563 <1> push ax 564 <1> mov ax, word [bp + ?length_of_source + 2] 565 <1> cmp word [bp + ?length_of_source_after_block + 2], ax 566 <1> jne @F 567 <1> mov ax, word [bp + ?length_of_source] 568 <1> cmp word [bp + ?length_of_source_after_block], ax 569 <1> @@: 570 <1> pop ax 571 <1> ja .error 572 <1> %endif 573 <1> je .end 574 <1> %endif 575 <1> 576 <1> %if _M && !_N 577 <1> ; here cx = 0 578 <1> %if 1 579 <1> jmp @F 580 <1> %else 581 <1> db __TEST_IMM8 ; skip xchg with ax 582 <1> %endif 583 <1> .got_literals: 584 <1> xchg cx,ax 585 <1> %if _WORDLENGTH 586 <1> %if !_N || !_UNSAFE 587 <1> sub word [bp + ?word_length_of_source], cx 588 <1> jb .error 589 <1> %endif 590 <1> %ifn _UNSAFE 591 <1> sub word [bp + ?word_length_of_destination], cx 592 <1> jb .error_or_full_2 593 <1> .after_full_2: 594 <1> %endif 595 <1> %else 596 <1> sub word [bp + ?length_of_source], cx 597 <1> sbb word [bp + ?length_of_source + 2], 0 598 <1> jb .error 599 <1> sub word [bp + ?length_of_destination], cx 600 <1> sbb word [bp + ?length_of_destination + 2], 0 601 <1> jb .error 602 <1> %endif 603 <1> rep movsb ; copy cx literals from ds:si to es:di 604 <1> @@: 605 <1> %endif 606 <1> 607 00000358 F6C2C0 <1> test dl,0C0h ; check match offset mode in token (X bit) 608 0000035B 7825 <1> js .rep_match_or_large_offset 609 <1> 610 <1> ;;cmp dl,040H ; check if this is a 5 or 9-bit offset (Y bit) 611 <1> ; discovered via the test with bit 6 set 612 0000035D 91 <1> xchg cx,ax ; clear ah - cx is zero from the rep movsb above 613 0000035E 7510 <1> jne .offset_9_bit 614 <1> 615 <1> ; 5 bit offset 616 00000360 80FA20 <1> cmp dl,020H ; test bit 5 617 00000363 E8E500 <1> call .get_nibble_x 618 00000366 EB16 <1> jmp short .dec_offset_top 619 <1> 620 <1> %if _WORDLENGTH 621 <1> %ifn _UNSAFE 622 <1> .error_or_full_1: 623 00000368 E8ED00 <1> call .error_or_full_common 624 0000036B EBE9 <1> jmp .after_full_1 625 <1> 626 <1> %if _M && !_N 627 <1> .error_or_full_2: 628 <1> call .error_or_full_common 629 <1> jmp .after_full_2 630 <1> %endif 631 <1> %endif 632 <1> %endif 633 <1> 634 <1> noninlinelod 438 <2> %if !_INLINELOD 439 <2> %if !_WORDLENGTH 440 <2> .lodsb equ depack.lodsb 441 <2> .lodsw equ depack.lodsw 442 <2> %else 443 <2> .lodsb: 444 <2> %if !_N || !_UNSAFE 445 <2> sub word [bp + ?word_length_of_source], 1 446 <2> jb .error 447 <2> %endif 448 <2> lodsb 449 <2> .retn: 450 <2> retn 451 <2> 452 <2> .lodsw: 453 <2> %if !_N || !_UNSAFE 454 <2> sub word [bp + ?word_length_of_source], 2 455 <2> jb .error 456 <2> %endif 457 <2> lodsw 458 <2> retn 459 <2> %endif 460 <2> %endif 635 <1> .error: 636 0000036D E96AFF <1> jmp depack.error 637 <1> 638 <1> .offset_9_bit: ; 9 bit offset 639 00000370 836EF80172F7AC <1> do_lodsb ; get 8 bit offset from stream in A 640 00000377 FECC <1> dec ah ; set offset bits 15-8 to 1 641 00000379 F6C220 <1> test dl,020H ; test bit Z (offset bit 8) 642 0000037C 7448 <1> je .get_match_length 643 <1> .dec_offset_top: 644 0000037E FECC <1> dec ah ; clear bit 8 if Z bit is clear 645 <1> ; or set offset bits 15-8 to 1 646 00000380 EB44 <1> jmp short .get_match_length 647 <1> 648 <1> .rep_match_or_large_offset: 649 <1> ;;cmp dl,0c0H ; check if this is a 13-bit offset or a 16-bit offset/rep match (Y bit) 650 00000382 7A2D <1> jpe .rep_match_or_16_bit 651 <1> 652 <1> ; 13 bit offset 653 <1> 654 00000384 80FAA0 <1> cmp dl,0A0H ; test bit 5 (knowing that bit 7 is also set) 655 00000387 86E0 <1> xchg ah,al 656 00000389 E8BF00 <1> call .get_nibble_x 657 0000038C 2C02 <1> sub al,2 ; substract 512 658 0000038E EB2D <1> jmp short .get_match_length_1 659 <1> 660 <1> %if _N 661 <1> .end_check: 662 <1> %ifn _UNSAFE 663 <1> %if _WORDLENGTH 664 00000390 837EF800 <1> cmp word [bp + ?word_length_of_source], 0 665 <1> %else 666 <1> mov ax, word [bp + ?length_of_source + 2] 667 <1> cmp word [bp + ?length_of_source_after_block + 2], ax 668 <1> jne @F 669 <1> mov ax, word [bp + ?length_of_source] 670 <1> cmp word [bp + ?length_of_source_after_block], ax 671 <1> @@: 672 <1> %endif 673 00000394 75D7 <1> jne .error 674 <1> %endif 675 <1> %endif 676 <1> .end: 677 00000396 58 <1> pop ax ; retrieve the original decompression offset 678 00000397 97 <1> xchg di,ax ; compute decompressed size 679 00000398 29F8 <1> sub ax,di 680 0000039A C3 <1> ret ; done 681 <1> 682 <1> .get_nibble: 683 0000039B F6DF <1> neg bh ; nibble ready? 684 0000039D 7909 <1> jns .has_nibble 685 <1> 686 0000039F 93 <1> xchg bx,ax 687 000003A0 836EF80172C7AC <1> do_lodsb ; load two nibbles 688 000003A7 93 <1> xchg bx,ax 689 <1> 690 <1> .has_nibble: 691 000003A8 B104 <1> mov cl,4 ; swap 4 high and low bits of nibble 692 000003AA D2CB <1> ror bl,cl 693 000003AC B10F <1> mov cl,0FH 694 000003AE 20D9 <1> and cl,bl 695 000003B0 C3 <1> ret 696 <1> 697 <1> .rep_match_or_16_bit: 698 000003B1 F6C220 <1> test dl,020H ; test bit Z (offset bit 8) 699 000003B4 7513 <1> jne .repeat_match ; rep-match 700 <1> 701 <1> ; 16 bit offset 702 000003B6 836EF80172B1AC <1> do_lodsb ; Get 2-byte match offset 703 <1> 704 <1> .get_match_length_1: 705 000003BD 86E0 <1> xchg ah,al 706 000003BF 836EF80172A8AC <1> do_lodsb ; load match offset bits 0-7 707 <1> 708 <1> .get_match_length: 709 000003C6 8746FA <1> xchg word [bp + ?matchlength], ax 710 <1> ; bp: offset 711 <1> .repeat_match: 712 000003C9 92 <1> xchg ax,dx ; ax: original token 713 000003CA 2407 <1> and al,07H ; isolate match length in token (MMM) 714 000003CC 0402 <1> add al,2 ; add MIN_MATCH_SIZE_V2 715 <1> 716 000003CE 3C09 <1> cmp al,09H ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2? 717 000003D0 7520 <1> jne .got_matchlen ; no, we have the full match length from the token, go copy 718 <1> 719 000003D2 E8C6FF <1> call .get_nibble ; get extra literals length nibble 720 000003D5 00C8 <1> add al,cl ; add len from token to nibble 721 000003D7 3C18 <1> cmp al,018H ; MIN_MATCH_SIZE_V2 + MATCH_RUN_LEN_V2 + 15? 722 000003D9 7517 <1> jne .got_matchlen ; no, we have the full match length from the token, go copy 723 <1> 724 000003DB 836EF801728CAC <1> do_lodsb ; grab extra length byte 725 000003E2 0418 <1> add al,018H ; overflow? 726 000003E4 730C <1> jnc .got_matchlen ; if not, we have the entire length 727 <1> %if _N 728 000003E6 74A8 <1> je .end_check 729 <1> %else 730 <1> je .error ; detect EOD code 731 <1> %endif 732 <1> 733 000003E8 836EF8027303E97CFF- <1> do_lodsw ; grab 16-bit length 733 000003F1 AD <1> 734 <1> 735 <1> .got_matchlen: 736 000003F2 91 <1> xchg cx,ax ; copy match length into cx 737 000003F3 1E <1> push ds ; save ds:si (current pointer to compressed data) 738 000003F4 96 <1> xchg si,ax 739 000003F5 06 <1> push es 740 000003F6 1F <1> pop ds 741 000003F7 89FE <1> mov si, di 742 000003F9 0376FA <1> add si, word [bp + ?matchlength] 743 <1> ; ds:si now points at back reference in output data 744 000003FC 721F <1> jc @FF ; simple case branches here --> 745 000003FE 53 <1> push bx 746 000003FF 51 <1> push cx 747 00000400 8B4EFA <1> mov cx, word [bp + ?matchlength] 748 00000403 BBFFFF <1> mov bx, -1 749 00000406 06 <1> push es 750 00000407 57 <1> push di 751 00000408 E89900 <1> call normalise_pointer_with_displacement_bxcx 752 0000040B 5E <1> pop si 753 0000040C 5B <1> pop bx 754 0000040D 7334 <1> jnc .error_j2 755 0000040F 3B5EEE <1> cmp bx, word [bp + ?original_dst + 2] 756 00000412 7503 <1> jne @F 757 00000414 3B76EC <1> cmp si, word [bp + ?original_dst] 758 <1> @@: 759 00000417 722A <1> jb .error_j2 760 00000419 8EDB <1> mov ds, bx 761 0000041B 59 <1> pop cx 762 0000041C 5B <1> pop bx 763 <1> @@: 764 <1> %if _WORDLENGTH 765 <1> %ifn _UNSAFE 766 0000041D 294EF6 <1> sub word [bp + ?word_length_of_destination], cx 767 00000420 7224 <1> jb .error_or_full_3 768 <1> .after_full_3: 769 <1> %endif 770 <1> %else 771 <1> sub word [bp + ?length_of_destination], cx 772 <1> sbb word [bp + ?length_of_destination + 2], 0 773 <1> jb .error_j2 774 <1> %endif 775 00000422 F3A4 <1> rep movsb ; copy match 776 00000424 96 <1> xchg si,ax ; restore ds:si 777 00000425 1F <1> pop ds 778 <1> %if _ALLOW_OVERLAPPING 779 00000426 53 <1> push bx 780 00000427 85FF <1> test di, di 781 00000429 7409 <1> jz .zero 782 0000042B E83100 <1> call check_pointers_not_overlapping 783 <1> .waszero: 784 0000042E 5B <1> pop bx 785 0000042F 7212 <1> jc .error_j2 786 00000431 E9D7FE <1> jmp .decode_token_clear_cx 787 <1> ; go decode another token 788 <1> 789 <1> .zero: 790 00000434 06 <1> push es 791 00000435 8CC3 <1> mov bx, es ; => our block 792 00000437 81C30010 <1> add bx, 1000h ; => next 64 KiB block 793 0000043B 8EC3 <1> mov es, bx ; es:di -> after our block 794 0000043D E81F00 <1> call check_pointers_not_overlapping 795 00000440 07 <1> pop es 796 00000441 EBEB <1> jmp .waszero 797 <1> %else 798 <1> jmp .decode_token 799 <1> ; go decode another token 800 <1> %endif 801 <1> 802 <1> .error_j2: 803 00000443 E994FE <1> jmp depack.error 804 <1> 805 <1> %if _WORDLENGTH 806 <1> %ifn _UNSAFE 807 <1> .error_or_full_3: 808 00000446 E80F00 <1> call .error_or_full_common 809 00000449 EBD7 <1> jmp .after_full_3 810 <1> %endif 811 <1> %endif 812 <1> 813 <1> .get_nibble_x: 814 0000044B F5 <1> cmc ; carry set if bit 4 was set 815 0000044C D0D8 <1> rcr al,1 816 0000044E E84AFF <1> call .get_nibble ; get nibble for offset bits 0-3 817 00000451 08C8 <1> or al,cl ; merge nibble 818 00000453 D0C0 <1> rol al,1 819 00000455 34E1 <1> xor al,0E1H ; set offset bits 7-5 to 1 820 00000457 C3 <1> ret 821 <1> 822 <1> %if _WORDLENGTH 823 <1> %ifn _UNSAFE 824 <1> ; INP: ?word_length_of_destination underflowed 825 <1> ; ?bool_not_full_destination == 0 iff underflow allowed 826 <1> ; OUT: to depack.error if underflow not allowed 827 <1> ; returns near if underflow allowed, 828 <1> ; ?bool_not_full_destination = nonzero 829 <1> .error_or_full_common: 830 00000458 836EF401 <1> sub word [bp + ?bool_not_full_destination], 1 831 <1> ; like cmp word, 1 832 0000045C 73E5 <1> jae .error_j2 ; word >= 1 ? then error --> 833 <1> ; word was < 1 (full destination), now is 0FFFFh 834 0000045E C3 <1> retn 835 <1> %endif 836 <1> %endif 1825 %endif 1826 1827 1828 %if _APL 1829 %include "apl.asm" 1830 %endif 1831 1832 1833 %if _BZP 1834 %include "bzp.asm" 1835 %endif 1836 1837 1838 %if _ZEROCOMP 1839 %include "zerocomp.asm" 1840 %endif 1841 1842 1843 %if _MVCOMP 1844 %include "mvcomp.asm" 1845 %endif 1846 1847 1848 %if _LZEXEDAT 1849 %include "lzexedat.asm" 1850 %endif 1851 1852 1853 %if _ZX0 1854 %include "zx0.asm" 1855 %endif 1856 1857 1858 %if _SCAN && ! SCAN_SUPPORTED 1859 %error Scan not supported by this depacker method 1860 %endif 1861 1862 1863 %if _ALLOW_OVERLAPPING 1864 ; INP: ?src, ?dst 1865 ; OUT: CY if error (?src < ?dst) 1866 ; NC if success 1867 ; CHG: ax, bx, cx, dx 1868 check_pointers_not_overlapping: 1869 %if CHECK_POINTERS_VARIABLE_DST 1870 push word [bp + ?dst + 2] 1871 push word [bp + ?dst] 1872 %else 1873 0000045F 06 push es 1874 00000460 57 push di 1875 %endif 1876 00000461 E86F00 call pointer_to_linear 1877 1878 00000464 91 xchg cx, ax 1879 00000465 87DA xchg bx, dx ; bx:cx = linear ?dst after write 1880 1881 %if CHECK_POINTERS_VARIABLE_SRC 1882 push word [bp + ?src + 2] 1883 push word [bp + ?src] 1884 %else 1885 00000467 1E push ds 1886 00000468 56 push si 1887 %endif 1888 00000469 E86700 call pointer_to_linear ; dx:ax = linear ?src before next read 1889 1890 0000046C 39DA cmp dx, bx ; ?src >= ?dst ? 1891 0000046E 7502 jne @F 1892 00000470 39C8 cmp ax, cx 1893 @@: 1894 ; (CY) if error (src < dst) 1895 ; (NC) if no error 1896 00000472 C3 retn 1897 %endif 1898 1899 ; This leaves the lframe context created within the 1900 ; specific depacker's file. The above function 1901 ; check_pointers_not_overlapping uses the frame. 1902 lleave ctx 1903 1904 1905 ; INP: ds:si = pointer 1906 ; es:di = pointer 1907 ; OUT: ds:si normalised 1908 ; es:di normalised 1909 %if NEED_NORMALISE_BOTH_POINTERS 1910 normalise_both_pointers: 1911 00000473 06 push es 1912 00000474 57 push di 1913 00000475 E80A00 call normalise_pointer 1914 00000478 5F pop di 1915 00000479 07 pop es 1916 %endif 1917 1918 normalise_dssi_pointer: 1919 0000047A 1E push ds 1920 0000047B 56 push si 1921 0000047C E80300 call normalise_pointer 1922 0000047F 5E pop si 1923 00000480 1F pop ds 1924 00000481 C3 retn 1925 1926 1927 ; INP: word [ss:sp + 2] = segment 1928 ; word [ss:sp] = offset 1929 ; 1930 ; Note: Does not work correctly with pointers that point to 1931 ; a HMA location. Do not use then! 1932 normalise_pointer: 1933 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1934 lframe near 1935 lpar word, segment 1936 lpar word, offset 1937 lpar_return 1938 00000482 5589E5 lenter 1939 1940 00000485 837E040F cmp word [bp + ?offset], 15 1941 00000489 7617 jbe .ret 1942 1943 0000048B 53 push bx 1944 0000048C 51 push cx 1945 1946 0000048D 31DB xor bx, bx 1947 0000048F 31C9 xor cx, cx 1948 00000491 FF7606 push word [bp + ?segment] 1949 00000494 FF7604 push word [bp + ?offset] 1950 00000497 E80A00 call normalise_pointer_with_displacement_bxcx 1951 0000049A 8F4604 pop word [bp + ?offset] 1952 0000049D 8F4606 pop word [bp + ?segment] 1953 1954 000004A0 59 pop cx 1955 000004A1 5B pop bx 1956 .ret: 1957 000004A2 5D lleave 1958 000004A3 C3 lret 1959 1960 1961 ; INP: word [ss:sp + 2] = segment 1962 ; word [ss:sp] = offset 1963 ; bx:cx = add/sub displacement 1964 ; OUT: CY if the displacement carries 1965 ; NC if not 1966 normalise_pointer_with_displacement_bxcx: 1967 %endif 1968 lframe near 1969 lpar word, segment 1970 lpar word, offset 1971 lpar_return 1972 000004A4 5589E5 lenter 1973 1974 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1975 cmp word [bp + ?offset], 15 1976 jbe .ret 1977 %endif 1978 1979 000004A7 50 push ax 1980 000004A8 51 push cx 1981 000004A9 52 push dx 1982 1983 000004AA FF7606 push word [bp + ?segment] 1984 000004AD FF7604 push word [bp + ?offset] 1985 000004B0 E82000 call pointer_to_linear 1986 1987 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 1988 ; push bx 1989 ; ; sign-extend cx into bx:cx 1990 ; cmp cx, 8000h ; CY if < 8000h (NC if negative) 1991 ; cmc ; NC if positive 1992 ; sbb bx, bx ; 0 if was NC, -1 if was CY 1993 1994 000004B3 01C1 add cx, ax 1995 000004B5 11DA adc dx, bx ; dx:cx = dx:ax + bx:cx 1996 ; pop bx 1997 000004B7 9F lahf ; ah = flags 1998 %else 1999 xchg ax, cx 2000 %endif 2001 2002 %if 0 2003 ; Adds in HMA support for this function. Not currently used. 2004 cmp dx, 10h ; dx:ax >= 10_0000h ? 2005 jb @F ; no, linear-to-pointer normally --> 2006 ; ja .error 2007 2008 add cx, 10h 2009 ; jc .error 2010 mov word [bp + ?offset], cx 2011 or word [bp + ?segment], -1 2012 jmp .return 2013 @@: 2014 %endif 2015 2016 000004B8 53 push bx 2017 000004B9 89CB mov bx, cx 2018 000004BB 83E10F and cx, 15 2019 000004BE 894E04 mov word [bp + ?offset], cx 2020 2021 000004C1 B104 mov cl, 4 2022 @@: 2023 000004C3 D1EA shr dx, 1 2024 000004C5 D1DB rcr bx, 1 2025 000004C7 E2FA loop @B 2026 2027 000004C9 895E06 mov word [bp + ?segment], bx 2028 000004CC 5B pop bx 2029 2030 ; test dx, dx 2031 ; jnz .error 2032 2033 .return: 2034 2035 %if NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2036 000004CD 9E sahf ; restore flags from ah 2037 %endif 2038 000004CE 5A pop dx 2039 000004CF 59 pop cx 2040 000004D0 58 pop ax 2041 %ifn NEED_NORMALISE_POINTER_WITH_DISPLACEMENT 2042 .ret: 2043 %endif 2044 000004D1 5D lleave 2045 000004D2 C3 lret 2046 2047 2048 ; INP: word [ss:sp + 2] = segment 2049 ; word [ss:sp] = offset 2050 ; OUT: dx:ax = linear address 2051 pointer_to_linear: 2052 lframe near 2053 lpar word, segment 2054 lpar word, offset 2055 000004D3 5589E5 lenter 2056 2057 000004D6 8B4606 mov ax, word [bp + ?segment] 2058 000004D9 31D2 xor dx, dx 2059 000004DB 51 push cx 2060 000004DC B90400 mov cx, 4 2061 @@: 2062 000004DF D1E0 shl ax, 1 2063 000004E1 D1D2 rcl dx, 1 2064 000004E3 E2FA loop @B 2065 2066 000004E5 034604 add ax, word [bp + ?offset] 2067 000004E8 11CA adc dx, cx ; cx = 0 here 2068 000004EA 59 pop cx 2069 2070 000004EB 5D lleave 2071 000004EC C20400 lret 2072 2073 2074 %ifn _SCAN 2075 2076 %if _PASSLCFG 2077 align 16 2078 transfer_lcfg_block: 2079 times lcfg.size nop 2080 %endif 2081 000004EF 90 align 16 2082 init1_end: 2083 2084 2085 usesection INIT0 2086 %if _TEST_PROGRAM 2087 init0_msg: 2088 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2089 00000202 4572726F723A20556E- .error_stderr_file: db "Error: Unable to open own executable file.",13,10 2089 0000020B 61626C6520746F206F- 2089 00000214 70656E206F776E2065- 2089 0000021D 786563757461626C65- 2089 00000226 2066696C652E0D0A 2090 .error_stderr_file.length equ $ - .error_stderr_file 2091 %endif 2092 0000022E 4572726F723A204E6F- .error_stderr: db "Error: Not enough memory allocated.",13,10 2092 00000237 7420656E6F75676820- 2092 00000240 6D656D6F727920616C- 2092 00000249 6C6F63617465642E0D- 2092 00000252 0A 2093 .error_stderr.length: equ $ - .error_stderr 2094 .error_c_stdout: 2095 00000253 30 .error_stdout: db "0" 2096 %if 0 2097 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 2102 %endif 2103 00000254 0D0A db 13,10 2104 .error_c_stdout.length: equ $ - .error_c_stdout 2105 .error_stdout.length: equ $ - .error_stdout 2106 2107 00000256 90 align 1024 2108 %if ($ - $$) != 1024 2109 %error Wrong INIT0 size 2110 %endif 2111 %endif 2112 2113 align 16 2114 init0_end: 2115 2116 2117 %assign num (init1_end - init1_start) + (init0_end - init0_start) 2118 %if _BRIEFLZ 2119 %define which iniblz 2120 %elif _LZ4 2121 %define which inilz4 2122 %elif _SNAPPY 2123 %define which inisz 2124 %elif _EXODECR 2125 %define which iniexo 2126 %elif _X 2127 %define which inix 2128 %elif _HEATSHRINK 2129 %define which inihs 2130 %elif _LZD 2131 %define which inilz 2132 %elif _LZO 2133 %define which inilzo 2134 %elif _LZSA2 2135 %define which inilzsa2 2136 %elif _APL 2137 %define which iniapl 2138 %elif _BZP 2139 %define which inibzp 2140 %elif _ZEROCOMP 2141 %define which inizero 2142 %elif _MVCOMP 2143 %define which inimv 2144 %elif _LZEXEDAT 2145 %define which inilzexe 2146 %elif _ZX0 2147 %define which inizx0 2148 %endif 2149 %warning which: num bytes used for depacker 2149 ****************** warning: inilzsa2: 2288 bytes used for depacker [-w+user] 2150 2151 2152 %if _TEST_PROGRAM 2153 addsection INIT2, align=16 follows=INIT1 vstart=0 2154 init2_start: 2155 ; si => after PSP 2156 ; cs => INIT2 2157 ; psp, free, payload, init1, init2, payload space, stack 2158 ; 2159 ; The correct allocation for the test program 2160 ; is image size (init0, payload, init1, init2) 2161 ; minus init0 plus compressed payload size 2162 ; plus decompressed size plus stack. For 2163 ; simplicity, init0 subtraction may be skipped. 2164 2165 ; ss:sp -> word amount repetitions, word ax 2166 ; bx = 1 if A mode test, 2167 ; 8001h if B mode test, 2168 ; 4001h if C mode test 2169 00000000 53 push bx ; push into ?whichtest 2170 2171 lframe 0 2172 %if (_INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE) || _RELOAD_FILE 2173 lpar word, handle 2174 %endif 2175 lpar word, repetitions 2176 lpar word, whichtest 2177 %if _RELOAD_XMS 2178 lvar dword, xmsentry 2179 lvar word, xmshandle 2180 %endif 2181 %if _INCLUDE_UNCOMPRESSED && ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2182 lequ 128, buffersize 2183 lvar ?buffersize, buffer 2184 %endif 2185 00000001 5589E58D6680 lenter 2186 2187 %if _RELOAD_FILE && _RELOAD_XMS 2188 or word [bp + ?xmshandle], -1 2189 %endif 2190 2191 00000007 8B5604 mov dx, word [bp + ?repetitions] 2192 0000000A 83FAFF cmp dx, -1 2193 0000000D 7509 jne @F 2194 2195 .cmdline_error: 2196 %if _DEBUG0 2197 mov bx, -1 2198 %endif 2199 0000000F BA[FC02] mov dx, init2_msg.cmdline_error 2200 00000012 B92400 mov cx, init2_msg.cmdline_error.length 2201 00000015 E9A701 jmp init2_error 2202 2203 2204 @@: 2205 00000018 F6460340 testopt [bp + ?whichtest], 4000h 2206 0000001C 750C jnz .a_or_c 2207 0000001E F6460380 testopt [bp + ?whichtest], 8000h 2208 00000022 7406 jz .a_or_c 2209 .b: 2210 00000024 85D2 test dx, dx 2211 00000026 74E7 jz .cmdline_error 2212 00000028 EB04 jmp @F 2213 2214 .a_or_c: 2215 0000002A 85D2 test dx, dx 2216 0000002C 75E1 jnz .cmdline_error 2217 @@: 2218 2219 %if _RELOAD_XMS 2220 push si 2221 mov ax, 4300h 2222 int 2Fh 2223 cmp al, 80h 2224 %if _RELOAD_FILE 2225 jne .noxms 2226 %else 2227 jne init2_error_xms 2228 %endif 2229 mov ax, 4310h 2230 int 2Fh 2231 mov word [bp + ?xmsentry], bx 2232 mov word [bp + ?xmsentry + 2], es 2233 mov ah, 09h 2234 mov dx, KiB(payload_end - payload) 2235 call far [bp + ?xmsentry] 2236 cmp ax, 1 2237 %if _RELOAD_FILE 2238 jne .noxms 2239 %else 2240 jne init2_error_xms 2241 %endif 2242 mov word [bp + ?xmshandle], dx 2243 mov ax, cs 2244 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2247 push cs 2248 pop ds 2249 mov si, init2_xmsm_to_save 2250 mov word [si + XMSM.dsthdl], dx 2251 mov word [si + XMSM.srcadr + 2], ax 2252 %ifn _RELOAD_FILE 2253 push ax 2254 %endif 2255 mov ah, 0Bh 2256 call far [bp + ?xmsentry] 2257 cmp ax, 1 2258 jne init2_error_xms_free 2259 %ifn _RELOAD_FILE 2260 pop ax ; => payload 2261 %else 2262 .noxms: 2263 mov ax, cs 2264 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2267 @@: 2268 %endif 2269 pop si 2270 %elif _RELOAD_FILE 2271 mov ax, cs 2272 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2275 %else 2276 0000002E 8CCA mov dx, cs 2277 00000030 83C23B add dx, (init2_end - init2_start) >> 4 2278 ; => payload saving area 2279 00000033 8CC8 mov ax, cs 2280 00000035 2D5320 sub ax, ( (init1_end - init1_start) + (payload_end - payload) ) >> 4 ; => payload source for first run 2283 00000038 B90420 mov cx, (payload_end - payload) >> 4 2284 0000003B E8E502 call init2_movp ; copy payload to payload saving area 2285 %endif 2286 ; We save away the payload here because a failure 2287 ; to decompress generally overwrites part of that 2288 ; payload which was used as source. 2289 2290 0000003E 89C2 mov dx, ax ; dx => payload source to use 2291 00000040 8CC8 mov ax, cs 2292 00000042 83E84F sub ax, (init1_end - init1_start) >> 4 2293 ; ax => INIT1 2294 00000045 BB0100 mov bx, 1 ; say we're in EXE mode 2295 00000048 52 push dx 2296 00000049 50 push ax 2297 0000004A 56 push si ; si => target 2298 0000004B 0E push cs 2299 0000004C E81701 call .transfer ; call decompression 2300 0000004F 5E pop si 2301 00000050 58 pop ax 2302 00000051 5A pop dx 2303 ; Returns here after decompression. 2304 ; CY if error. 2305 00000052 7309 jnc @F 2306 2307 00000054 BA[4D02] mov dx, init2_msg.initial_error 2308 00000057 B93C00 mov cx, init2_msg.initial_error.length 2309 0000005A E96201 jmp init2_error_free 2310 2311 @@: 2312 %if _INCLUDE_UNCOMPRESSED 2313 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2314 payload_uncompressed_size equ payload_uncompressed.end - payload_uncompressed 2315 %else 2316 payload_uncompressed_size equ _TEST_PROGRAM_DECOMPRESSED_SIZE 2317 %endif 2318 0000005D E80C01 call checkdecompressed 2319 00000060 7409 je @F 2320 2321 %if _WRITE_WRONG_FILE 2322 call writefiles 2323 %endif 2324 2325 %if _DEBUG0 2326 mov bx, -1 2327 %endif 2328 00000062 BA[8902] mov dx, init2_msg.initial_error_2 2329 00000065 B93C00 mov cx, init2_msg.initial_error_2.length 2330 00000068 E95401 jmp init2_error_free 2331 2332 @@: 2333 %endif 2334 2335 0000006B F6460340 testopt [bp + ?whichtest], 4000h 2336 0000006F 741D jz @F 2337 00000071 8CC8 mov ax, cs 2338 00000073 83E84F sub ax, (init1_end - init1_start) >> 4 2339 ; ax => INIT1 2340 00000076 8EC0 mov es, ax 2341 00000078 26A1[4300] mov ax, word [es:init1_c_mode_counter] 2342 0000007C E87A01 call init2_disp_ax_dec 2343 0000007F B00D mov al, 13 2344 00000081 E86A01 call init2_disp_al 2345 00000084 B00A mov al, 10 2346 00000086 E86501 call init2_disp_al 2347 %if _RELOAD_XMS 2348 call freexms 2349 %endif 2350 00000089 B8004C mov ax, 4C00h 2351 0000008C CD21 int 21h 2352 2353 @@: 2354 lvar word, upperbound 2355 0000008E 52 push dx 2356 lvar word, lowerbound 2357 0000008F 56 push si 2358 lvar word, current_init1 2359 00000090 50 push ax 2360 2361 %if _TEST_PROGRESS 2362 00000091 BA[4202] mov dx, init2_msg.progress.1 2363 00000094 B90700 mov cx, init2_msg.progress.1.length 2364 .loop: 2365 00000097 0E push cs 2366 00000098 1F pop ds 2367 00000099 BB0200 mov bx, 2 2368 0000009C B440 mov ah, 40h 2369 0000009E CD21 int 21h 2370 %else 2371 .loop: 2372 %endif 2373 2374 000000A0 8B967EFF mov dx, [bp + ?upperbound] 2375 2376 000000A4 F6460380 testopt [bp + ?whichtest], 8000h 2377 000000A8 7419 jz @F 2378 2379 000000AA FF4E04 dec word [bp + ?repetitions] 2380 000000AD 7520 jnz .test_b_skip_bound 2381 2382 %if _TEST_PROGRESS 2383 000000AF 0E push cs 2384 000000B0 1F pop ds 2385 000000B1 BA[4B02] mov dx, init2_msg.progress.linebreak 2386 000000B4 B90200 mov cx, init2_msg.progress.linebreak.length 2387 000000B7 BB0200 mov bx, 2 2388 000000BA B440 mov ah, 40h 2389 000000BC CD21 int 21h 2390 %endif 2391 %if _RELOAD_XMS 2392 call freexms 2393 %endif 2394 000000BE B8004C mov ax, 4C00h 2395 000000C1 CD21 int 21h 2396 2397 2398 @@: 2399 000000C3 2B967CFF sub dx, [bp + ?lowerbound] 2400 000000C7 7473 jz .found 2401 000000C9 D1EA shr dx, 1 2402 ; Rounding down, so that we never retry upper bound. 2403 ; The upper bound is known to be working. 2404 000000CB 03967CFF add dx, [bp + ?lowerbound] 2405 2406 .test_b_skip_bound: 2407 000000CF 52 push dx 2408 000000D0 81C20420 add dx, (payload_end - payload) >> 4 2409 000000D4 8B867AFF mov ax, [bp + ?current_init1] 2410 000000D8 B94F00 mov cx, (init1_end - init1_start) >> 4 2411 000000DB E84502 call init2_movp 2412 000000DE 89967AFF mov [bp + ?current_init1], dx 2413 000000E2 5A pop dx 2414 2415 %if _RELOAD_XMS 2416 mov ax, [bp + ?xmshandle] 2417 %if _RELOAD_FILE 2418 cmp ax, -1 2419 je .restore_no_xms 2420 %endif 2421 push si 2422 push cs 2423 pop ds 2424 mov si, init2_xmsm_from_save 2425 mov word [si + XMSM.srchdl], ax 2426 mov word [si + XMSM.dstadr + 2], dx 2427 mov ah, 0Bh 2428 call far [bp + ?xmsentry] 2429 cmp ax, 1 2430 jne init2_error_xms_free 2431 pop si 2432 %if _RELOAD_FILE 2433 jmp .restore_done 2434 %endif 2435 %endif 2436 %if _RELOAD_FILE 2437 .restore_no_xms: 2438 size_compressed equ (payload.end - payload) 2439 push dx 2440 mov ds, dx 2441 mov cx, ((- size_compressed) >> 16) & 0FFFFh 2442 mov dx, (- size_compressed) & 0FFFFh 2443 mov ax, 4202h 2444 mov bx, [bp + ?handle] 2445 int 21h 2446 jc init2_error_file 2447 mov dx, size_compressed >> 16 2448 mov ax, size_compressed & 0FFFFh 2449 @@: 2450 mov cx, 0FF00h 2451 test dx, dx 2452 jnz @F 2453 cmp ax, cx 2454 jae @F 2455 mov cx, ax 2456 @@: 2457 sub ax, cx 2458 sbb dx, 0 2459 push dx 2460 push ax 2461 xor dx, dx 2462 mov ah, 3Fh 2463 int 21h 2464 jc init2_error_file 2465 cmp ax, cx 2466 jne init2_error_file 2467 mov dx, ds 2468 add dx, 0FF0h 2469 mov ds, dx 2470 pop ax 2471 pop dx 2472 mov cx, ax 2473 or cx, dx 2474 jnz @BB 2475 pop dx 2476 .restore_done: 2477 %endif 2478 %ifn _RELOAD_XMS || _RELOAD_FILE 2479 000000E3 8CC8 mov ax, cs 2480 000000E5 83C03B add ax, (init2_end - init2_start) >> 4 2481 ; => payload in saving area 2482 000000E8 B90420 mov cx, (payload_end - payload) >> 4 2483 000000EB E83502 call init2_movp ; copy payload from payload saving area 2484 %endif 2485 ; dx => source 2486 000000EE 8B867AFF mov ax, [bp + ?current_init1] 2487 000000F2 BB0100 mov bx, 1 2488 000000F5 52 push dx 2489 000000F6 56 push si 2490 000000F7 0E push cs 2491 000000F8 E86B00 call .transfer 2492 000000FB 5E pop si 2493 000000FC 5A pop dx 2494 ; Returns here after decompression. 2495 ; CY if error. 2496 000000FD 7313 jnc @F 2497 2498 000000FF F6460380 testopt [bp + ?whichtest], 8000h 2499 00000103 7512 jnz .test_b_fail 2500 2501 ; error: this attempt is one below the new lower bound 2502 00000105 42 inc dx 2503 00000106 89967CFF mov word [bp + ?lowerbound], dx 2504 2505 %if _TEST_PROGRESS 2506 0000010A BA[4902] mov dx, init2_msg.progress.fail 2507 0000010D B90100 mov cx, init2_msg.progress.fail.length 2508 %endif 2509 00000110 EB85 jmp .loop 2510 2511 @@: 2512 %if _INCLUDE_UNCOMPRESSED 2513 00000112 E85700 call checkdecompressed 2514 00000115 7418 je @F 2515 2516 %if _WRITE_WRONG_FILE 2517 call writefiles 2518 %endif 2519 2520 .test_b_fail: 2521 %if _TEST_PROGRESS 2522 00000117 0E push cs 2523 00000118 1F pop ds 2524 00000119 BA[4B02] mov dx, init2_msg.progress.linebreak 2525 0000011C B90200 mov cx, init2_msg.progress.linebreak.length 2526 0000011F BB0200 mov bx, 2 2527 00000122 B440 mov ah, 40h 2528 00000124 CD21 int 21h 2529 %endif 2530 %if _DEBUG0 2531 mov bx, -2 2532 %endif 2533 00000126 BA[C502] mov dx, init2_msg.subsequent_error_2 2534 00000129 B93700 mov cx, init2_msg.subsequent_error_2.length 2535 0000012C E99000 jmp init2_error_free 2536 2537 @@: 2538 %endif 2539 ; success: this attempt is the new upper bound 2540 0000012F 89967EFF mov word [bp + ?upperbound], dx 2541 %if _TEST_PROGRESS 2542 00000133 BA[4A02] mov dx, init2_msg.progress.success 2543 00000136 B90100 mov cx, init2_msg.progress.success.length 2544 %endif 2545 00000139 E95BFF jmp .loop 2546 2547 .found: 2548 %if _TEST_PROGRESS 2549 0000013C 0E push cs 2550 0000013D 1F pop ds 2551 0000013E BA[4B02] mov dx, init2_msg.progress.linebreak 2552 00000141 B90200 mov cx, init2_msg.progress.linebreak.length 2553 00000144 BB0200 mov bx, 2 2554 00000147 B440 mov ah, 40h 2555 00000149 CD21 int 21h 2556 %endif 2557 0000014B 8B867EFF mov ax, word [bp + ?upperbound] 2558 0000014F 29F0 sub ax, si ; = how many paragraphs in buffer before source 2559 00000151 055320 add ax, paras( (init1_end - init1_start) + (payload_end - payload) ) 2561 ; = how many paragraphs needed for process 2562 00000154 E8A200 call init2_disp_ax_dec 2563 00000157 B00D mov al, 13 2564 00000159 E89200 call init2_disp_al 2565 0000015C B00A mov al, 10 2566 0000015E E88D00 call init2_disp_al 2567 %if _RELOAD_XMS 2568 call freexms 2569 %endif 2570 00000161 B8004C mov ax, 4C00h 2571 00000164 CD21 int 21h 2572 2573 2574 .transfer: 2575 00000166 31FF xor di, di 2576 00000168 57 push di ; placeholder ax value on stack 2577 00000169 50 push ax ; INIT1 segment 2578 0000016A 57 push di ; zero = init1_start 2579 0000016B CB retf ; transfer to INIT1:init1_start 2580 2581 2582 2583 %if _INCLUDE_UNCOMPRESSED 2584 2585 2586 %if _WRITE_WRONG_FILE 2587 ; INP: si => decompressed image 2588 ; payload_uncompressed_size = size 2589 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2590 ; word [bp + ?handle] = file handle 2591 ; [bp + ?buffer] = ?buffersize buffer 2592 ; OUT: WRONG.BIN contains what we decompressed 2593 ; WRONG2.BIN contains expected payload 2594 ; CHG: ds, si, ax, bx, cx, dx 2595 ; STT: UP 2596 writefiles: 2597 push cs 2598 pop ds 2599 mov dx, init2_msg.wrong_file_name 2600 xor cx, cx 2601 mov ah, 3Ch 2602 int 21h 2603 jc .notfile 2604 2605 mov bx, ax 2606 mov cx, payload_uncompressed_size >> 4 2607 xor dx, dx 2608 .loopfile: 2609 mov ds, si 2610 mov ah, 40h 2611 push cx 2612 mov cx, 16 2613 int 21h 2614 pop cx 2615 inc si 2616 loop .loopfile 2617 2618 mov ds, si 2619 mov cx, payload_uncompressed_size & 15 2620 mov ah, 40h 2621 int 21h 2622 2623 mov ah, 3Eh 2624 int 21h 2625 2626 .notfile: 2627 2628 push cs 2629 pop ds 2630 mov dx, init2_msg.wrong_file_name2 2631 xor cx, cx 2632 mov ah, 3Ch 2633 int 21h 2634 jc .notfile2 2635 2636 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2637 mov bx, ax 2638 mov cx, payload_uncompressed_size >> 4 2639 mov si, cs 2640 add si, (payload_uncompressed - init2_start) >> 4 2641 xor dx, dx 2642 .loopfile2: 2643 mov ds, si 2644 mov ah, 40h 2645 push cx 2646 mov cx, 16 2647 int 21h 2648 pop cx 2649 inc si 2650 loop .loopfile2 2651 2652 mov ds, si 2653 mov cx, payload_uncompressed_size & 15 2654 mov ah, 40h 2655 int 21h 2656 2657 mov ah, 3Eh 2658 int 21h 2659 %else 2660 xchg si, ax 2661 2662 %if _RELOAD_FILE 2663 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2664 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2665 %else 2666 mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2667 mov dx, (- payload_uncompressed_size) & 0FFFFh 2668 %endif 2669 mov ax, 4202h 2670 mov bx, [bp + ?handle] 2671 int 21h 2672 jc .closefile2 2673 2674 push ss 2675 pop ds 2676 lea dx, [bp + ?buffer] 2677 2678 %if payload_uncompressed_size == 0 2679 %error Empty payload not allowed 2680 %endif 2681 %if (payload_uncompressed_size / ?buffersize) != 0 2682 mov cx, payload_uncompressed_size / ?buffersize 2683 %if ?buffersize == 0 || (?buffersize & 15) != 0 2684 %error Unexpected layout 2685 %endif 2686 .loop: 2687 push cx 2688 mov cx, ?buffersize 2689 call transferchunk 2690 pop cx 2691 jc .closefile2 2692 loop .loop 2693 %endif 2694 %if (payload_uncompressed_size % ?buffersize) != 0 2695 mov cx, payload_uncompressed_size % ?buffersize 2696 call transferchunk 2697 %endif 2698 2699 .closefile2: 2700 mov bx, si 2701 mov ah, 3Eh 2702 int 21h 2703 %endif 2704 2705 .notfile2: 2706 retn 2707 2708 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2709 ; INP: ds:dx -> buffer 2710 ; cx = size to transfer, must fit in buffer 2711 ; ?handle = source file handle 2712 ; si = destination file handle 2713 ; OUT: NC if success 2714 ; CY if error 2715 ; CHG: ax, bx 2716 ; STT: UP 2717 transferchunk: 2718 mov bx, word [bp + ?handle] 2719 mov ah, 3Fh 2720 int 21h 2721 jc .ret 2722 cmp ax, cx 2723 stc 2724 jne .ret ; if partial read --> (CY) 2725 mov bx, si 2726 mov ah, 40h 2727 int 21h 2728 jc .ret 2729 cmp ax, cx 2730 je .ret ; if not partial write --> (NC) 2731 stc 2732 .ret: 2733 retn 2734 %endif 2735 2736 %endif 2737 2738 2739 ; INP: si => decompressed image 2740 ; payload_uncompressed_size = size 2741 ; ! _INCLUDE_UNCOMPRESSED_IN_IMAGE: 2742 ; word [bp + ?handle] = file handle 2743 ; [bp + ?buffer] = ?buffersize buffer 2744 ; OUT: ZR if matching 2745 ; NZ if mismatching 2746 ; CHG: es, ds, di, bx, cx 2747 ; STT: UP 2748 checkdecompressed: 2749 0000016C 50 push ax 2750 0000016D 52 push dx 2751 0000016E 56 push si 2752 %if _INCLUDE_UNCOMPRESSED_IN_IMAGE 2753 %if _PAYLOAD_KERNEL_MAX_PARAS 2754 mov cx, _PAYLOAD_KERNEL_MAX_PARAS 2755 mov bx, 0 2756 %else 2757 mov cx, payload_uncompressed_size >> 4 2758 mov bx, payload_uncompressed_size & 15 2759 %endif 2760 mov di, cs 2761 add di, (payload_uncompressed - init2_start) >> 4 2762 jcxz .end 2763 .loop: 2764 push cx 2765 mov cx, 8 2766 mov ds, si 2767 mov es, di 2768 inc si 2769 inc di 2770 push si 2771 push di 2772 xor si, si 2773 xor di, di 2774 repe cmpsw 2775 pop di 2776 pop si 2777 pop cx 2778 jne .ret 2779 loop .loop 2780 .end: 2781 mov ds, si 2782 mov es, di 2783 xor si, si 2784 xor di, di ; (ZR) 2785 mov cx, bx 2786 repe cmpsb 2787 %else 2788 %if _RELOAD_FILE 2789 size_compressed_plus_uncompressed equ payload_uncompressed_size + (payload.end - payload) 2791 mov cx, ((- size_compressed_plus_uncompressed) >> 16) & 0FFFFh 2792 mov dx, (- size_compressed_plus_uncompressed) & 0FFFFh 2793 %else 2794 0000016F B9FDFF mov cx, ((- payload_uncompressed_size) >> 16) & 0FFFFh 2795 00000172 BAD0FF mov dx, (- payload_uncompressed_size) & 0FFFFh 2796 %endif 2797 00000175 B80242 mov ax, 4202h 2798 00000178 8B5E06 mov bx, [bp + ?handle] 2799 0000017B CD21 int 21h 2800 0000017D 7219 jc .error 2801 %if payload_uncompressed_size == 0 2802 %error Empty payload not allowed 2803 %endif 2804 %if (payload_uncompressed_size / ?buffersize) != 0 2805 0000017F B90004 mov cx, payload_uncompressed_size / ?buffersize 2806 %if ?buffersize == 0 || (?buffersize & 15) != 0 2807 %error Unexpected layout 2808 %endif 2809 .loop: 2810 00000182 51 push cx 2811 00000183 B98000 mov cx, ?buffersize 2812 00000186 E81300 call comparechunk 2813 00000189 59 pop cx 2814 0000018A 7508 jne .ret 2815 0000018C E2F4 loop .loop 2816 %endif 2817 %if (payload_uncompressed_size % ?buffersize) != 0 2818 0000018E B93000 mov cx, payload_uncompressed_size % ?buffersize 2819 00000191 E80800 call comparechunk 2820 %endif 2821 %endif 2822 .ret: 2823 00000194 5E pop si 2824 00000195 5A pop dx 2825 00000196 58 pop ax 2826 00000197 C3 retn 2827 2828 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2829 .error: 2830 00000198 0C01 or al, 1 ; NZ 2831 0000019A EBF8 jmp .ret 2832 %endif 2833 %endif 2834 2835 2836 %if ! _INCLUDE_UNCOMPRESSED_IN_IMAGE 2837 ; INP: ?buffer -> ?buffersize buffer 2838 ; cx = amount of bytes, 0 < cx <= ?buffersize 2839 ; si => chunk 2840 ; ?handle = handle 2841 ; seek -> chunk 2842 ; OUT: NZ if mismatch or error 2843 ; ZR else, 2844 ; si => next chunk (assumes full chunk) 2845 ; CHG: ds, es, di, ax, bx, cx, dx 2846 ; STT: UP 2847 comparechunk: 2848 0000019C 16 push ss 2849 0000019D 1F pop ds 2850 0000019E 8D5680 lea dx, [bp + ?buffer] 2851 000001A1 8B5E06 mov bx, [bp + ?handle] 2852 000001A4 B43F mov ah, 3Fh 2853 000001A6 CD21 int 21h 2854 000001A8 7212 jc .error 2855 000001AA 39C8 cmp ax, cx 2856 000001AC 750E jne .error 2857 000001AE 8EC6 mov es, si 2858 000001B0 83C608 add si, ?buffersize / 16 2859 000001B3 56 push si 2860 000001B4 31FF xor di, di 2861 000001B6 89D6 mov si, dx 2862 000001B8 F3A6 repe cmpsb 2863 000001BA 5E pop si 2864 .ret: 2865 000001BB C3 retn 2866 2867 .error: 2868 000001BC 0C01 or al, 1 ; NZ 2869 000001BE C3 retn 2870 %endif 2871 2872 %if _RELOAD_XMS 2873 freexms: 2874 push ax 2875 push bx 2876 push dx 2877 mov dx, -1 2878 xchg dx, [bp + ?xmshandle] 2879 %if _RELOAD_FILE 2880 cmp dx, -1 2881 je @F 2882 %endif 2883 mov ah, 0Ah 2884 call far [bp + ?xmsentry] 2885 @@: 2886 pop dx 2887 pop bx 2888 pop ax 2889 retn 2890 2891 init2_error_xms_free: 2892 call freexms 2893 init2_error_xms: 2894 mov dx, init2_msg.xms_error 2895 mov cx, init2_msg.xms_error.length 2896 jmp init2_error 2897 %endif 2898 2899 %if _RELOAD_FILE 2900 init2_error_file: 2901 mov dx, init2_msg.file_error 2902 mov cx, init2_msg.file_error.length 2903 %endif 2904 2905 init2_error_free: 2906 %if _RELOAD_XMS 2907 call freexms 2908 %endif 2909 init2_error: 2910 %if _DEBUG0 2911 push bx 2912 %endif 2913 000001BF 0E push cs 2914 000001C0 1F pop ds 2915 000001C1 BB0200 mov bx, 2 2916 000001C4 B440 mov ah, 40h 2917 000001C6 CD21 int 21h 2918 2919 %if _DEBUG0 2920 mov dx, init2_msg.rc 2921 mov cx, init2_msg.rc.length 2922 mov bx, 2 2923 mov ah, 40h 2924 int 21h 2925 pop ax 2926 call init2_error_disp_ax_hex 2927 mov dx, init2_msg.linebreak 2928 mov cx, init2_msg.linebreak.length 2929 mov bx, 2 2930 mov ah, 40h 2931 int 21h 2932 %endif 2933 2934 000001C8 F6460340 testopt [bp + ?whichtest], 4000h 2935 000001CC 7408 jz @F 2936 000001CE BA[2003] mov dx, init2_msg.error_c_stdout 2937 000001D1 B90300 mov cx, init2_msg.error_c_stdout.length 2938 000001D4 EB0C jmp @FF 2939 @@: 2940 000001D6 F6460380 testopt [bp + ?whichtest], 8000h 2941 000001DA 750D jnz @FF 2942 000001DC BA[2003] mov dx, init2_msg.error_stdout 2943 000001DF B90300 mov cx, init2_msg.error_stdout.length 2944 @@: 2945 000001E2 BB0100 mov bx, 1 2946 000001E5 B440 mov ah, 40h 2947 000001E7 CD21 int 21h 2948 @@: 2949 000001E9 B8FF4C mov ax, 4CFFh 2950 000001EC CD21 int 21h 2951 2952 lleave ctx 2953 2954 2955 %if _DEBUG0 2956 init2_error_disp_ax_hex: ; ax 2957 xchg al,ah 2958 call init2_error_disp_al_hex ; display former ah 2959 xchg al,ah ; and fall trough for al 2960 init2_error_disp_al_hex: ; al 2961 push cx 2962 mov cl,4 2963 ror al,cl 2964 call init2_error_disp_al_lownibble_hex 2965 ; display former high-nibble 2966 rol al,cl 2967 pop cx 2968 ; and fall trough for low-nibble 2969 init2_error_disp_al_lownibble_hex: 2970 push ax ; save ax for call return 2971 and al,00001111b ; high nibble must be zero 2972 add al,'0' ; if number is 0-9, now it's the correct character 2973 cmp al,'9' 2974 jna .decimalnum ; if we get decimal number with this, ok --> 2975 add al,7 ; otherwise, add 7 and we are inside our alphabet 2976 .decimalnum: 2977 call init2_error_disp_al 2978 pop ax 2979 retn 2980 2981 2982 init2_error_disp_al: 2983 push dx 2984 push cx 2985 push bx 2986 push ax 2987 mov dx, sp 2988 push ds 2989 push ss 2990 pop ds 2991 mov cx, 1 2992 mov bx, 2 2993 mov ah, 40h 2994 int 21h 2995 pop ds 2996 pop ax 2997 pop bx 2998 pop cx 2999 pop dx 3000 retn 3001 %endif 3002 3003 3004 init2_disp_al: 3005 000001EE 52 push dx 3006 000001EF 50 push ax 3007 000001F0 88C2 mov dl, al 3008 000001F2 B402 mov ah, 2 3009 000001F4 CD21 int 21h 3010 000001F6 58 pop ax 3011 000001F7 5A pop dx 3012 000001F8 C3 retn 3013 3014 3015 ; Display number in ax decimal 3016 ; 3017 ; INP: ax = number 3018 ; OUT: displayed using Int21.02 3019 ; CHG: none 3020 init2_disp_ax_dec: ; ax (no leading zeros) 3021 000001F9 53 push bx 3022 000001FA 31DB xor bx, bx 3023 .pushax: 3024 000001FC 52 push dx 3025 000001FD 50 push ax 3026 000001FE 08DB or bl, bl 3027 00000200 7405 jz .nobl 3028 00000202 80EB05 sub bl, 5 3029 00000205 F6DB neg bl 3030 .nobl: 3031 00000207 51 push cx 3032 00000208 B91027 mov cx, 10000 3033 0000020B E81B00 call .divide_out 3034 0000020E B9E803 mov cx, 1000 3035 00000211 E81500 call .divide_out 3036 00000214 B96400 mov cx, 100 3037 00000217 E80F00 call .divide_out 3038 0000021A B10A mov cl, 10 3039 0000021C E80A00 call .divide_out 3040 ; (Divisor 1 is useless) 3041 0000021F 0430 add al, '0' 3042 00000221 E8CAFF call init2_disp_al 3043 00000224 59 pop cx 3044 00000225 58 pop ax 3045 00000226 5A pop dx 3046 00000227 5B pop bx ; Caller's register 3047 00000228 C3 retn 3048 3049 3050 ; INP: ax = number 3051 ; cx = divisor 3052 ; OUT: ax = remainder of operation 3053 ; result displayed 3054 .divide_out: 3055 00000229 52 push dx 3056 0000022A 31D2 xor dx, dx 3057 0000022C F7F1 div cx ; 0:ax / cx 3058 0000022E 52 push dx ; remainder 3059 0000022F FECB dec bl 3060 00000231 7503 jnz .nobl2 3061 00000233 80CF01 or bh, 1 3062 .nobl2: 3063 00000236 08C7 or bh, al 3064 00000238 7405 jz .leadingzero 3065 0000023A 0430 add al, '0' 3066 0000023C E8AFFF call init2_disp_al ; display result 3067 .leadingzero: 3068 0000023F 58 pop ax ; remainder 3069 00000240 5A pop dx 3070 00000241 C3 retn 3071 3072 3073 init2_msg: 3074 %if _TEST_PROGRESS 3075 00000242 496E666F3A2031 .progress.1: db "Info: 1" 3076 .progress.1.length: equ $ - .progress.1 3077 00000249 46 .progress.fail: db "F" 3078 .progress.fail.length: equ $ - .progress.fail 3079 0000024A 53 .progress.success: db "S" 3080 .progress.success.length: equ $ - .progress.success 3081 0000024B 0D0A .progress.linebreak: db 13,10 3082 .progress.linebreak.length: equ $ - .progress.linebreak 3083 %endif 3084 %if _WRITE_WRONG_FILE 3085 .wrong_file_name: asciz "WRONG.BIN" 3086 .wrong_file_name2: asciz "WRONG2.BIN" 3087 %endif 3088 0000024D 4572726F723A205465- .initial_error: db "Error: Test program failed to decompress with full buffer." 3088 00000256 73742070726F677261- 3088 0000025F 6D206661696C656420- 3088 00000268 746F206465636F6D70- 3088 00000271 726573732077697468- 3088 0000027A 2066756C6C20627566- 3088 00000283 6665722E 3089 00000287 0D0A .linebreak: db 13,10 3090 .initial_error.length: equ $ - .initial_error 3091 .linebreak.length: equ $ - .linebreak 3092 %if _DEBUG0 3093 .rc: db "Error: Failure code=" 3094 .rc.length: equ $ - .rc 3095 %endif 3096 %if _INCLUDE_UNCOMPRESSED 3097 00000289 4572726F723A205465- .initial_error_2: db "Error: Test program decompressed wrongly with full buffer.",13,10 3097 00000292 73742070726F677261- 3097 0000029B 6D206465636F6D7072- 3097 000002A4 65737365642077726F- 3097 000002AD 6E676C792077697468- 3097 000002B6 2066756C6C20627566- 3097 000002BF 6665722E0D0A 3098 .initial_error_2.length: equ $ - .initial_error_2 3099 000002C5 4572726F723A205465- .subsequent_error_2: db "Error: Test program decompressed wrongly during test.",13,10 3099 000002CE 73742070726F677261- 3099 000002D7 6D206465636F6D7072- 3099 000002E0 65737365642077726F- 3099 000002E9 6E676C792064757269- 3099 000002F2 6E6720746573742E0D- 3099 000002FB 0A 3100 .subsequent_error_2.length: equ $ - .subsequent_error_2 3101 %endif 3102 000002FC 4572726F723A20496E- .cmdline_error: db "Error: Invalid command line input.",13,10 3102 00000305 76616C696420636F6D- 3102 0000030E 6D616E64206C696E65- 3102 00000317 20696E7075742E0D0A 3103 .cmdline_error.length: equ $ - .cmdline_error 3104 %if _RELOAD_XMS 3105 .xms_error: db "Error: XMS failure.",13,10 3106 .xms_error.length: equ $ - .xms_error 3107 %endif 3108 %if _RELOAD_FILE 3109 .file_error: db "Error: File read failure.",13,10 3110 .file_error.length: equ $ - .file_error 3111 %endif 3112 3113 .error_c_stdout: 3114 00000320 30 .error_stdout: db "0" 3115 %if 0 3116 _autodigits paras(_TEST_PROGRAM_DECOMPRESSED_SIZE + (payload_end - payload) + (init1_end - init1_start) + ADDITIONAL_MEMORY ) 3121 %endif 3122 00000321 0D0A db 13,10 3123 .error_c_stdout.length: equ $ - .error_c_stdout 3124 .error_stdout.length: equ $ - .error_stdout 3125 3126 3127 ; Move paragraphs 3128 ; 3129 ; INP: ax => source 3130 ; dx => destination 3131 ; cx = number of paragraphs 3132 ; CHG: - 3133 ; OUT: ax and dx unchanged 3134 ; Note: Doesn't work correctly on HMA; doesn't always wrap to LMA either. 3135 ; Do not provide a wrapped/HMA source or destination! 3136 init2_movp: 3137 00000323 51 push cx 3138 00000324 1E push ds 3139 00000325 56 push si 3140 00000326 06 push es 3141 00000327 57 push di 3142 3143 00000328 39D0 cmp ax, dx ; source above destination ? 3144 0000032A 770A ja .up ; yes, move up (forwards) --> 3145 0000032C 747B je .return ; same, no need to move --> 3146 0000032E 50 push ax 3147 0000032F 01C8 add ax, cx ; (expected not to carry) 3148 00000331 39D0 cmp ax, dx ; end of source is above destination ? 3149 00000333 58 pop ax 3150 00000334 7730 ja .down ; yes, move from top down --> 3151 ; Here, the end of source is below-or-equal the destination, 3152 ; so they do not overlap. In this case we prefer moving up. 3153 3154 .up: 3155 00000336 50 push ax 3156 00000337 52 push dx 3157 .uploop: 3158 00000338 8ED8 mov ds, ax 3159 0000033A 8EC2 mov es, dx 3160 0000033C 31FF xor di, di 3161 0000033E 31F6 xor si, si ; -> start of segment 3162 00000340 81E90010 sub cx, 1000h ; 64 KiB left ? 3163 00000344 7610 jbe .uplast ; no --> 3164 00000346 51 push cx 3165 00000347 B90080 mov cx, 10000h /2 3166 0000034A F3A5 rep movsw ; move 64 KiB 3167 0000034C 59 pop cx 3168 0000034D 050010 add ax, 1000h 3169 00000350 81C20010 add dx, 1000h ; -> next segment 3170 00000354 EBE2 jmp short .uploop ; proceed for more --> 3171 .uplast: 3172 00000356 81C10010 add cx, 1000h ; restore counter 3173 0000035A D1E1 shl cx, 1 3174 0000035C D1E1 shl cx, 1 3175 0000035E D1E1 shl cx, 1 ; *8, paragraphs to words 3176 00000360 F3A5 rep movsw ; move last part 3177 00000362 5A pop dx 3178 00000363 58 pop ax 3179 00000364 EB43 jmp short .return 3180 3181 .down: 3182 00000366 FD std ; _AMD_ERRATUM_109_WORKAROUND as below 3183 .dnloop: 3184 00000367 81E90010 sub cx, 1000h ; 64 KiB left ? 3185 0000036B 761A jbe .dnlast ; no --> 3186 0000036D 50 push ax 3187 0000036E 52 push dx 3188 0000036F 01C8 add ax, cx 3189 00000371 01CA add dx, cx 3190 00000373 8ED8 mov ds, ax ; -> 64 KiB not yet moved 3191 00000375 8EC2 mov es, dx 3192 00000377 5A pop dx 3193 00000378 58 pop ax 3194 00000379 BFFEFF mov di, -2 3195 0000037C 89FE mov si, di ; moved from last word down 3196 0000037E 51 push cx 3197 0000037F B90080 mov cx, 10000h /2 3198 00000382 F3A5 rep movsw ; move 64 KiB 3199 00000384 59 pop cx 3200 00000385 EBE0 jmp short .dnloop ; proceed for more --> 3201 .dnlast: 3202 00000387 81C10010 add cx, 1000h ; restore counter 3203 0000038B D1E1 shl cx, 1 3204 0000038D D1E1 shl cx, 1 3205 0000038F D1E1 shl cx, 1 ; *8, paragraphs to words 3206 00000391 89CF mov di, cx 3207 00000393 4F dec di 3208 00000394 D1E7 shl di, 1 ; words to offset, -> last word 3209 00000396 89FE mov si, di 3210 00000398 8ED8 mov ds, ax 3211 0000039A 8EC2 mov es, dx ; first segment correct 3212 3213 ; Refer to comment in init0_movp. 3214 %if _AMD_ERRATUM_109_WORKAROUND 3215 0000039C E308 jcxz @FF 3216 0000039E 83F914 cmp cx, 20 3217 000003A1 7703 ja @FF 3218 @@: 3219 000003A3 A5 movsw 3220 000003A4 E2FD loop @B 3221 @@: 3222 %endif 3223 000003A6 F3A5 rep movsw ; move first part 3224 000003A8 FC cld 3225 .return: 3226 000003A9 5F pop di 3227 000003AA 07 pop es 3228 000003AB 5E pop si 3229 000003AC 1F pop ds 3230 000003AD 59 pop cx 3231 000003AE C3 retn 3232 3233 3234 000003AF 90 align 4 3235 %if _RELOAD_XMS 3236 init2_xmsm_from_save: 3237 istruc XMSM 3238 at XMSM.size_, dd payload_end - payload 3239 iend 3240 init2_xmsm_to_save: 3241 istruc XMSM 3242 at XMSM.size_, dd payload_end - payload 3243 iend 3244 %endif 3245 3246 align 16 3247 3248 %if _INCLUDE_UNCOMPRESSED && _INCLUDE_UNCOMPRESSED_IN_IMAGE 3249 strdef UNCOMPRESSED_FILE, "lDOSLOAD.BIN" 3250 payload_uncompressed: 3251 incbin _UNCOMPRESSED_FILE 3252 .end: 3253 db 38 3254 align 16, db 38 3255 %endif 3256 init2_end: 3257 %endif 3258 3259 3260 %endif ; _SCAN