rev |
line source |
pascal@179
|
1 #ifndef FLAT32
|
pascal@179
|
2 // input ds:si=inStream, es:di=outStream
|
pascal@179
|
3 // output outStream[], ds:si, es:di
|
pascal@179
|
4 .code16
|
pascal@179
|
5 #define BX %bx
|
pascal@179
|
6 #define SI %si
|
pascal@179
|
7 #define DI %di
|
pascal@179
|
8 #else
|
pascal@179
|
9 // input esi=inStream, edi=outStream
|
pascal@179
|
10 // output outStream[], ds:esi, es:edi
|
pascal@179
|
11 .code32
|
pascal@179
|
12 #define BX %ebx
|
pascal@179
|
13 #define SI %esi
|
pascal@179
|
14 #define DI %edi
|
pascal@179
|
15 #endif
|
pascal@179
|
16
|
pascal@179
|
17 // unzx0_8088.S - ZX0 decompressor for 8088 - 73 bytes - NASM
|
pascal@179
|
18 //
|
pascal@179
|
19 // inputs:
|
pascal@179
|
20 // * ds:si: start of compressed data
|
pascal@179
|
21 // * es:di: start of decompression buffer
|
pascal@179
|
22 //
|
pascal@179
|
23 // Copyright (C) 2021 Emmanuel Marty
|
pascal@179
|
24 // ZX0 compression (c) 2021 Einar Saukas, https://github.com/einar-saukas/ZX0
|
pascal@179
|
25 //
|
pascal@179
|
26 // This software is provided 'as-is', without any express or implied
|
pascal@179
|
27 // warranty. In no event will the authors be held liable for any damages
|
pascal@179
|
28 // arising from the use of this software.
|
pascal@179
|
29 //
|
pascal@179
|
30 // Permission is granted to anyone to use this software for any purpose,
|
pascal@179
|
31 // including commercial applications, and to alter it and redistribute it
|
pascal@179
|
32 // freely, subject to the following restrictions:
|
pascal@179
|
33 //
|
pascal@179
|
34 // 1. The origin of this software must not be misrepresented; you must not
|
pascal@179
|
35 // claim that you wrote the original software. If you use this software
|
pascal@179
|
36 // in a product, an acknowledgment in the product documentation would be
|
pascal@179
|
37 // appreciated but is not required.
|
pascal@179
|
38 // 2. Altered source versions must be plainly marked as such, and must not be
|
pascal@179
|
39 // misrepresented as being the original software.
|
pascal@179
|
40 // 3. This notice may not be removed or altered from any source distribution.
|
pascal@179
|
41
|
pascal@179
|
42 zx0_decompress:
|
pascal@179
|
43 // cld // make string operations go forward
|
pascal@179
|
44 movb $0x80, %al // initialize empty bit queue
|
pascal@179
|
45 // plus bit to roll into carry
|
pascal@179
|
46 stc
|
pascal@179
|
47 sbb BX, BX // initialize rep-offset to 1
|
pascal@179
|
48
|
pascal@179
|
49 .literals:
|
pascal@179
|
50 #if !defined(FLAT16) && !defined(FLAT32)
|
pascal@179
|
51 movw $32768, %dx
|
pascal@179
|
52 cmpw %dx, %si // assume 32767 literals max
|
pascal@179
|
53 jb .si_ok
|
pascal@179
|
54 subw %dx, %si
|
pascal@179
|
55 movw %ds, %dx
|
pascal@179
|
56 addb $8, %dh
|
pascal@179
|
57 movw %dx, %ds
|
pascal@179
|
58 .si_ok:
|
pascal@179
|
59 #endif
|
pascal@179
|
60 call .get_elias // read number of literals to copy
|
pascal@179
|
61 rep movsb // copy literal bytes
|
pascal@179
|
62
|
pascal@179
|
63 addb %al, %al // shift bit queue, and high bit into carry
|
pascal@179
|
64 jc .get_offset // if 1: read offset, if 0: rep-match
|
pascal@179
|
65
|
pascal@179
|
66 call .get_elias // read rep-match length (starts at 1)
|
pascal@179
|
67
|
pascal@179
|
68 #if !defined(FLAT16OUT) && !defined(FLAT32)
|
pascal@179
|
69 jmp .copy_match
|
pascal@179
|
70 .fix_di:
|
pascal@179
|
71 subw $256, %di
|
pascal@179
|
72 movw %es, %dx
|
pascal@179
|
73 addw $16, %dx
|
pascal@179
|
74 movw %dx, %es
|
pascal@179
|
75 .copy_match:
|
pascal@179
|
76 cmpw $-32640, %di // assume 32639 max window
|
pascal@179
|
77 ja .fix_di
|
pascal@179
|
78 #else
|
pascal@179
|
79 .copy_match:
|
pascal@179
|
80 #endif
|
pascal@179
|
81 push SI // save si (current pointer to compressed data)
|
pascal@179
|
82 lea (BX,DI), SI // point to destination in es:di + offset in bx
|
pascal@179
|
83 #ifdef ONLY8086
|
pascal@179
|
84 .copy_loop:
|
pascal@179
|
85 movsb %es:(SI), %es:(DI) // copy matched bytes using NMOS 8088/8086 workaround.
|
pascal@179
|
86 loop .copy_loop
|
pascal@179
|
87 #else
|
pascal@179
|
88 rep movsb %es:(SI), %es:(DI) // copy matched bytes
|
pascal@179
|
89 #endif
|
pascal@179
|
90 pop SI // restore si
|
pascal@179
|
91
|
pascal@179
|
92 addb %al, %al // read 'literal or match' bit
|
pascal@179
|
93 jnc .literals // if 0: go copy literals
|
pascal@179
|
94
|
pascal@179
|
95 .get_offset:
|
pascal@179
|
96 movb $0xfe, %cl // initialize value to FEh
|
pascal@179
|
97 call .elias_loop // read high byte of match offset, set carry
|
pascal@179
|
98 incb %cl // obtain negative offset high byte
|
pascal@179
|
99 je .done // exit if EOD marker
|
pascal@179
|
100
|
pascal@179
|
101 movb %cl, %bh // transfer negative high byte into bh
|
pascal@179
|
102 movw $1, %cx // initialize match length value to 1
|
pascal@179
|
103 movb (%si), %bl // read low byte of offset + 1 bit of len
|
pascal@179
|
104 incw %si // inc instruction keep carry set
|
pascal@179
|
105 // set high bit that is shifted into bit 15
|
pascal@179
|
106 rcrw $1, %bx // shift len bit into carry/offset in place
|
pascal@179
|
107 call .elias_bt // if len bit is set, no need for more
|
pascal@179
|
108 // else read rest of elias-encoded match length
|
pascal@179
|
109 incw %cx // fix match length
|
pascal@179
|
110 jmp .copy_match // go copy match
|
pascal@179
|
111
|
pascal@179
|
112 .get_elias:
|
pascal@179
|
113 movw $1, %cx // initialize value to 1
|
pascal@179
|
114 .elias_loop:
|
pascal@179
|
115 addb %al, %al // shift bit queue, and high bit into carry
|
pascal@179
|
116 jnz .got_bit // queue not empty, bits remain
|
pascal@179
|
117 lodsb // read 8 new bits
|
pascal@179
|
118 adcb %al, %al // shift bit queue, and high bit into carry
|
pascal@179
|
119 .got_bit:
|
pascal@179
|
120 .elias_bt:
|
pascal@179
|
121 jc .got_elias // done if control bit is 1
|
pascal@179
|
122 addb %al, %al // read data bit
|
pascal@179
|
123 adcw %cx, %cx // shift into cx
|
pascal@179
|
124 jmp .elias_loop // keep reading
|
pascal@179
|
125 .got_elias:
|
pascal@179
|
126 .done:
|
pascal@179
|
127 ret
|