rev |
line source |
pascal@25514
|
1 // Lzsa2Decode:
|
pascal@25514
|
2 #ifndef FLAT32
|
pascal@25514
|
3 // input ds:si=inStream, es:di=outStream
|
pascal@25514
|
4 // output outStream[], ds:si, es:di
|
pascal@25514
|
5 .code16
|
pascal@25514
|
6 #define AX %ax
|
pascal@25514
|
7 #define BX %bx
|
pascal@25514
|
8 #define BP %bp
|
pascal@25514
|
9 #define SI %si
|
pascal@25514
|
10 #define DI %di
|
pascal@25514
|
11 #else
|
pascal@25514
|
12 // input esi=inStream, edi=outStream
|
pascal@25514
|
13 // output outStream[], ds:esi, es:edi
|
pascal@25514
|
14 .code32
|
pascal@25514
|
15 #define AX %eax
|
pascal@25514
|
16 #define BX %ebx
|
pascal@25514
|
17 #define BP %ebp
|
pascal@25514
|
18 #define SI %esi
|
pascal@25514
|
19 #define DI %edi
|
pascal@25514
|
20 #endif
|
pascal@25514
|
21
|
pascal@25514
|
22 MATCH_RUN_LEN = 7
|
pascal@25514
|
23 LITERALS_RUN_LEN = 3
|
pascal@25514
|
24 MIN_MATCH_SIZE = 2
|
pascal@25514
|
25 MIN_LITERALS_SIZE = 0
|
pascal@25514
|
26
|
pascal@25514
|
27 #define PACKED_ONLY // assume no copy block, optional
|
pascal@25514
|
28 //#define PARANOIA // cover rare cases, optional
|
pascal@25514
|
29
|
pascal@25514
|
30 lzsa2main:
|
pascal@25514
|
31 #ifdef PARANOIA
|
pascal@25514
|
32 cld
|
pascal@25514
|
33 #endif
|
pascal@25514
|
34 #ifdef FLAT16OUT
|
pascal@25514
|
35 #define RAW_FORMAT
|
pascal@25514
|
36 #endif
|
pascal@25514
|
37 #ifndef RAW_FORMAT
|
pascal@25514
|
38 # if defined(PARANOIA) && !defined(FLAT32) && !defined(FLAT16)
|
pascal@25514
|
39 xorw %cx, %cx
|
pascal@25514
|
40 call normalize
|
pascal@25514
|
41 # endif
|
pascal@25514
|
42 # ifndef NO_LZSA2_HEADER
|
pascal@25514
|
43 lodsw
|
pascal@25514
|
44 cmpw $0x9E7B, %ax // magic
|
pascal@25514
|
45 jne lzsa2main
|
pascal@25514
|
46 lodsb
|
pascal@25514
|
47 testb $0x20, %al // lzsa2
|
pascal@25514
|
48 je lzsa2main
|
pascal@25514
|
49 # endif
|
pascal@25514
|
50 lzsa2block: // uncompress chunk
|
pascal@25514
|
51 # if !defined(FLAT32) && !defined(FLAT16)
|
pascal@25514
|
52 xorw %cx, %cx
|
pascal@25514
|
53 call normalize
|
pascal@25514
|
54 # endif
|
pascal@25514
|
55 lodsw // block size
|
pascal@25514
|
56 xchgw %ax, %cx
|
pascal@25514
|
57 lodsb
|
pascal@25514
|
58 # ifndef PACKED_ONLY
|
pascal@25514
|
59 orb %al, %al
|
pascal@25514
|
60 jns lzsa2compressed
|
pascal@25514
|
61 # if !defined(FLAT32) && !defined(FLAT16OUT)
|
pascal@25514
|
62 movw %cx, %dx
|
pascal@25514
|
63 movb $0, %cl
|
pascal@25514
|
64 movb $0, %dh
|
pascal@25514
|
65 copytail:
|
pascal@25514
|
66 call lzsa1movStr
|
pascal@25514
|
67 xchg %dx, %cx
|
pascal@25514
|
68 incw %cx
|
pascal@25514
|
69 loop copytail
|
pascal@25514
|
70 # else
|
pascal@25514
|
71 movsb // copy block
|
pascal@25514
|
72 copylp:
|
pascal@25514
|
73 movsb // copy block
|
pascal@25514
|
74 loop copylp // handle 64K case
|
pascal@25514
|
75 # endif
|
pascal@25514
|
76 jmp lzsa2block // end of block
|
pascal@25514
|
77 lzsa2compressed:
|
pascal@25514
|
78 jne lzsa2chunk // 64Kb block
|
pascal@25514
|
79 # endif
|
pascal@25514
|
80 jcxz lzsa2quit // bail if we hit EOD
|
pascal@25514
|
81 # if !defined(FLAT16)
|
pascal@25514
|
82 pushw %cx
|
pascal@25514
|
83 xorw %cx, %cx
|
pascal@25514
|
84 call normalize
|
pascal@25514
|
85 # define NeedNormalize
|
pascal@25514
|
86 popw %dx
|
pascal@25514
|
87 addw %si, %dx
|
pascal@25514
|
88 # else
|
pascal@25514
|
89 movw %si, %dx
|
pascal@25514
|
90 addw %cx, %dx
|
pascal@25514
|
91 # endif
|
pascal@25514
|
92 #else
|
pascal@25514
|
93 # if !defined(FLAT16)
|
pascal@25514
|
94 xorw %cx, %cx
|
pascal@25514
|
95 call normalize
|
pascal@25514
|
96 # define NeedNormalize
|
pascal@25514
|
97 # endif
|
pascal@25514
|
98 #endif
|
pascal@25514
|
99 movb $0, %bh // no nibble stored
|
pascal@25514
|
100 lzsa2chunk: // uncompress chunk
|
pascal@25514
|
101 lodsb // get token XYZ|LL|MMM
|
pascal@25514
|
102 movb %al, %bl // keep token in bl
|
pascal@25514
|
103 movw $LITERALS_RUN_LEN+256*MIN_LITERALS_SIZE, %cx
|
pascal@25514
|
104 shrb %cl, %al // shift literals length into place
|
pascal@25514
|
105 call lzsa2len // %cl = LITERALS_RUN_LEN
|
pascal@25514
|
106 #if defined(NeedNormalize)
|
pascal@25514
|
107 pushw %bp
|
pascal@25514
|
108 call lzsa2movLit // copy %cx literals from %ds:%si to %es:%di
|
pascal@25514
|
109 popw %bp
|
pascal@25514
|
110 #else
|
pascal@25514
|
111 rep movsb // copy %cx literals from %ds:%si to %es:%di
|
pascal@25514
|
112 #endif
|
pascal@25514
|
113 #ifndef RAW_FORMAT
|
pascal@25514
|
114 maxsi:
|
pascal@25514
|
115 cmpw %dx, %si
|
pascal@25514
|
116 jae lzsa2block // bail if we hit EOD
|
pascal@25514
|
117 #endif
|
pascal@25514
|
118 #ifdef FLAT32
|
pascal@25514
|
119 orl $-1, %eax // set offset bits 31-8 to 1
|
pascal@25514
|
120 #else
|
pascal@25514
|
121 movb $-1, %ah // set offset bits 15-8 to 1
|
pascal@25514
|
122 #endif
|
pascal@25514
|
123 // XYZ
|
pascal@25514
|
124 testb $0xC0, %bl // check match offset mode in token (X bit)
|
pascal@25514
|
125 bt $5, %bx // move bit 5 to carry
|
pascal@25514
|
126 js rep_match_or_large_offset
|
pascal@25514
|
127 jne offset_9_bit
|
pascal@25514
|
128 // 00Z 5-bit offset: read a nibble for offset bits 1-4 and use the inverted bit Z of the token as bit 0 of the offset.
|
pascal@25514
|
129 // set bits 5-15 of the offset to 1.
|
pascal@25514
|
130 call getByteFromNibbleAndC
|
pascal@25514
|
131 jmp get_match_length
|
pascal@25514
|
132 offset_9_bit:
|
pascal@25514
|
133 // 01Z 9-bit offset: read a byte for offset bits 0-7 and use the inverted bit Z for bit 8 of the offset.
|
pascal@25514
|
134 // set bits 9-15 of the offset to 1.
|
pascal@25514
|
135 sbbb %cl, %ah // clear bit 8 if Z bit is clear
|
pascal@25514
|
136 jmp get_match_length_0
|
pascal@25514
|
137
|
pascal@25514
|
138 getNibble:
|
pascal@25514
|
139 xorb $0xF0, %bh // toggle nibble stored flags
|
pascal@25514
|
140 movb %bh, %al
|
pascal@25514
|
141 jns gotnibble
|
pascal@25514
|
142 lodsb
|
pascal@25514
|
143 movb $0xF0, %bh
|
pascal@25514
|
144 orb %al, %bh
|
pascal@25514
|
145 shrb $4, %al
|
pascal@25514
|
146 gotnibble:
|
pascal@25514
|
147 lzsa2quit:
|
pascal@25514
|
148 ret
|
pascal@25514
|
149
|
pascal@25514
|
150 rep_match_or_large_offset:
|
pascal@25514
|
151 jpe rep_match_or_16_bit
|
pascal@25514
|
152 //10Z 13-bit offset: read a nibble for offset bits 9-12 and use the inverted bit Z for bit 8 of the offset,
|
pascal@25514
|
153 // then read a byte for offset bits 0-7. set bits 13-15 of the offset to 1.
|
pascal@25514
|
154 // substract 512 from the offset to get the final value.
|
pascal@25514
|
155 call getByteFromNibbleAndC
|
pascal@25514
|
156 subb $2, %al // substract 512
|
pascal@25514
|
157 jmp get_match_length_1
|
pascal@25514
|
158 rep_match_or_16_bit:
|
pascal@25514
|
159 jc repeat_match // rep-match
|
pascal@25514
|
160 //110 16-bit offset: read a byte for offset bits 8-15, then another byte for offset bits 0-7.
|
pascal@25514
|
161 lodsb // Get 2-byte match offset
|
pascal@25514
|
162 get_match_length_1:
|
pascal@25514
|
163 xchgb %al, %ah
|
pascal@25514
|
164 get_match_length_0:
|
pascal@25514
|
165 lodsb // load match offset bits 0-7
|
pascal@25514
|
166 get_match_length:
|
pascal@25514
|
167 xchgw %ax, %bp // bp: offset
|
pascal@25514
|
168 repeat_match:
|
pascal@25514
|
169 //111 repeat offset: reuse the offset value of the previous match command.
|
pascal@25514
|
170
|
pascal@25514
|
171 movb %bl, %al // %al: original token
|
pascal@25514
|
172 movw $MATCH_RUN_LEN+256*MIN_MATCH_SIZE, %cx
|
pascal@25514
|
173 call lzsa2len
|
pascal@25514
|
174 #ifdef RAW_FORMAT
|
pascal@25514
|
175 jcxz lzsa2quit // bail if we hit EOD
|
pascal@25514
|
176 #endif
|
pascal@25514
|
177 #if !defined(FLAT32) && !defined(FLAT16OUT)
|
pascal@25514
|
178 pushw %ds
|
pascal@25514
|
179 pushw %si
|
pascal@25514
|
180 movw %di, %si
|
pascal@25514
|
181 addw %bp, %si
|
pascal@25514
|
182 movw %es, %ax
|
pascal@25514
|
183 jc axok
|
pascal@25514
|
184 subb $0x10, %ah
|
pascal@25514
|
185 axok:
|
pascal@25514
|
186 .macro norm reg
|
pascal@25514
|
187 movw %si, \reg
|
pascal@25514
|
188 subw %si, %dx
|
pascal@25514
|
189 andw $0xF, %si
|
pascal@25514
|
190 addw %si, %dx
|
pascal@25514
|
191 shrw $4, \reg
|
pascal@25514
|
192 addw \reg, %ax
|
pascal@25514
|
193 movw %ax, %ds
|
pascal@25514
|
194 movw %di, \reg
|
pascal@25514
|
195 andw $0xF, %di
|
pascal@25514
|
196 shrw $4, \reg
|
pascal@25514
|
197 movw %es, %ax
|
pascal@25514
|
198 addw \reg, %ax
|
pascal@25514
|
199 movw %ax, %es
|
pascal@25514
|
200 .endm
|
pascal@25514
|
201 pushw %bp
|
pascal@25514
|
202 pushw %dx
|
pascal@25514
|
203 # if defined(NeedNormalize) || defined(PARANOIA)
|
pascal@25514
|
204 call lzsa2movStr // copy string
|
pascal@25514
|
205 # else
|
pascal@25514
|
206 norm %bp
|
pascal@25514
|
207 rep movsb
|
pascal@25514
|
208 # endif
|
pascal@25514
|
209 popw %dx
|
pascal@25514
|
210 popw %bp
|
pascal@25514
|
211 popw %si
|
pascal@25514
|
212 popw %ds
|
pascal@25514
|
213 #else
|
pascal@25514
|
214 xchg AX, SI // save %si
|
pascal@25514
|
215 lea (BP,DI), SI
|
pascal@25514
|
216 rep movsb %es:(SI), %es:(DI)
|
pascal@25514
|
217 xchg AX, SI // restore %si
|
pascal@25514
|
218 #endif
|
pascal@25514
|
219 jmp lzsa2chunk
|
pascal@25514
|
220
|
pascal@25514
|
221 getByteFromNibbleAndC:
|
pascal@25514
|
222 pushfw
|
pascal@25514
|
223 call getNibble // get nibble for offset bits 0-3
|
pascal@25514
|
224 popfw
|
pascal@25514
|
225 rclb $1, %al
|
pascal@25514
|
226 xorb $0xE1, %al // set offset bits 7-5 to 1
|
pascal@25514
|
227 ret
|
pascal@25514
|
228
|
pascal@25514
|
229 lzsa2len: // get length in %cx
|
pascal@25514
|
230 andb %cl, %al
|
pascal@25514
|
231 cbw // clear %ah
|
pascal@25514
|
232 cmpb %al, %cl
|
pascal@25514
|
233 jne lzsa2minNumber // S=0-2, L=0-6
|
pascal@25514
|
234 call getNibble
|
pascal@25514
|
235 cmp $0xF, %al
|
pascal@25514
|
236 jne lzsa2noExtraByte
|
pascal@25514
|
237 addb %al, %ch
|
pascal@25514
|
238 lodsb
|
pascal@25514
|
239 lzsa2noExtraByte:
|
pascal@25514
|
240 addb %cl, %ch
|
pascal@25514
|
241 lzsa2minNumber:
|
pascal@25514
|
242 addb %ch, %al
|
pascal@25514
|
243 jnc lzsa2gotNumber // 0-255
|
pascal@25514
|
244 #if 0
|
pascal@25514
|
245 je lzsa2BigNumber
|
pascal@25514
|
246 movb %al, %ah // S=256-767, L=256-1791
|
pascal@25514
|
247 lodsb
|
pascal@25514
|
248 .byte 0xB1 // mask lodsw with movb $0xAD, %cl
|
pascal@25514
|
249 lzsa2BigNumber:
|
pascal@25514
|
250 #endif
|
pascal@25514
|
251 lodsw // 0-65535
|
pascal@25514
|
252 lzsa2gotNumber:
|
pascal@25514
|
253 xchgw %ax, %cx
|
pascal@25514
|
254 ret
|
pascal@25514
|
255
|
pascal@25514
|
256 #if defined(NeedNormalize) || defined(PARANOIA)
|
pascal@25514
|
257 # if defined(PARANOIA)
|
pascal@25514
|
258 lzsa2movlp:
|
pascal@25514
|
259 decw %ch
|
pascal@25514
|
260 rep movsb
|
pascal@25514
|
261 incw %ch
|
pascal@25514
|
262 # endif
|
pascal@25514
|
263 normalize:
|
pascal@25514
|
264 lzsa2movLit:
|
pascal@25514
|
265 movw %ds, %ax
|
pascal@25514
|
266 lzsa2movStr:
|
pascal@25514
|
267 norm %bp
|
pascal@25514
|
268 # if defined(PARANOIA)
|
pascal@25514
|
269 cmpb $0xFF, %ch // catch FFFX case
|
pascal@25514
|
270 je lzsa2movlp
|
pascal@25514
|
271 # endif
|
pascal@25514
|
272 rep movsb
|
pascal@25514
|
273 ret
|
pascal@25514
|
274 #endif
|