I am re-listening to Intellivisionaries Episode 4, featuring Christmas Carol. James was talking about the bug he experienced at CGE.
It got me thinking "what if there is a production bug in the next thing I make, how can I get some information about it?" So...
Would it be possible for a running game to somehow catch a crash/Exception and write the ROM/RAM/STIC contents to a JLP "save slot"? I was thinking that if all of that was collected into a file that could be read later, it would be A Good Thing .
I don't know if that means running the game within a kind of "container" or if there is some kind of hook that can be added to in the as1600 build process, or what.
I think a JLP board would have enough storage to hold the largest Inty games several times over, definitely enough to store the entire state of a crashed environment. If the crash happens in emulation, the file could be parsed by some tooling, if it happens on a cart, I'm not sure how to physically get the data out...
What do you think?
One thing to consider is that, any "debug" or "error handler" code you add to your program may take away from precious cycles (and storage space) needed to run the actual game. During Christmas Carol's development, the way I handled this was by adding a "DEBUG" assembler symbol that conditionally assembled parts of the code, changing the program flow into "error traps."
What this did was that, on certain conditions I wanted to identify, the game branched into a special error handler that captured all register values and an error code, displayed it on the screen, and halted the CPU.
In game, it would like like this:
The error handler was an entire library infrastructure that decoded the error codes from a table, captured all register values and displayed the information on the screen, and all I had to do was insert a macro call with a code wherever I wanted to trap an error.
Note that this required me to build my code in a way that avoided the dependency and testing of these conditions, so that I could just re-build the program without any debug code for production, once I fixed all identified bugs.
For the two examples illustrated above, this was a matter of adding the error trap at points that SHOULD NEVER EVER HAPPEN EVAH! Like overflowing the timer queue or an auto-pilot script that didn't return to its original caller. The intention was to identify all situations that may cause these conditions and eradicate them, at which point the error trap can be removed.
What I didn't want to have, under any circumstance, was any "defensive" code that impacted negatively on the performance of the game. Indeed, you don't want that there since, as opposed to a business application, there is no acceptable "failure" state of a game: you can't just say "an error occur, please contact support or try again later." The game program should be a self-contained and closed world, where all conditions and states are known and accounted for, and any necessary recovery procedures are built into its normal flow.
A queue overflow, for instance, is something that should NEVER happen. If the game has any possibility of creating more tasks than the queue can handle -- and this condition can occur -- then the game is broken. Full stop. You don't want to test around it and display an error, you want to identify those conditions and eradicate, mitigate, ignore, or otherwise handle them gracefully and recover.
This is why I stress the point of conditional assembly of "debug code" rather than building it into the production cartridge. Halting and displaying an error is a very useful tool to the programmer. However, if a player got an error message, we failed. I rather we as a community put more energy in coming up with better testing mechanisms and methods during development.
Of course, that's the theory of it. In practice, I'm a bit ashamed to say that there were many issues I didn't catch during testing. Part of it was the eagerness to complete the game quickly (after 18 months of development and 6 months of beta testing), and part of it was sloppy testing on my part. I used the mechanism described above for highly critical situations, but not in many others where I assumed proper function. The debug feature I built did help me catch a heckova lotta bugs, though.
Edited by DZ-Jay, Wed Jul 13, 2016 5:28 AM.