I was wondering if perhaps the freezing might be caused by a DMA or GIF stall caused by interrupting a transfer. Perhaps monitoring their respective status registers might help since it should be possible to reset/restart the GIF or restart/continue a dma transfer.
Here's some documentation I wrote on the DX,DY,MAGH,MAGV,DW,DH attributes of the display register when I was playing around with gsKit.
DX seems to be a waiting period to skip reading until the framebuffer.
DY might be (DY-1) * DW for waiting, so the whole formula might be:
((DY-1)*DW)+DX to get the correct waiting period when reading of the framebuffer occurs.
MAGH seems to focus down the reading period to a specific number of reads.
E.g. 2560/(MAGH + 1). 2560/(9+1) = 256, so a raster line break occurs after reading 256 times.
DW seem to be some sort of timing mechanism per line, perhaps 2560 total reads per cycle minus one.
E.g. Total time to read a line after reading has started: DX + (2560/(MAGH + 1)) + (Reading time used for other purposes).
DH seems to be the number of rasterization lines needed minus one.
The main things to focus on are the width parameters, since they can change depending on the video read cycle, which changes depending on the various other things in SMODE1/SYNCV/SYNCH1/SYNCH2 and etc.
Also I say "reading" and "reads" but I'm not exactly sure what I mean. I think it's a sync pulse that lasts 2560-1 units (whatever a unit is) on NTSC/PAL. I read a book on google books about it which mentioned a variety of things that might also be related to the other registers, such as front porch, back porch, front porch end, back porch end, and sync pulses.
Unfortunately I can't find the page again, seems my viewing limit is used up, but it's called "How Video Works". I did find this book on scribd which has a nice graph within the first few pages.
I haven't read all the pages in this thread, so I might have reposted some known information...