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@25490
|
60 andb $0x7F, %ch
|
pascal@25490
|
61 andw $0x8000, %dx
|
pascal@25490
|
62 copy32k:
|
pascal@25490
|
63 call lzsa2movStr
|
pascal@25490
|
64 xchg %dx, %cx
|
pascal@25490
|
65 incw %cx
|
pascal@25490
|
66 loop copy32k
|
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@25490
|
82 addw %si, %dx
|
pascal@25490
|
83 # else
|
pascal@25492
|
84 movw %si, %dx
|
pascal@25492
|
85 addw %cx, %dx
|
pascal@25490
|
86 # endif
|
pascal@25492
|
87 shll $16, %edx
|
pascal@25490
|
88 #else
|
pascal@25490
|
89 # if !defined(FLAT16)
|
pascal@25490
|
90 xorw %cx, %cx
|
pascal@25490
|
91 call normalize
|
pascal@25490
|
92 # endif
|
pascal@25490
|
93 #endif
|
pascal@25490
|
94 movb $1, %dh // no nibble stored
|
pascal@25490
|
95 lzsa2chunk: // uncompress chunk
|
pascal@25490
|
96 lodsb // get token XYZ|LL|MMM
|
pascal@25490
|
97 #if !defined(FLAT32) && !defined(FLAT16OUT)
|
pascal@25490
|
98 pushw %ax
|
pascal@25490
|
99 #else
|
pascal@25490
|
100 movb %al, %bl // keep token in bl
|
pascal@25490
|
101 #endif
|
pascal@25490
|
102 shrb $3, %al // shift literals length into place
|
pascal@25490
|
103 movw $LITERALS_RUN_LEN*256+MIN_LITERALS_SIZE, %cx
|
pascal@25490
|
104 call lzsa2len // %ch = LITERALS_RUN_LEN
|
pascal@25490
|
105 #if !defined(FLAT32) && !defined(FLAT16OUT)
|
pascal@25490
|
106 call lzsa2movLit // copy %cx literals from %ds:%si to %es:%di
|
pascal@25490
|
107 popw %bx
|
pascal@25490
|
108 #else
|
pascal@25490
|
109 rep movsb // copy %cx literals from %ds:%si to %es:%di
|
pascal@25490
|
110 #endif
|
pascal@25490
|
111 #ifndef RAW_FORMAT
|
pascal@25490
|
112 maxsi:
|
pascal@25492
|
113 shld $16, %edx, %eax
|
pascal@25492
|
114 cmpw %ax, %si
|
pascal@25490
|
115 jae lzsa2block // bail if we hit EOD
|
pascal@25490
|
116 #endif
|
pascal@25490
|
117 #ifdef FLAT32
|
pascal@25490
|
118 orl $-1, %eax // set offset bits 31-8 to 1
|
pascal@25490
|
119 #else
|
pascal@25490
|
120 movb $-1, %ah // set offset bits 15-8 to 1
|
pascal@25490
|
121 #endif
|
pascal@25490
|
122 // XYZ
|
pascal@25492
|
123 testb $0xC0, %bl // check match offset mode in token (X bit)
|
pascal@25492
|
124 bt $5, %bx // move bit 5 to carry
|
pascal@25490
|
125 js rep_match_or_large_offset
|
pascal@25490
|
126 jne offset_9_bit
|
pascal@25490
|
127 // 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
|
128 // set bits 5-15 of the offset to 1.
|
pascal@25490
|
129 call getByteFromNibble
|
pascal@25490
|
130 jmp get_match_length
|
pascal@25490
|
131 offset_9_bit:
|
pascal@25490
|
132 // 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
|
133 // set bits 9-15 of the offset to 1.
|
pascal@25492
|
134 sbbb %cl, %ah // clear bit 8 if Z bit is clear
|
pascal@25490
|
135 jmp get_match_length_0
|
pascal@25490
|
136
|
pascal@25490
|
137 getNibble:
|
pascal@25490
|
138 negb %dh
|
pascal@25490
|
139 jns gotnibble
|
pascal@25490
|
140 lodsb
|
pascal@25490
|
141 movb %al, %dl
|
pascal@25490
|
142 gotnibble:
|
pascal@25490
|
143 rolb $4, %dl
|
pascal@25490
|
144 movb %dl, %al
|
pascal@25490
|
145 andb $0xF, %al
|
pascal@25490
|
146 lzsa2quit:
|
pascal@25490
|
147 ret
|
pascal@25490
|
148
|
pascal@25490
|
149 rep_match_or_large_offset:
|
pascal@25490
|
150 jpe rep_match_or_16_bit
|
pascal@25490
|
151 //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
|
152 // then read a byte for offset bits 0-7. set bits 13-15 of the offset to 1.
|
pascal@25490
|
153 // substract 512 from the offset to get the final value.
|
pascal@25490
|
154 call getByteFromNibble
|
pascal@25490
|
155 subb $2, %al // substract 512
|
pascal@25490
|
156 jmp get_match_length_1
|
pascal@25490
|
157 rep_match_or_16_bit:
|
pascal@25492
|
158 jc repeat_match // rep-match
|
pascal@25490
|
159 //110 16-bit offset: read a byte for offset bits 8-15, then another byte for offset bits 0-7.
|
pascal@25490
|
160 lodsb // Get 2-byte match offset
|
pascal@25490
|
161 get_match_length_1:
|
pascal@25490
|
162 xchgb %al, %ah
|
pascal@25490
|
163 get_match_length_0:
|
pascal@25490
|
164 lodsb // load match offset bits 0-7
|
pascal@25490
|
165 get_match_length:
|
pascal@25490
|
166 xchgw %ax, %bp // bp: offset
|
pascal@25490
|
167 repeat_match:
|
pascal@25490
|
168 //111 repeat offset: reuse the offset value of the previous match command.
|
pascal@25490
|
169
|
pascal@25490
|
170 xchg AX, BX // %ax: original token
|
pascal@25490
|
171 movw $MATCH_RUN_LEN*256+MIN_MATCH_SIZE, %cx
|
pascal@25490
|
172 call lzsa2len
|
pascal@25490
|
173 #ifdef RAW_FORMAT
|
pascal@25490
|
174 jz lzsa2quit // bail if we hit EOD
|
pascal@25490
|
175 #endif
|
pascal@25490
|
176 #if !defined(FLAT32) && !defined(FLAT16OUT)
|
pascal@25490
|
177 pushw %ds
|
pascal@25490
|
178 pushw %si
|
pascal@25490
|
179 movw %di, %si
|
pascal@25490
|
180 addw %bp, %si
|
pascal@25490
|
181 movw %es, %ax
|
pascal@25490
|
182 jc dxok
|
pascal@25490
|
183 subb $0x10, %ah
|
pascal@25490
|
184 dxok:
|
pascal@25490
|
185 movw %ax, %ds
|
pascal@25490
|
186 call lzsa2movStr // copy string
|
pascal@25490
|
187 popw %si
|
pascal@25490
|
188 popw %ds
|
pascal@25490
|
189 #else
|
pascal@25490
|
190 xchg AX, SI // save %si
|
pascal@25490
|
191 lea (BP,DI), SI
|
pascal@25490
|
192 rep movsb %es:(SI), %es:(DI)
|
pascal@25490
|
193 xchg AX, SI // restore %si
|
pascal@25490
|
194 #endif
|
pascal@25490
|
195 jmp lzsa2chunk
|
pascal@25490
|
196
|
pascal@25490
|
197 getByteFromNibble:
|
pascal@25490
|
198 pushfw
|
pascal@25490
|
199 call getNibble // get nibble for offset bits 0-3
|
pascal@25490
|
200 popfw
|
pascal@25490
|
201 rclb $1, %al
|
pascal@25492
|
202 xorb $0xE1, %al // set offset bits 7-5 to 1
|
pascal@25490
|
203 ret
|
pascal@25490
|
204
|
pascal@25490
|
205 lzsa2len: // get length in %ecx
|
pascal@25490
|
206 andb %ch, %al
|
pascal@25490
|
207 cbw // clear %ah
|
pascal@25490
|
208 cmpb %al, %ch
|
pascal@25490
|
209 jne lzsa2minNumber // S=0-2, L=0-6
|
pascal@25490
|
210 call getNibble
|
pascal@25490
|
211 cmp $0xF, %al
|
pascal@25490
|
212 jne lzsa2noExtraByte
|
pascal@25490
|
213 lodsb
|
pascal@25490
|
214 addb $0xF, %cl
|
pascal@25490
|
215 lzsa2noExtraByte:
|
pascal@25490
|
216 addb %ch, %cl
|
pascal@25490
|
217 lzsa2minNumber:
|
pascal@25490
|
218 addb %cl, %al
|
pascal@25490
|
219 jnc lzsa2gotNumber // 0-255
|
pascal@25490
|
220 #if 0
|
pascal@25490
|
221 je lzsa2BigNumber
|
pascal@25492
|
222 movb %al, %ah // S=256-767, L=256-1791
|
pascal@25490
|
223 lodsb
|
pascal@25490
|
224 .byte 0xB1 // mask lodsb with movb $0xAD, %cl
|
pascal@25490
|
225 lzsa2BigNumber:
|
pascal@25490
|
226 #endif
|
pascal@25490
|
227 lodsw // 0-65535
|
pascal@25490
|
228 lzsa2gotNumber:
|
pascal@25490
|
229 xchgw %ax, %cx
|
pascal@25490
|
230 ret
|
pascal@25490
|
231
|
pascal@25490
|
232 #if !defined(FLAT32) && !defined(FLAT16OUT)
|
pascal@25490
|
233 # if defined(PARANOIA)
|
pascal@25490
|
234 lzsa2movlp:
|
pascal@25490
|
235 decw %ch
|
pascal@25490
|
236 rep movsb
|
pascal@25490
|
237 incw %ch
|
pascal@25490
|
238 # endif
|
pascal@25490
|
239 normalize:
|
pascal@25490
|
240 lzsa2movStr:
|
pascal@25490
|
241 movw %si, %ax
|
pascal@25490
|
242 andw $0xF, %si
|
pascal@25490
|
243 shrw $4, %ax
|
pascal@25490
|
244 movw %ds, %bx
|
pascal@25490
|
245 addw %ax, %bx
|
pascal@25490
|
246 movw %bx, %ds
|
pascal@25490
|
247 lzsa2movLit:
|
pascal@25490
|
248 movw %di, %ax
|
pascal@25490
|
249 andw $0xF, %di
|
pascal@25490
|
250 shrw $4, %ax
|
pascal@25490
|
251 movw %es, %bx
|
pascal@25490
|
252 addw %ax, %bx
|
pascal@25490
|
253 movw %bx, %es
|
pascal@25490
|
254 # if defined(PARANOIA)
|
pascal@25490
|
255 cmpb $0xFF, %ch // catch FFFX case
|
pascal@25490
|
256 je lzsa2movlp
|
pascal@25490
|
257 # endif
|
pascal@25490
|
258 rep movsb
|
pascal@25490
|
259 ret
|
pascal@25490
|
260 #endif
|