cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

crash_handler.s (8907B)


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