gbdk-2020 | GameBoy Development Kit |
| download: https://git.y1.nz/archives/gbdk.tar.gz | |
| README | Files | Log | Refs | LICENSE |
gbdk-lib/libc/targets/sm83/duck/crash_handler.s
1 ; Crash handler support
2 ; Original code by ISSOtm
3 ; Adapted by Toxa from gb-starter-kit: https://github.com/ISSOtm/gb-starter-kit
4
5 .include "global.s"
6
7 .globl _font_ibm
8
9 SCRN_X = 160 ; Width of screen in pixels
10 SCRN_Y = 144 ; Height of screen in pixels
11 SCRN_X_B = 20 ; Width of screen in bytes
12 SCRN_Y_B = 18 ; Height of screen in bytes
13
14 SCRN_VX = 256 ; Virtual width of screen in pixels
15 SCRN_VY = 256 ; Virtual height of screen in pixels
16 SCRN_VX_B = 32 ; Virtual width of screen in bytes
17 SCRN_VY_B = 32 ; Virtual height of screen in bytes
18
19
20 .area _CRASH_HEADER(ABS)
21
22 .org 0x38
23 di
24 jp ___HandleCrash
25
26
27 .area _HOME
28
29 ___HandleCrash::
30
31 ; We will use VRAM as scratch, since we are going to overwrite it for
32 ; screen output anyways. The thing is, we need to turn the LCD off
33 ; *without* affecting flags... fun task, eh?
34
35 ; Note: it's assumed that this was jumped to with IME off.
36 ; Don't call this directly, use `rst Crash`.
37
38 ld (wCrashA), a ; We need to have at least one working register, so...
39 ldh a, (.IE) ; We're also going to overwrite this
40 ld (wCrashIE), a
41 ldh a, (.LCDC)
42 ld (wCrashLCDC), a
43 ld a, #LCDCF_ON ; LCDCF_ON Make sure the LCD is turned on to avoid waiting infinitely
44 ldh (.LCDC), a
45 ld a, #IEF_VBLANK ; IEF_VBLANK
46 ldh (.IE), a
47 ld a, #0 ; `xor a` would overwrite flags
48 ldh (.IFL), a ; No point in backing up that register, it's always changing
49 halt ; With interrupts disabled, this will exit when `IE & IF != 0`
50 nop ; Handle hardware bug if it becomes true *before* starting to execute the instruction (1-cycle window)
51
52 ; We're now in VBlank! So we can now use VRAM as scratch for some cycles
53 ld a, #0
54 ldh (.LCDC), a ; Turn off LCD so VRAM can always be safely accessed
55 ; Save regs
56 ld (vCrashSP), sp
57 ld sp, #vCrashSP
58 push hl
59 push de
60 push bc
61 ld a, (wCrashA)
62 push af
63
64 ; We need to have all the data in bank 0, but we can't guarantee we were there
65 ldh a, (.VBK)
66 ld e, a
67 bit #0, a
68 jr z, .bank0
69 ; Oh noes. We need to copy the data across banks!
70 ld hl, #vCrashAF
71 ld c, #(5 * 2)
72 .copyAcross:
73 ld b, (hl)
74 xor a
75 ldh (.VBK), a
76 ld (hl), b
77 inc l ; inc hl
78 inc a ; ld a, 1
79 ldh (.VBK), a
80 dec c
81 jr nz, .copyAcross
82 .bank0:
83 xor a
84 ldh (.NR52), a ; Kill sound for this screen
85
86 ldh (.VBK), a
87 ld a, e
88 ld (vCrashVBK), a ; copy vCrashVBK across banks
89
90 ld a, #1
91 ldh (.VBK), a
92 ld hl, #vCrashDumpScreen
93 ld b, #SCRN_Y_B
94 .writeAttrRow:
95 xor a
96 ld c, #(SCRN_X_B + 1)
97 rst #0x28 ; .MemsetSmall
98 ld a, l
99 add a, #(SCRN_VX_B - SCRN_X_B - 1)
100 ld l, a
101 dec b
102 jr nz, .writeAttrRow
103 xor a
104 ldh (.VBK), a
105
106 ; Load palettes
107 ld a, #0x03
108 ldh (.BGP), a
109 ld a, #0x80
110 ldh (.BCPS), a
111 xor a
112 ld c, #.BCPD
113 ldh (c), a
114 ldh (c), a
115 dec a ; ld a, $FF
116 ldh (c), a
117 ldh (c), a
118 ldh (c), a
119 ldh (c), a
120 ldh (c), a
121 ldh (c), a
122
123 ld a, #(SCRN_VY - SCRN_Y)
124 ldh (.SCY), a
125 ld a, #(SCRN_VX - SCRN_X - 4)
126 ldh (.SCX), a
127
128 call loadfont
129
130 ; Copy the registers to the dump viewers
131 ld hl, #vDumpHL
132 ld de, #vCrashHL
133 ld c, #4
134 rst #0x30 ; .MemcpySmall
135
136 ; We're now going to draw the screen, top to bottom
137 ld hl, #vCrashDumpScreen
138
139 ; First 3 lines of text
140 ld de, #.header
141 ld b, #3
142 .writeHeaderLine:
143 ld a, #0x20 ; " "
144 ld (hl+), a
145 ld c, #19
146 rst #0x30 ; .MemcpySmall
147 ld a, #0x20 ; " "
148 ld (hl+), a
149 ld a, l
150 add a, #(SCRN_VX_B - SCRN_X_B - 1)
151 ld l, a
152 dec b
153 jr nz, .writeHeaderLine
154
155 ; Blank line
156 ld a, #0x20 ; " "
157 ld c, #(SCRN_X_B + 1)
158 rst #0x28 ; .MemsetSmall
159
160 ; AF and console model
161 ld l, #<vCrashDumpScreenRow4
162 ld c, #4
163 rst #0x30 ; .MemcpySmall
164 pop bc
165 call .printHexBC
166 ld c, #8
167 rst #0x30 ; .MemcpySmall
168 ld a, (__cpu)
169 call .printHexA
170 ld a, #0x20 ; " "
171 ld (hl+), a
172 ld (hl+), a
173 ld (hl+), a
174
175 ; BC and DE
176 ld l, #<vCrashDumpScreenRow5
177 ld c, #4
178 rst #0x30 ; .MemcpySmall
179 pop bc
180 call .printHexBC
181 ld c, #6
182 rst #0x30 ; .MemcpySmall
183 pop bc
184 call .printHexBC
185 ld a, #0x20
186 ld (hl+), a
187 ld (hl+), a
188 ld (hl+), a
189
190 ; Now, the two memory dumps
191 .writeDump:
192 ld a, l
193 add a, #(SCRN_VX_B - SCRN_X_B - 1)
194 ld l, a
195 ld c, #4
196 rst #0x30 ; .MemcpySmall
197 pop bc
198 push bc
199 call .printHexBC
200 ld de, #.viewStr
201 ld c, #7
202 rst #0x30 ; .MemcpySmall
203 pop de
204 call .printDump
205 ld de, #.spStr
206 bit #7, l
207 jr z, .writeDump
208
209 ld de, #.hwRegsStrs
210 ld l, #<vCrashDumpScreenRow14
211 ld c, #6
212 rst #0x30 ; .MemcpySmall
213 ld a, (wCrashLCDC)
214 call .printHexA
215 ld c, #4
216 rst #0x30 ; .MemcpySmall
217 ldh a, (.KEY1)
218 call .printHexA
219 ld c, #4
220 rst #0x30 ; .MemcpySmall
221 ld a, (wCrashIE)
222 call .printHexA
223 ld (hl), #0x20 ; " "
224
225 ld l, #<vCrashDumpScreenRow15
226 ld c, #7
227 rst #0x30 ; .MemcpySmall
228 .writeBank:
229 ld a, #0x20 ; " "
230 ld (hl+), a
231 ld a, (de)
232 inc de
233 ld (hl+), a
234 cp #0x20 ; " "
235 jr z, .banksDone
236 ld a, (de)
237 inc de
238 ld c, a
239 ld a, (de)
240 inc de
241 ld b, a
242 ld a, (bc)
243 call .printHexA
244 jr .writeBank
245 .banksDone:
246
247 ; Start displaying
248 ld a, #(LCDCF_ON | LCDCF_BG9C00 | LCDCF_BGON)
249 ldh (.LCDC), a
250
251 .loop:
252 ; The code never lags, and IE is equal to IEF_VBLANK
253 xor a
254 ldh (.IFL), a
255 halt
256 nop
257
258 jr .loop
259
260 .printHexBC:
261 call .printHexB
262 ld a, c
263 .printHexA:
264 ld b, a
265 .printHexB:
266 ld a, b
267 and #0xF0
268 swap a
269 add a, #0x30
270 cp #0x3a
271 jr c, 1$
272 add a, #(0x41 - 0x3a)
273 1$: ld (hl+), a
274 ld a, b
275 and #0x0F
276 add a, #0x30
277 cp #0x3a
278 jr c, 2$
279 add a, #(0x41 - 0x3a)
280 2$: ld (hl+), a
281 ret
282
283 .printDump:
284 ld b, d
285 ld c, e
286 call .printHexBC
287 ld a, #0x20 ; " "
288 ld (hl+), a
289 ld (hl+), a
290 ld a, e
291 sub #8
292 ld e, a
293 ld a, d
294 sbc #0
295 ld d, a
296 .writeDumpLine:
297 ld a, l
298 add a, #(SCRN_VX_B - SCRN_X_B - 1)
299 ld l, a
300 ld a, #0x20 ; " "
301 ld (hl+), a
302 .writeDumpWord:
303 ld a, (de)
304 inc de
305 call .printHexA
306 ld a, (de)
307 inc de
308 call .printHexA
309 ld a, #0x20 ; " "
310 ld (hl+), a
311 bit 4, l
312 jr nz, .writeDumpWord
313 ld a, l
314 and #0x7F
315 jr nz, .writeDumpLine
316 ret
317
318 loadfont:
319 xor a
320 cpl
321 ld hl, #0x9000
322 ld c, #16
323 rst #0x28 ; .MemsetSmall
324 ld hl, #(0x9000 + ' ' * 16)
325 ld c, #16
326 rst #0x28 ; .MemsetSmall
327
328 ld de, #(_font_ibm + 2 + '0') ; recode table
329 ld hl, #(0x9000 + '0' * 16) ; destination
330 push hl
331 ld c, #(16 * 3)
332 1$:
333 ld a, (de)
334 inc de
335 push de
336
337 swap a
338 ld l, a
339 and #0x0f
340 ld h, a
341 ld a, l
342 and #0xf0
343 srl h
344 rra
345 ld l, a
346 ld de, #(_font_ibm + 2 + 128)
347 add hl, de
348
349 ld d, h
350 ld e, l
351
352 ldhl sp, #2
353 ld a, (hl+)
354 ld h, (hl)
355 ld l, a
356
357 ld b, #8
358 2$:
359 ld a, (de)
360 cpl
361 inc de
362 ld (hl+), a
363 ld (hl+), a
364
365 dec b
366 jr nz, 2$
367
368 ld d, h
369 ld a, l
370 ldhl sp, #2
371 ld (hl+), a
372 ld (hl), d
373
374 pop de
375
376 dec c
377 jr nz, 1$
378
379 add sp, #2
380 ret
381
382 .header:
383 ; 0123456789ABCDEFGHI 19 chars
384 .ascii "KERNEL PANIC PLEASE"
385 .ascii "SEND A CLEAR PIC OF"
386 .ascii "THIS SCREEN TO DEVS"
387 .ascii " AF:"
388 .ascii " MODEL:"
389 .ascii " BC:"
390 .ascii " DE:"
391 .ascii " HL:"
392 .viewStr:
393 .ascii " VIEW:"
394 .spStr:
395 .ascii " SP:"
396 .hwRegsStrs:
397 .ascii " LCDC:"
398 .ascii " K1:"
399 .ascii " IE:"
400 .ascii " BANK:"
401 .ascii "R"
402 .dw __current_bank
403 .ascii "V"
404 .dw vCrashVBK
405 .ascii "W"
406 .db .SVBK, 0xff
407 .ascii " "
408
409
410 .area _DATA
411
412 wCrashA:
413 .ds 1 ; We need at least one working register, and A allows accessing memory
414 wCrashIE:
415 .ds 1
416 wCrashLCDC:
417 .ds 1
418
419
420 .area _CRASH_SCRATCH(ABS)
421
422 .org 0x9C00
423
424 ; Put the crash dump screen at the bottom-right of the 9C00 tilemap, since that tends to be unused space
425 .ds SCRN_VX_B * (SCRN_VY_B - SCRN_Y_B - 2) ; 2 rows reserved as scratch space
426
427 .ds SCRN_X_B ; Try not to overwrite the window area
428 .ds 2 * 1 ; Free stack entries (we spill into the above by 1 entry, though :/)
429 ; These are the initial values of the registers
430 ; They are popped off the stack when printed, freeing up stack space
431
432 vCrashAF:
433 .ds 2
434 vCrashBC:
435 .ds 2
436 vCrashDE:
437 .ds 2
438 vCrashHL:
439 .ds 2
440 vCrashSP:
441 .ds 2
442
443 .ds SCRN_X_B
444 vHeldKeys:
445 .ds 1 ; Keys held on previous frame
446 vUnlockCounter:
447 .ds 1 ; How many frames until dumps are "unlocked"
448 vWhichDump:
449 .ds 1
450 vDumpHL:
451 .ds 2
452 vDumpSP:
453 .ds 2
454 vCrashVBK:
455 .ds 1
456 .ds 4 ; Unused
457
458 .ds SCRN_VX_B - SCRN_X_B - 1
459 vCrashDumpScreen:
460 vCrashDumpScreenRow0 = vCrashDumpScreen + 1 * SCRN_VX_B
461 vCrashDumpScreenRow1 = vCrashDumpScreen + 2 * SCRN_VX_B
462 vCrashDumpScreenRow2 = vCrashDumpScreen + 3 * SCRN_VX_B
463 vCrashDumpScreenRow3 = vCrashDumpScreen + 4 * SCRN_VX_B
464 vCrashDumpScreenRow4 = vCrashDumpScreen + 5 * SCRN_VX_B
465 vCrashDumpScreenRow5 = vCrashDumpScreen + 6 * SCRN_VX_B
466 vCrashDumpScreenRow6 = vCrashDumpScreen + 7 * SCRN_VX_B
467 vCrashDumpScreenRow7 = vCrashDumpScreen + 8 * SCRN_VX_B
468 vCrashDumpScreenRow8 = vCrashDumpScreen + 9 * SCRN_VX_B
469 vCrashDumpScreenRow9 = vCrashDumpScreen + 10 * SCRN_VX_B
470 vCrashDumpScreenRow10 = vCrashDumpScreen + 11 * SCRN_VX_B
471 vCrashDumpScreenRow11 = vCrashDumpScreen + 12 * SCRN_VX_B
472 vCrashDumpScreenRow12 = vCrashDumpScreen + 13 * SCRN_VX_B
473 vCrashDumpScreenRow13 = vCrashDumpScreen + 14 * SCRN_VX_B
474 vCrashDumpScreenRow14 = vCrashDumpScreen + 15 * SCRN_VX_B
475 vCrashDumpScreenRow15 = vCrashDumpScreen + 16 * SCRN_VX_B
476 vCrashDumpScreenRow16 = vCrashDumpScreen + 17 * SCRN_VX_B
477 vCrashDumpScreenRow17 = vCrashDumpScreen + 18 * SCRN_VX_B
This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.