I've been contemplating a lot of things, getting ready to do more serious stuff for the NES, (lower level 'driver' kind of things) and I was wondering if anyone codes runtime error messages into their games. Something like:
Code:
( ...some code..)
#ifdef _DEBUG_
cpx #MAX_VALUE
bcc continue
pha
lda #ERROR_CODE_X_OUT_OF_RANGE
jsr display_message_halt ;clears screen and displays message indexed by reg A, maybe dumps all registers
#end
continue:
(..more code..)
I know the debugging tools are pretty good, but something like this might be helpful too.
The closest I have is this macro:
Code:
.macro trap;{
traplabel\@
jmp traplabel\@
.endm;}
If I put trap somewhere in my code, it will be stuck in an endless loop. I use it to find where problems are occurring, and occasionally to look at what's in the registers at a particular point since they obviously won't change while this is running.
Edit: Well... until the NMI hits
There should be no runtime errors in games at all. For debugging purposes, this has a problem - you would need to have full font in the CHR ROM, which is not always possible. So I think it is better to either just put an error code into a certain RAM address with filling whole screen with a color, or use an emulator to display actual messages (i.e. write an error message into a special register that'll be redirected to the PC console).
Good points. I have seen the halt trick before somewhere, I guess it is not too hard to trace that. If you are always going to have characters in CHR this could work, and even though it is extra coding, sometimes I find stepping code and checking regs a chore.
I think (assuming you have a valid character set) this might help if you have some code from weeks before that you felt was solid suddenly not working right with no reason to check it. I guess an endless loop would still do the job there too.. Thanks for the feedback..
EDIT:Trivial to turn off NMI in your macro..
Following Shiru's input, this isn't a bad idea if used with a LUA script to print the info. Then you don't need any characters in CHR.
I once used an FCEUX LUA script that paused the emulator whenever my character was traveling faster than 8 pixels per frame (which is as fast as the game can scroll), but because of how LUA works it only stopped on the beginning of the next frame rather than directly when it occurred. I had to use it in conjunction with input movies to know which frame to start my breakpoint that detected writes to that variable. Otherwise, the game would have been unplayable breaking X times a frame while I try to find the rare case where the max speed check wasn't working.
It would have been a bit of a pain to place a check at each place that variable had its value updated, but probably no worse than what I ended up doing. I also keep a few debug defines around now that I think about it. One that doesn't run the sprite logic and rigs scrolling to the buttons so I can debug scrolling updates, and various ones that enable cycle counting emulator register writes for various parts of the program. I guess I've just never thought about the sort of debugging you're suggesting. Not a bad idea, though.
And yeah, true about the NMI. I just honestly hadn't thought about it at all until I reread the post. "Oh, wait. The registers CAN be changed in that loop!"
Shiru wrote:
So I think it is better to either just put an error code into a certain RAM address
For Thwaite, I just had the engine put various condition codes in an otherwise unused part of the status bar. (I wonder if I left the "C0DE" for that in 0.03.) The emulators for Linux that run anywhere near full speed on my laptop don't have debugging, and I hadn't yet thought about trying to run FCEUX for Windows in Wine.
I like the idea of using emulator scripts. Or I like Shiru was saying - a special register for error codes - I suppose this would require an open source emulator and knowledge of how to create this feature.
Actually
there is an emulator with many useful debug features including (similar) to this one.
I didn't look that over in detail, and while that looks very powerful, it appears to depend entirely on CC65 based software. Unless I am missing something, it doesn't have generic special registers for writing error codes, does it?
It does it in a more comfortable way - you just put this code:
Code:
sta $4040
jmp .skip
db "error message text is here",0
.skip
The emulator intercepts the write into a non-existing register $4040 and puts a null terminated string from PC+3 into output console. So you can make a simple macro instead of a loop that would read string and write it byte by byte. It is not related to CC65, it is a debug feature of the emulator.
Very nice! I'll give that a try. Thanks for explaining.
Shiru wrote:
It does it in a more comfortable way - you just put this code:
Code:
sta $4040
jmp .skip
db "error message text is here",0
.skip
The emulator intercepts the write into a non-existing register $4040 and puts a null terminated string from PC+3 into output console. So you can make a simple macro instead of a loop that would read string and write it byte by byte. It is not related to CC65, it is a debug feature of the emulator.
Some mappers require some form of usage around $4020-$40FF, Like my upcoming mapper that may first be a powerpak mapper...
Same with FDS Images, The RAM take up $4020-$40FF for extra mapper regs.
When you will be adding support for your mapper in this exact emulator, you'll be able to change the $4040 to $4100 or something easily, I think.
Or, if you have access to number tiles, you could simply, say, put some sprites in the upper-left corner with an error code number if an error ever occurs.