forked from Sterophonick/omega-de-kernel
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgba_sleep_patch.s
284 lines (263 loc) · 6.2 KB
/
gba_sleep_patch.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
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
@;********************************************************************
@;********************************************************************
@;--------------------------------------------------------------------
@;- Reset -
@;--------------------------------------------------------------------
.section .iwram,"ax",%progbits
.global Sleep_ReplaceIRQ_start
.global Sleep_ReplaceIRQ_end
.global Return_address_L
.global Sleep_key
.global Reset_key
.global Wakeup_key
REG_BASE = 0x4000000
REG_DISPCNT = 0x00
REG_DISPSTAT = 0x04
REG_VCOUNT = 0x06
REG_BG0CNT = 0x08
REG_BG1CNT = 0x0A
REG_BG2CNT = 0x0C
REG_BG3CNT = 0x0E
REG_BG0HOFS = 0x10
REG_BG0VOFS = 0x12
REG_BG1HOFS = 0x14
REG_BG1VOFS = 0x16
REG_BG2HOFS = 0x18
REG_BG2VOFS = 0x1A
REG_BG3HOFS = 0x1C
REG_BG3VOFS = 0x1E
REG_WIN0H = 0x40
REG_WIN1H = 0x42
REG_WIN0V = 0x44
REG_WIN1V = 0x46
REG_WININ = 0x48
REG_WINOUT = 0x4A
REG_BLDCNT = 0x50
REG_BLDALPHA = 0x52
REG_BLDY = 0x54
REG_SOUND1CNT_L = 0x60
REG_SOUND1CNT_H = 0x62
REG_SOUND1CNT_X = 0x64
REG_SOUND2CNT_L = 0x68
REG_SOUND2CNT_H = 0x6C
REG_SOUND3CNT_L = 0x70
REG_SOUND3CNT_H = 0x72
REG_SOUND3CNT_X = 0x74
REG_SOUND4CNT_L = 0x78
REG_SOUND4CNT_H = 0x7c
REG_SOUNDCNT_L = 0x80
REG_SOUND2CNT_H = 0x82
REG_SOUNDCNT_X = 0x84
REG_SOUNDBIAS = 0x88
REG_WAVE_RAM0_L = 0x90
REG_FIFO_A_L = 0xA0
REG_FIFO_A_H = 0xA2
REG_FIFO_B_L = 0xA4
REG_FIFO_B_H = 0xA6
REG_DM0SAD = 0xB0
REG_DM0DAD = 0xB4
REG_DM0CNT_L = 0xB8
REG_DM0CNT_H = 0xBA
REG_DM1SAD = 0xBC
REG_DM1DAD = 0xC0
REG_DM1CNT_L = 0xC4
REG_DM1CNT_H = 0xC6
REG_DM2SAD = 0xC8
REG_DM2DAD = 0xCC
REG_DM2CNT_L = 0xD0
REG_DM2CNT_H = 0xD2
REG_DM3SAD = 0xD4
REG_DM3DAD = 0xD8
REG_DM3CNT_L = 0xDC
REG_DM3CNT_H = 0xDE
REG_TM0D = 0x100
REG_TM0CNT = 0x102
REG_IE = 0x200
REG_IF = 0x202
REG_P1 = 0x130
REG_P1CNT = 0x132
REG_WAITCNT = 0x204
.arm
Sleep_ReplaceIRQ_start:
MOV R0, #0x4000000
ADR R1, my_irq
STR R1, [R0,#-0x4] @; 3FFFFFC = my_irq;
LDR R0, =0x12345678 @;//0x80000C0
BX R0 @; loc_80000C0
.align
Return_address_L:
.ltorg
@;--------------------------------------------------------------
my_irq:
@;r0 = reg_base
@;r1 = REG_IE,REG_IF
@;LDR PC, [R0,#-0xC]
LDR R1, [R0,#0x200]
TST R1, #0x10000
TSTEQ R1, #0x10000000
LDREQ PC, [R0,#-0xC] @;old_interrupt_handler
ldr r2,[r0,#REG_P1]
bic r2,r2,#0xFF000000
bic r2,r2,#0x00FF0000
@;tst r2,#0x0300 @L+R?
@;ldrne pc,[r0,#-(0x04000000-0x03FFFFB4)] @to IRQ routine if not pressed
adr r3,Reset_key @
ldr r3,[r3]
cmp r2,r3
beq reset_now
adr r3,Sleep_key @
ldr r3,[r3]
cmp r2,r3
beq sleep_now
ldr pc,[r0,#-(0x04000000-0x03FFFFF4)] @;to normal IRQ routine
@;--------------------------------------------------------------
reset_now:
adr r1,reset_code
adr r3,reset_end
mov r2,#0x02000000
copy_loop:
ldr r0,[r1],#4
str r0,[r2],#4
cmp r1,r3
blt copy_loop
mov r0,#0x02000000
add r0,r0,#1
bx r0
@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Sleep_key:
.word 0xF7 @L+R+Start?
Reset_key:
.word 0x1BD @;L up B;
@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.thumb
reset_code:
mov r0,#0x20
lsl r3,r0,#22 @;#0x8000000 r3
lsl r0,r0,#12 @;#0x0020000
add r4,r3,r0 @;#0x8020000 r4
add r5,r4,r0 @;#0x8040000 r5
lsl r1,r0,#8 @;#0x2000000
add r2,r3,r1 @;#0xa000000
lsr r1,r3,#4 @;#0x0800000
sub r6,r2,r1 @;#0x9800000
lsr r1,r1,#4 @;#0x0080000
add r6,r6,r1 @;#0x9880000 r6
sub r2,r2,r0 @;#0x9fe0000 r2
sub r7,r2,r0 @;#0x9fc0000 r7
mov r0,#210
lsl r0,r0,#8 @;0xd200 r0
mov r1,#21
lsl r1,r1,#8 @;0x1500 r1
strh r0,[r2]
strh r1,[r3]
strh r0,[r4]
strh r1,[r5]
lsr r0,r3,#12 @;#0x0008000 r0
add r0,#2
strh r0,[r6]
strh r1,[r7]
lsl r1,r0,#11 @;#0x4000000
sub r1,r1,#8 @;#0x3FFFFFA
mov r0,#0xfc @;#252 r0
str r0,[r1] @;#0x3FFFFFA (mirror of #0x3007FFA
swi 0x01
swi 0x00
reset_end:
@;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.arm
sleep_now:
stmfd sp!,{r4-r11,lr}
add r1,r0,#REG_SOUND1CNT_L
@;copy and push 32 bytes
ldmia r1!,{r2-r9}
stmfd sp!,{r2-r9}
@;copy and push 32 bytes
ldmia r1!,{r2-r9}
stmfd sp!,{r2-r9}
@;r3 = contents of REG_SOUND3CNT_X
@;save old io values
add r1,r0,#REG_IE
ldrh r4,[r1]
ldr r5,[r0,#REG_P1]
ldrh r6,[r0,#REG_DISPCNT]
@;enable ints on Keypad, Game Pak
ldr r1,=0xFFFF1000
str r1,[r0,#REG_IE]
mov r1,#0xC0000000 @;interrupt on start+sel
@;orr r1,r1,#0x000C0000
adr r2,Wakeup_key
ldr r2,[r2]
MVN R2,R2
lsl r2,r2,#0x10
orr r1,r1,r2
str r1,[r0,#REG_P1]
strh r0,[r0,#REG_SOUNDCNT_X] @;sound off
orr r1,r6,#0x80
strh r1,[r0,#REG_DISPCNT] @;LCD off
swi 0x030000
@;Loop to wait for letting go of Sel+start
loop:
mov r0,#REG_BASE
ldr r1,[r0,#REG_P1]
adr r7,Wakeup_key
ldr r7,[r7]
and r1,r1,r7
@;cmp r1,#0x000C
cmp r1,r7
bne loop
@;spin until VCOUNT==159
spin2:
ldrh r1,[r0,#REG_VCOUNT]
cmp r1,#159
bne spin2
@;spin until VCOUNT==160
spin4:
ldrh r1,[r0,#REG_VCOUNT]
cmp r1,#160
bne spin4
@;spin until VCOUNT==159
spin5:
ldrh r1,[r0,#REG_VCOUNT]
cmp r1,#159
bne spin5
@;spin until VCOUNT==160
spin6:
ldrh r1,[r0,#REG_VCOUNT]
cmp r1,#160
bne spin6
@;spin until VCOUNT==159
spin7:
ldrh r1,[r0,#REG_VCOUNT]
cmp r1,#159
bne spin7
@;restore interrupts
add r1,r0,#REG_IE
strh r4,[r1]
@;restore joystick interrupt
str r5,[r0,#REG_P1]
mov r4,#0x1000 @;clear the damn joystick interrupt
strh r4,[r1,#2]
@;restore screen
strh r6,[r0,#REG_DISPCNT]
ldmfd sp!,{r2-r9}
@;restore sound state
str r3,[r0,#REG_SOUNDCNT_X]
add r1,r0,#0x80
stmia r1!,{r2-r9}
add r1,r0,#0x60
ldmfd sp!,{r2-r9}
stmia r1!,{r2-r9}
ldmfd sp!,{r4-r11,lr}
@;spin until VCOUNT==160, triggers next vblank
spin3:
ldrh r1,[r0,#REG_VCOUNT]
cmp r1,#160
bne spin3 @<insert ytmnd cliche here>
@;all done!
ldr pc,[r0,#-(0x04000000-0x03FFFFF4)] @to IRQ routine
.align
Wakeup_key:
.word 0x3F3 @;start and select
.ltorg
Sleep_ReplaceIRQ_end:
.end