aboutsummaryrefslogtreecommitdiff
path: root/tools/apultra_src/asm/ARM7TDMI/aplib_arm.s
blob: b6d0cef25a45d83318d66adb1649c0c0b992b096 (plain)
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
@APlib ARM7 decompressor by Dan Weiss, based on the original C version
@Takes in raw apacked data, NOT data created by the 'safe' compressor.
@Code is from the PocketNES NES Emulator for GBA

@Code is formatted for GNU Assembler

 src .req r0
 dest .req r1
 byte .req r2
 mask .req r3
 gamma .req r4
 lwm .req r6
 recentoff .req r7
 temp .req r8

.global depack
.type   depack STT_FUNC

@r0 = src
@r1 = dest
@r2 = byte
@r3 = rotating bit mask
@r4 = increasing gamma
@r6 = lwm
@r7 = recentoff
@r8 = lr copy/scratch

	.macro GETBIT @3 instructions
	movs mask,mask,ror #1
	ldrcsb byte,[src],#1
	tst byte,mask
	.endm

	.macro GETBITGAMMA @5 instructions
	mov gamma,gamma,lsl #1
	GETBIT
	addne gamma,gamma,#1
	.endm

@This initilaiztion code can go into slow memory

depack:
	stmfd sp!,{r4-r10,lr}
	ldrb temp,[src],#1
	strb temp,[dest],#1
	ldr mask,=0x01010101
	b aploop_nolwm

@This inner-loop code should be placed into fast memory

	@depack enters here
aploop_nolwm:
	mov lwm,#0
aploop:
	GETBIT
	bne apbranch1
	ldrb temp,[src],#1
	strb temp,[dest],#1
	b aploop_nolwm
apbranch1:
	GETBIT
	beq apbranch2
	GETBIT
	beq apbranch3
	@get an offset
	mov gamma,#0
	GETBIT
	addne gamma,gamma,#1
	GETBITGAMMA
	GETBITGAMMA
	GETBITGAMMA
	cmp gamma,#0
	ldrneb gamma,[dest,-gamma]
	strb gamma,[dest],#1
	b aploop_nolwm
apbranch3:
	@use 7 bit offset, length = 2 or 3
	@if a zero is encountered here, it's EOF
	ldrb gamma,[src],#1
	movs recentoff,gamma,lsr #1
	beq done
	ldrcsb temp,[dest,-recentoff]
	strcsb temp,[dest],#1
	ldrb temp,[dest,-recentoff]
	strb temp,[dest],#1
	ldrb temp,[dest,-recentoff]
	strb temp,[dest],#1
	mov lwm,#1
	b aploop
apbranch2:
	@use a gamma code * 256 for offset, another gamma code for length

	bl ap_getgamma
	sub gamma,gamma,#2
	cmp lwm,#0
	bne ap_is_lwm
	mov lwm,#1
	cmp gamma,#0
	bne ap_not_zero_gamma

	@if gamma code is 2, use old recent offset, and a new gamma code for length
	bl ap_getgamma
copyloop1:
	ldrb temp,[dest,-recentoff]
	strb temp,[dest],#1
	subs gamma,gamma,#1
	bne copyloop1
	b aploop
	
ap_not_zero_gamma:
	sub gamma,gamma,#1
ap_is_lwm:
	ldrb temp,[src],#1
	add recentoff,temp,gamma,lsl #8
	bl ap_getgamma
	@gamma=length
	cmp recentoff,#32000
	addge gamma,gamma,#1
	cmp recentoff,#1280
	addge gamma,gamma,#1
	cmp recentoff,#128
	addlt gamma,gamma,#2
copyloop2:
	ldrb temp,[dest,-recentoff]
	strb temp,[dest],#1
	subs gamma,gamma,#1
	bne copyloop2
	b aploop

ap_getgamma:
	mov gamma,#1
ap_getgammaloop:
	GETBITGAMMA
	GETBIT
	bne ap_getgammaloop
	bx lr

done:
	ldmfd sp!,{r4-r10,lr}
	bx lr

.unreq src
.unreq dest
.unreq byte
.unreq mask
.unreq gamma
.unreq lwm
.unreq recentoff
.unreq temp