[SOLVED] Intercepting a crash

General Programming help in C, C++ or ASM, Compiling / Debugging, and R3000A Central Processing Unit (CPU) information
Post Reply
PBnJK
What is PSXDEV?
What is PSXDEV?
Posts: 3
Joined: Sep 11, 2023
I am a: Hobbyist Programmer
Motto: C is better than C++
Location: Brazil

[SOLVED] Intercepting a crash

Post by PBnJK » November 9th, 2023, 9:59 am

Hello, it is me again :praise

Recently, following some 3D misadventures (game's 2D now, that's how well that went,) I've been delving into the Zelda OOT source code and TCRF page and remembered that neat crash handling screen it has. It's also included in Animal Forest (N64 Animal Crossing).

Now, although I've barely just started on my little homebrew projects, I've already experienced my fair share of weird crashes, which, though NO$PSX valiantly attempts to help me solve them, mostly end up costing me a few hours to solve :oops:

This left me thinking: is there some way to implement a crash debugger ala OOT/AF on the PSX? The way I think it works on the N64 is that an interrupt is triggered whenever the game encounters a fatal exception, which the game then catches, figures out what was wrong1, and then shows a screen with some snapshots of the game's memory, error message2 and so on.

My question is not how to implement this whole system; I would try to figure that out on my own. My question is, is there any way to catch/intercept/detect a crash before the main loop is interrupted? A callback of some sorts, a function, heck; a memory adress to poke and peek at would be great!

Thanks in advance for any answers, and sorry in advance if the question is stupid...



1 This is the part I'm most interested in. The crash screen seems to know some basic info about how the crash came to happen. There are some screenshots that, for example, show that the game crashed due to a "floating point exception", which would be some mighty useful information to have while debugging...

2
HungUp on Thread 4
RCP is HUNG UP!!
Oh! MY GOD!!
Last edited by PBnJK on November 10th, 2023, 4:20 am, edited 1 time in total.

User avatar
nocash
Verified
PSX Aficionado
PSX Aficionado
Posts: 614
Joined: Nov 12, 2012
Contact:

Post by nocash » November 9th, 2023, 8:13 pm

Crashes are routed to A(40h) SystemErrorUnresolvedException, you can hook the A(40h) function vector at address 300h (=200h+40h*4).
At that point, many CPU register are smashed, but their original values should be stored on stack, you can restore them as done in the B(17h) function, that is, like this:

Code: Select all

;------------------
ret_from_exception: ;B(17h) ReturnFromException
 mov   r1,[108h]       ;r1=[tot_pcb_addr]
 nop
 mov   r1,[r1]         ;r1=[[tot_pcb_addr]]
 nop
 mov   r2,[r1+8+84h] ;hi       ;.
 mov   r3,[r1+8+88h] ;lo       ;
 mov   r4,[r1+8+8Ch] ;sr       ; pop hi,lo,sr
 mov   hi,r2                   ;
 mov   lo,r3                   ;
 mov   cop0r12,r4              ;/
 mov   r2,[r1+8+08h]           ;.
 mov   r3,[r1+8+0Ch]           ;
 mov   r4,[r1+8+10h]           ;
 mov   r5,[r1+8+14h]           ;
 mov   r6,[r1+8+18h]           ;
 mov   r7,[r1+8+1Ch]           ;
 mov   r8,[r1+8+20h]           ;
 mov   r9,[r1+8+24h]           ;
 mov   r10,[r1+8+28h]          ;
 mov   r11,[r1+8+2Ch]          ;
 mov   r12,[r1+8+30h]          ; pop r2..r25
 mov   r13,[r1+8+34h]          ;
 mov   r14,[r1+8+38h]          ;
 mov   r15,[r1+8+3Ch]          ;
 mov   r16,[r1+8+40h]          ;
 mov   r17,[r1+8+44h]          ;
 mov   r18,[r1+8+48h]          ;
 mov   r19,[r1+8+4Ch]          ;
 mov   r20,[r1+8+50h]          ;
 mov   r21,[r1+8+54h]          ;
 mov   r22,[r1+8+58h]          ;
 mov   r23,[r1+8+5Ch]          ;
 mov   r24,[r1+8+60h]          ;
 mov   r25,[r1+8+64h]          ;/
;n/a   k0, [r1+8+68h] ;aka r26 ;-do NOT pop r26 (aka k0)
 mov   k1, [r1+8+6Ch] ;aka r27 ;.
 mov   r28,[r1+8+70h]          ;
 mov   sp, [r1+8+74h] ;aka r29 ; pop r27..r31
 mov   r30,[r1+8+78h]          ;
 mov   ra, [r1+8+7Ch] ;aka r31 ;/
 mov   k0, [r1+8+80h] ;aka r26 ;-pop epc to k0
 mov   r1, [r1+8+04h]          ;-pop r1
 reti  ;aka "jmp k0, rfe"      ;-RFE and JMP K0/EPC
An error screen might be quite useful if a crash occurs on real hardware. Although it would be probably more limited than what you can see in debuggers. As for no$psx, there are two ways to see crashes and errors:

1) Enable warnings (press Ctrl+E in the debugger), that way you should see most errors immediately when they occur, and before running into the SystemError function.

2) If that didn't work (and if the CPU has entered the SystemError function and then hangs in the endless loop):
Type "Ctrl+G, epc" in the debugger's code window to go to the instruction that had triggered the exception.

In the 2nd case, many CPU registers are smashed. Now that I am thinking about it, to ease debugging, I should change my kernel clone to restore their original values before entering the endless loop.

PBnJK
What is PSXDEV?
What is PSXDEV?
Posts: 3
Joined: Sep 11, 2023
I am a: Hobbyist Programmer
Motto: C is better than C++
Location: Brazil

Post by PBnJK » November 10th, 2023, 4:19 am

nocash wrote: Crashes are routed to A(40h) SystemErrorUnresolvedException, you can hook the A(40h) function vector at address 300h (=200h+40h*4).
Alright! Thank you very much!!

P.S Thanks for the emulator, by the way. I was a bit unintentionally mean to it in my post, but its been invaluable these past few weeks (especially for a hardware-less guy such as my self! :D)

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests