Jump to content
IGNORED

JLP and Logging Exceptions (and jzIntv?)


Recommended Posts

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?

  • Like 1
Link to comment
Share on other sites

In jzIntv, you already sort-of have this: If you enable jzIntv's debugger, turn on 'h' for history tracking. It will track the last 65,536 instructions in a circular buffer, along with the values of all the registers, cycle-by-cycle. The 'd' command will then dump this history to a file named 'dump.hst'. The '!' command will show you the last N instructions leading to the current point.

 

For in-the-field crashes, it gets a bit trickier. It may be possible to save JLP's internal RAM to JLP's own save slots. But, getting the information from inside the unit would be trickier. It really depends on the nature of the crash: If the CPU hit a HLT instruction, the only way out is a RESET, and that will lose state. If the game hit an infinite loop (as was the case with Carol, IIRC), JLP wouldn't know anything is wrong.

Link to comment
Share on other sites

 

I am making a wild guess that JLP boards have games soldered on, but would it be possible to have one socketed as part of a production run?

I recognize that this is pure fantasy and affects a statistically near-0% of the Intv community. :)

It might be useful if a bug was discovered in the game, the socketed one could be used and the chip popped out and the contents read on a real computer?

 

 

(snip)

 

For in-the-field crashes, it gets a bit trickier. It may be possible to save JLP's internal RAM to JLP's own save slots. But, getting the information from inside the unit would be trickier. It really depends on the nature of the crash: If the CPU hit a HLT instruction, the only way out is a RESET, and that will lose state. If the game hit an infinite loop (as was the case with Carol, IIRC), JLP wouldn't know anything is wrong.

Link to comment
Share on other sites

I am making a wild guess that JLP boards have games soldered on, but would it be possible to have one socketed as part of a production run?

I recognize that this is pure fantasy and affects a statistically near-0% of the Intv community. :)

It might be useful if a bug was discovered in the game, the socketed one could be used and the chip popped out and the contents read on a real computer?

All the current cart designs on offer can be reprogrammed without removing any chips.

Link to comment
Share on other sites

The JLP board is programmed after it's assembled. There's no socketed variant or anything.

 

There is a TTL-level serial port pinned out on the JLP04 boards, so you can wire up a USB-to-serial cable to it pretty trivially to dump data out of one. FTDI makes some suitable cables. Solder 4 wires to the holes and off you go. They're pricey, but easy to work with. You wouldn't want to do this in volume, naturally. For volume applications, you'd make a small daughter board that could be mass produced to reduce the unit cost.

 

To get the data out, you just need a small bit of code in your program to read data the captured data out over serial. It's not much code, and it's pretty simple to write. I have reference code and even some demo programs that make use of the serial port, if there ever is a need for it.

  • Like 1
Link to comment
Share on other sites

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:

post-27318-0-44490900-1468407942_thumb.gifpost-27318-0-81925600-1468408006_thumb.gif

 

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. :)

 

-dZ.

Edited by DZ-Jay
  • Like 4
Link to comment
Share on other sites

  • 9 months later...

I am thinking of adding a "state report" keypad sequence to my IntyBASIC game to report variables and GRAM contents. Your CC screen really looks good and informative. My "game make" program selects .bas files and concatenates them in memory-safe order, so I now thinking of adding that as a separate .bas that I can/not add as needed.

Link to comment
Share on other sites

I am thinking of adding a "state report" keypad sequence to my IntyBASIC game to report variables and GRAM contents. Your CC screen really looks good and informative. My "game make" program selects .bas files and concatenates them in memory-safe order, so I now thinking of adding that as a separate .bas that I can/not add as needed.

 

:cool: I wonder if you really need a "state report" screen. Why not use the debugger to inspect variables and GRAM during development. Of course, that would be while you test in the emulator.

 

Remember one critical aspect: any debug code you add for debugging is code that has a relatively high chance to get in the way of your game. What's more, any debug code you remove for production will cause a change in the flow of your program, which may result in a high chance of getting in the way of your game.

 

-dZ.

Edited by DZ-Jay
Link to comment
Share on other sites

I thcan no I need to take a harder look at what the jzIntv debugger provides. I initially thought it would not show enough context for my game, and that variables would be renamed dynamically by the compiler and therefore hard to decipher at runtime. I'll look again.

 

I definitely get what you mean by potential bugs in debug bits. :)

Link to comment
Share on other sites

I thcan no I need to take a harder look at what the jzIntv debugger provides. I initially thought it would not show enough context for my game, and that variables would be renamed dynamically by the compiler and therefore hard to decipher at runtime. I'll look again.

 

I definitely get what you mean by potential bugs in debug bits. :)

 

If you are using the IntyBASIC SDK, it includes options in the command-line for building, to generate symbol tables and translation tables between IntyBASIC variables and Assembly symbols. The debugger command-line also includes the options to invoke these.

 

Therefore, using the SDK, you're already set. Otherwise, you'll have to read the jzIntv and IntyBASIC documents to figure out how to do this -- or just ask nicely and we'll help. :)

 

The jzIntv debugger is the quintessential developer tool. It may be a little "hard-core" and low-level to IntyBASIC programmers because of its omniscient view into CPU and memory, but it just takes a bit of practice to get used to it.

 

Some of the features it supports are:

  • Breakpoints - marks a spot in the code where the debugger will interrupt program flow when the CPU reaches it. This allows you to inspect the execution of the CPU as well as the rest of the environment.
  • Watches - keeps track of specified memory locations (i.e., variables) and reports whenever their values are changed, while the program is executing. It includes the old value, the new value, and the instruction and location where it happened.
  • CPU Stepping - once interrupted, you can step through your program flow one instruction at a time, or jump in any number of increments.
  • Peek - allows you to view (peek) any memory location and inspect its current value.
  • Poke - allows you to write (poke) to any memory location overwriting its current value.
  • Source-Level Debugging - by default, the debugger disassembles the ROM binary during execution, showing you each op-code as it is being processed. However, utilizing the symbol/translation table allows you to view the current execution point in your IntyBASIC source code itself. The debugger still shows you the underlying assembly codes for each statement, but you can see in which IntyBASIC line you're in.
  • ... And much, much more!
  • Act now! Operators are standing by!

Importing the symbol table into the debugger allows you to use IntyBASIC variable and procedure names when using any of the debugger commands, thus abstracting the underlying memory locations.

 

-dZ.

Edited by DZ-Jay
  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...