Kodewerx
https://www.kodewerx.org/forum/

N64 Exception Handling
https://www.kodewerx.org/forum/viewtopic.php?f=11&t=7352
Page 1 of 1

Author:  HyperHacker [ Sun Jul 11, 2010 1:29 am ]
Post subject:  N64 Exception Handling

So I put together this nice complex hack for Mario Kart and it works great in Mupen64 but on the real machine it locks right up. The game draws a little box in the corner any time it crashes, just like Zelda does with its debug screen, but I see no trace of text that might actually appear on such a screen.

Any advice on how I might find a "cheat code" that displays the exception information (like Zelda had) or somehow get the exception address out so I can look at it? 80000180 is supposed to be an exception handler, but it's also an interrupt handler, so just hooking there doesn't help a lot. Where would I go from there to see if an actual exception occurred or just an interrupt?

Author:  Parasyte [ Sun Jul 11, 2010 11:30 am ]
Post subject:  Re: N64 Exception Handling

You have to hook the exception vector, then filter the exceptions you want to handle; either handle it (do something fun, like printing register contents!) or pass it -> to the original exception handler. Everything you need to know about exceptions on MIPS R4300i is available in the R4300i Datasheet, specifically the section titled "Exception Management" which starts on page 18.

Author:  HyperHacker [ Sun Jul 11, 2010 10:49 pm ]
Post subject:  Re: N64 Exception Handling

Thanks. I looked at the handler (I guess both interrupts and exceptions go through the same mechanism?) and tracked down Mario Kart's exception display code: L, Up, Left, Down, Right, R, L, B, A. Press that when you see a white square in the upper left corner (i.e. the game has crashed) and you'll get some info on the screen.
First line is what I'm guessing is a thread ID (always seems to be 5), then the PC at which the exception occurred, then the exception code (as listed in the R4300i manual). Second line is RA, third I don't know (was just zeros for me).
The reset button still appears to work. (For me, it only blanks out the screen and doesn't actually reset the game, even if it's not crashed. Some issue with the CD64 maybe.)
This doesn't work on Mupen64; the code runs, but I guess it just never redraws the screen if the game never finishes its handler.

Using 810DC6FE FFFF shortens the code to simply "press L".

Image
Notice the white square in the corner (looks like the bottom left corner of the "A") that indicates a game crash.

Author:  James0x57 [ Mon Jul 12, 2010 6:06 am ]
Post subject:  Re: N64 Exception Handling

Feakin sweet! Nice job.

Author:  Parasyte [ Mon Jul 12, 2010 10:44 am ]
Post subject:  Re: N64 Exception Handling

I don't see the indicator in your image, but I know exactly what you are talking about. A white square with a red border, as I recall.

And yes, exceptions and interrupts are technically the "same thing". So they can be handled in the same way ... CPU stops in its tracks and jumps to the exception vector. Exception vector either handles it (for example, in the case of a TLB miss, the handler can load the missing page, and then exit; continuing the game) or dies by stalling in an infinite loop. That infinite loop is usually where you find the exception display.

EDIT: I just added some official MIPS documentation to the EnHacklopedia Documents page:
Volume 3 contains the information about interrupts and exceptions. That should keep you busy for a while.

Author:  HyperHacker [ Mon Jul 12, 2010 4:01 pm ]
Post subject:  Re: N64 Exception Handling

Yes, it's very hard to see in this image because of the blur. Near impossible if you don't already know what it looks like because it just looks like part of the title logo.

Now, this is very strange. Sometimes the hack works but often I just get exception code 0A at 80400280, which is "reserved instruction exception". How the heck a reserved instruction is ending up in my code is a mystery, especially since the CD64 I use to run it lets me poke at the "ROM" and (if it's still intact after a power-cycle) N64 RAM, and it all looks just fine there.

Author:  Parasyte [ Mon Jul 12, 2010 5:43 pm ]
Post subject:  Re: N64 Exception Handling

Probably the cache giving you trouble. You flush data cache and invalidate instruction cache after writing to cached memory at 0x80000000. Just because you write to memory doesn't mean the CPU will start executing your instructions.

When you write to cached memory, you're just placing the data into the data cache; it hasn't actually been committed to memory at that point. When the data cache is flushed, then it's physically getting stored into memory. There's also an instruction cache, which is totally separate. When the instruction cache is "valid" the CPU will simply execute the instructions already in the cache. And that means, none of your hack gets executed. When the instruction cache is invalidated, that will cause the next instruction(s) to be pulled from memory into the cache.

That's why the order of cache operations is important: flush data cache first, then invalidate instruction cache. Alternatively, write to the uncached memory at 0xA0000000, then invalidate the instruction cache.

Author:  HyperHacker [ Mon Jul 12, 2010 8:42 pm ]
Post subject:  Re: N64 Exception Handling

Well the game never normally uses that region at all, so I'm not sure why anything would be cached there, but it's worth trying. How do you flush/invalidate cache on an N64? I've never had to deal with it before.

Author:  Parasyte [ Tue Jul 13, 2010 12:06 pm ]
Post subject:  Re: N64 Exception Handling

I believe one of the CP0 registers is used to control the cache.

Author:  HyperHacker [ Tue Jul 13, 2010 4:09 pm ]
Post subject:  Re: N64 Exception Handling

I don't see any that look cache-related. There's a CACHE opcode, but I can't find any documentation of how to work it.

I don't suppose just copying my routine to A0xxxxxx and jumping to that address would work? (It's copied from ROM immediately before first execution, so this does seem like the likely culprit.)

Author:  Parasyte [ Tue Jul 13, 2010 4:55 pm ]
Post subject:  Re: N64 Exception Handling

Using uncached memory would avoid any caching problems altogether, but will be slower if it needs to do any heavy lifting. The CACHE opcode is just to inform the CPU that following memory region(s) will be used soon, so that it can pre-cache them. Volume 2 has information on it.

It looks like Coprocessor 0 Config 1 register is for setting up the instruction and data caches, but I don't see anything specifically for committing or invalidating the cache. Volume 3 has some information on the bit fields of this register, but I don't think it will be much use.

Author:  HyperHacker [ Tue Jul 13, 2010 7:14 pm ]
Post subject:  Re: N64 Exception Handling

Yep, that seems to be working. I'll need to worry about cache later, but right now speed isn't important.

Page 1 of 1 All times are UTC - 8 hours [ DST ]
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/