-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathunlz4_old.s
155 lines (138 loc) · 4.31 KB
/
unlz4_old.s
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
;LZ4 data decompressor for Apple II
;
; http://fastcompression.blogspot.com/2011/05/lz4-explained.html
; token | literal length | literals | offset | match length
; 1 byte | 0-n bytes | 0-L bytes | 2 bytes | 0-n bytes
; token aaaabbbb
; aaaa = length of literals 0 = no literal, $f need more bytes
; bbbb = match length 0 = 4 $f = 19 after offset
; Example
; 00000000: *b4*56 6f69 7475 7265 2075 6e0a 0b00 *45*64 .Voiture un...Ed
; 00000010: 6575 780d 00*55* 7472 6f69 730e 00*70* 7175 eux..Utrois..pqu
; 00000020: 6174 7265 0a atre.
; token b4: b = 11 = length of literals
; output Voiture un@
; 01234567890
; offset 000b -> -11 before offset, match = 4 + 4 = 8 -> Voiture(space)
; output Voiture un@Voiture
; 0123456789012345678
; token 45: 4 literals = deux
; output Voiture un@Voiture deux
; 01234567890123456789012
; offset 000d -> -13 (@ position), match length = 5+4 = 9
; output Voiture un@Voiture deux@Voiture
; 01234567890123456789012345678901
; token 55
; output Voiture un@Voiture deux@Voiture trois
; 0123456789012345678901234567890123456
; offset 000e, length 5+4=9
; output Voiture un@Voiture deux@Voiture trois@Voiture
; 0123456789012345678901234567890123456789012345
; token 70
; output Voiture un@Voiture deux@Voiture trois@Voiture quatre@
; 0123456789012345678901234567890123456789012345
src = $06
dst = $08
.if DIRECT
* = $300
.fi
inflate
ldy #0 ; Y is always 0
parsetoken
jsr getsrc ; get token
pha ; push it
lsr ; get # litterals
lsr
lsr
lsr
beq copymatches ; if 0, no litterals
jsr buildcount ; after, A = LSB #, count = MSB #
tax
jsr docopy ; use X LSB / count MSB
lda src ; src >= end ?
cmp end
lda src+1
sbc end+1
bge lzdone ; yes, done
copymatches ; else copymatch phase
jsr getsrc ; get offset (2 bytes)
sta offset
jsr getsrc
sta offset+1
pla ; get token
and #$0f ;
jsr buildcount
clc ; add 4 to get matchlength
adc #4
tax ;
bcc + ; if more than $FF, MSB++
inc count
+ lda src ; push src on stack
pha
lda src+1
pha
sec ; src = dst - offset
lda dst
sbc offset
sta src
lda dst+1
sbc offset+1
sta src+1
jsr docopy ; copy temporarily from dest - offset to dest
pla ; restore src
sta src+1
pla
sta src
jmp parsetoken ; end of block -> next token
docopy jsr getput ; copy X + 256 * [count] litterals
dex ; get value
bne docopy
dec count
bpl docopy
rts
; example1: 4x
; at enter, A = $04, at exit A = 4 and count = 0
;
; example2: Fx FF F3 for literals length
; at enter, A = $0F
; tmp only matters to get carry C and increment count
; count = 0, then get next A = $FF
; $FF + $F = $10E > $100 -> count = 1, A = $0E
; count = 1, tmp = $0E then get next A = $F3
; $F3 + $E = $101, count=2 and A = $01
; # = 256 * [count] + A (X is useless)
buildcount ; build count from token nibble
ldx #0 ;
stx count
cmp #$0f ; if nibble == $f, read next byte
bne bc_rts ; else exit
- sta tmp ; store A=LSB in tmp
jsr getsrc ; get next byte in A
tax ; copy in X for $FF test
clc ; tmp ~ count LSB
adc tmp ; if A + tmp > $FF, C is set
bcc + ;
inc count ; if carry, incr count=MSB
+ inx ; if $FF read, X=0 -> continue
beq -
bc_rts rts
lzdone pla ; restore stack (parsetoken pha)
rts
; get byte from src and put to dest
getput jsr getsrc ; (dst++) <- (src++)
; put byte from A to dest
putdst sta (dst), y ; store to (dst++)
inc dst
bne +
inc dst+1
+ rts
; get byte in A from src
getsrc lda (src), y ; get from (src++)
inc src
bne +
inc src+1
+ rts
end .word 0
offset .word 0
count .byte 0
tmp .byte 0