git.y1.nz

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.