This repository has been archived by the owner on Jul 24, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lzss.baku.unsafe.asm
132 lines (104 loc) · 2.73 KB
/
lzss.baku.unsafe.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
// a decompressor for the variant of LZSS used by Bomberman 64.
// a matching compressor is available here:
// https://github.com/notwa/baku/blob/master/compressor.c
// this unsafe variant assumes that:
// * the 0x400 bytes before the destination are readable and null
// * the input data ends exactly where it is expected to
// * the input data writes exactly as many bytes as expected
// the performance gain over the safe variant is around 38%.
LzDecomp:
// a0: pointer to compressed data (must be RDRAM, cart is unsupported)
// a1: compressed size
// a2: output pointer
// a3: maximum uncompressed size
// v0: error code (0 is OK)
// t0: current pointer for reading
// t1: end pointer (exclusive)
// t2: current pointer for writing
// t3: end pointer (exclusive)
// t4: current code, shifted as necessary
// t5: 1 means raw, 0 means copy
// t6: either raw byte or part of copy command
// t7: current pseudo-position
// t8: match length
// t9: match position
beqz a1, LzExit // nothing to decompress? nothing to do!
lli v0, 0
blez a3, LzExit
lli v0, 1
or t0, a0, r0
addu t1, a0, a1
or t2, a2, r0
addu t3, a2, a3
lli t7, 0x3BE
LzNextCode:
// READ
lbu t4, 0(t0)
addiu t0, 1
ori t4, t4, 0x100 // add end marker
andi t5, t4, 1
LzReadCode:
beq t2, t3, LzExit
lli v0, 0
// READ
lbu t6, 0(t0)
addiu t0, 1
beqz t5, LzCopy
nop
LzRaw:
// WRITE
addiu t7, 1
andi t7, t7, 0x3FF
sb t6, 0(t2)
addiu t2, 1
// SHIFT
srl t4, 1
xori at, t4, 1
bnez at, LzReadCode // branch if t4 != 1
andi t5, t4, 1
// reiterate
bne t0, t1, LzNextCode
nop
b LzExit
lli v0, 0
LzCopy:
// READ
lbu t8, 0(t0)
addiu t0, 1
// extract match position
sll t9, t8, 2
andi t9, 0x0300
or t9, t6
// extract and prepare match length
andi t8, 0x003F
addiu t8, 3
// prepare absolute match position
subu t9, t7, t9
subiu t9, 1
andi t9, 0x03FF
addiu t9, 1
subu t9, t2, t9
// preemptively move pseudo-position ahead (don't need it for the loop)
addu t7, t8
andi t7, t7, 0x3FF
LzCopyLoop:
// repurposing t6: byte being copied
lbu t6, 0(t9)
// WRITE
subiu t8, 1
sb t6, 0(t2)
addiu t2, 1
bnez t8, LzCopyLoop
addiu t9, 1
// SHIFT
srl t4, 1
xori at, t4, 1
bnez at, LzReadCode // branch if t4 != 1
andi t5, t4, 1
// reiterate
bne t0, t1, LzNextCode
nop
lli v0, 0
LzExit:
jr ra
nop