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