/
decrunch_extreme.asm
342 lines (257 loc) · 4.46 KB
/
decrunch_extreme.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/*
decrunch_extreme.asm
NMOS 6502 decompressor for data stored in TSCrunch format.
This code is written for the KickAssembler assembler.
Copyright Antonio Savona 2022.
*/
//#define INPLACE //Enables inplace decrunching. Use -i switch when crunching.
.label tsget = $f8 //2 bytes
.label tstemp = $fa
.label tsput = $fb //2 bytes
.label lzput = $fd //2 bytes
#if INPLACE
.macro TS_DECRUNCH(src)
{
lda #<src
sta.zp tsget
lda #>src
sta.zp tsget + 1
jsr tsdecrunch
}
#else
.macro TS_DECRUNCH(src,dst)
{
lda #<src
sta.zp tsget
lda #>src
sta.zp tsget + 1
lda #<dst
sta.zp tsput
lda #>dst
sta.zp tsput + 1
jsr tsdecrunch
}
#endif
tsdecrunch:
{
decrunch:
#if INPLACE
ldy #$ff
!: iny
lda (tsget),y
sta tsput , y //last iteration trashes lzput, with no effect.
cpy #3
bne !-
pha
lda lzput
sta optRun + 1
ldx #$d0 //bne opcode
and #1
bne !skp+
ldx #$29 //and immediate opcode
!skp:
stx optOdd
tya
ldy #0
beq update_getonly
#else
ldy #0
lda (tsget),y
sta optRun + 1
ldx #$d0 //bne opcode
and #1
bne !skp+
ldx #$29 //and immediate opcode
!skp:
stx optOdd
inc tsget
bne entry2
inc tsget + 1
#endif
entry2:
lax (tsget),y
bmi rleorlz
cmp #$20
bcs lz2
//literal
#if INPLACE
inc tsget
beq updatelit_hi
return_from_updatelit:
and #1
bne !odd+
ts_delit_loop:
lda (tsget),y
sta (tsput),y
iny
dex
!odd:
lda (tsget),y
sta (tsput),y
iny
dex
bne ts_delit_loop
tya
tax
//carry is clear
ldy #0
#else //not inplace
tay
and #1
bne !odd+
ts_delit_loop:
lda (tsget),y
dey
sta (tsput),y
!odd:
lda (tsget),y
dey
sta (tsput),y
bne ts_delit_loop
txa
inx
#endif
updatezp_noclc:
adc tsput
sta tsput
bcs updateput_hi
putnoof:
txa
update_getonly:
adc tsget
sta tsget
bcc entry2
inc tsget+1
bcs entry2
#if INPLACE
updatelit_hi:
inc tsget+1
bcc return_from_updatelit
#endif
updateput_hi:
inc tsput+1
clc
bcc putnoof
//LZ2
lz2:
beq done
ora #$80
adc tsput
sta lzput
lda tsput + 1
sbc #$00
sta lzput + 1
//y already zero
lda (lzput),y
sta (tsput),y
iny
lda (lzput),y
sta (tsput),y
tya
dey
adc tsput
sta tsput
bcs lz2_put_hi
!skp:
inc tsget
bne entry2
inc tsget + 1
bne entry2
lz2_put_hi:
inc tsput + 1
bcs !skp-
rleorlz:
alr #$7f
bcc ts_delz
//RLE
beq zeroRun
plain:
iny
sta tstemp //number of bytes to de-rle
lsr //c = test parity
lda (tsget),y //fetch rle byte
ldy tstemp
runStart:
sta (tsput),y
bcs !odd+
sec
ts_derle_loop:
dey
sta (tsput),y
!odd:
dey
sta (tsput),y
bne ts_derle_loop
//update zero page with a = runlen, x = 2 , y = 0
lda tstemp
ldx #2
bcs updatezp_noclc
done:
#if INPLACE
pla
sta (tsput),y
#endif
rts
//LZ
ts_delz:
lsr
sta lzto + 1
iny
lda tsput
bcc long
sbc (tsget),y
sta lzput
lda tsput+1
sbc #$00
ldx #2
//lz MUST decrunch forward
lz_put:
sta lzput+1
ldy #0
lda lzto + 1
lsr
bcs !odd+
lda (lzput),y
sta (tsput),y
ts_delz_loop:
iny
!odd:
lda (lzput),y
sta (tsput),y
iny
lda (lzput),y
sta (tsput),y
lzto: cpy #0
bne ts_delz_loop
tya
//update zero page with a = runlen, x = 2, y = 0
ldy #0
//clc not needed as we have len - 1 in A (from the encoder) and C = 1
jmp updatezp_noclc
zeroRun:
optRun: ldy #255
sta (tsput),y
optOdd: bne !odd+
ts_dezero_loop:
dey
sta (tsput),y
!odd:
dey
sta (tsput),y
bne ts_dezero_loop
lda optRun + 1
ldx #1
jmp updatezp_noclc
long:
//carry is clear and compensated for from the encoder
adc (tsget),y
sta lzput
iny
lax (tsget),y
ora #$80
adc tsput + 1
cpx #$80
rol lzto + 1
ldx #3
bne lz_put
}