'De Buggers Bit3 Dust
by DAVE and SANDY SMALL
As you may recall from our last article, we are discussing the development of a commercial game product and the techniques we used to get the job done very quickly. You can apply these same techniques to save yourself time (and thus money) in your projects.
Last month we explained why we chose MAC/65 over the other assemblers available for the ATARI. Now that we have picked an assembler, we can write the program and generate machine language. Ah, but we have to debug machine language. Remember, debugging time = 1.5 x programming time. If you are doing development work, debugging costs you a great deal of time. We found a way to considerably cut the time involved.
The problem we solved in a unique way was that of debugging the assembly language program. It was quite long (25K), and contained a number of different displays utilizing scrolling, PM graphics, and display lists changing dynamically. The problem is, how do you debug such code!
There are a number of popular debuggers on the market. There's Dunion's DDT, a powerful debugger for the Atari Macro Assembler. There's Dave Young's OMNIMON, a ROM-based monitor utilizing a patched Operating System board. There's MAE, BUG/65, and so forth. Last, and least, there's the crude and annoying debugger in the Atari Assembler/Editor cartridge.
I'll bet you can guess from my description which one we used. Yup, the ASM/ ED cartridge. "Why?", you ask. I'll answer that in a minute, but first, some background information.
There is a problem common to all of the debuggers currently on the market: they use the TV screen for display.
This is not a trivial consideration to a game writer. You program ANTIC to create a given visual display. This display is then shown on the TV. But while that display is there, you cannot get any information about memory, the 6502, ANTIC, collision status, or anything else, because the TV screen is already being used. This makes debugging of dynamic displays, where things are going on during this display process, nearly impossible; you need to be able to talk to the debugger to find out what's going on, but the debugger can't output anything to you.
Presently, there are two rather kludgey solutions. Both involve giving you a way to get information from the debugger without conflicting with the TV display you are generating.
The first is to redirect console(E:) output to the printer, via C364(A6,EE (from the ASM/ED debugger). This makes anything that normally would be printed out on the screen get typed out on the printer instead. Hence you can get output from your debugger, at the expense of a considerable quantity of paper. For instance, if you have your display up on-screen, and there are too many scan lines being generated, you can dump the display list off to the printer to find out what's going on, and why too many lines are on-screen.
This solution has drawbacks, however. It assumes you have a respectable supply of paper and are willing to put up with a (relatively) slow printer output as compared to a CRT output. You can't see what you're typing on the keyboard, so if you make a mistake, you won't find out about it and can't correct it. And just to make things interesting, in order for the printer to even function, both CIO and SIO must be initialized and running, which means a number of low memory locations need to be set and not altered by your code. One quick example would be the sound registers, used by SIO.
The other solution, utilized by many debuggers, is to "flip" out the current display, by rewriting ANTIC's display list shadow registers, onto a "debug" display, where all sorts of registers, breakpoints, and memory locations are shown. When you are done with the debug display, you "flip" back to the original display. This too has its problems, which is why we didn't go this route either. The main drawback is that you cannot see the debugging display and the TV display you are working on at the same time.
A case in point: Let's say we are attempting to debug a display where a player can collide with a terrain playfield. We would like to debug it by checking the collision registers, by hand, when the player is being plotted on top of the terrain it should collide with. Well, with the "page flip" debugger displays, you can't do that, because the instant the text debugger window pops up (probably with your players still running), your collision registers take on amazingly random values.
Or perhaps you are debugging a display list interrupt? A DLI does not even happen unless your original display is on-screen. We are using at least one and as many as five DLI's on every screen.
The problem remains that you just can't get debugging information out of the machine and have your TV display, to be debugged, up there also. There's only one CRT information path out of the ATARI, and that's ANTIC.
Until, of course, Bit3 came out with their 80-column card. The Bit3 board plugs into the rear RAM slot of the ATART 800 and has a complete 80-column video circuit inside. It generates a signal for a monochrome monitor which you attach to it. (Incidentally, color monitors specifically made for high resolution work will not suffce. I can remember one review of the Rit3 board which was very negative because the reviewer hooked it up to a color monitor, and the Bit3, of course, could not generate a legible image.) You will need a 32K card to make up for the lost 16K RAM slot; Mosaic has a particularly convenient adaptor which takes the RAM chips from two Atari 16K memory boards and reuses them in one Mosaic board, for 32K.
At first we used the 80-columns for word processing, until we moved to CP/M and Wordstar. The Bit3 board remained retired for a while, until this debugging came up and we realized the power it could offer in debugging. (Certainly this application has never been advertised.) What is Bit3's special potential? The board provides an alternate path for debugging output.
This means you can have your TV playing whatever ANTIC and GTIA are up to in terms of the game screen, and have your Bit3 & 80-column monitor displaying debugging information at the same time.
This is a tremendous debugging tool. It is the most powerful debugging tool I have seen for the ATARI with the exception of a hardware logic analyzer. For instance: If I want to watch collision registers, I can wait until the game reaches the collision point, stop the game (via [BREAK]), and using the Bit3 board as output, display the registers. The TV display at this point is static, busily displaying players and playfield, and most importantly, having GTIA set collision registers. The ANTIC display is unaffected by the debugger, which is working with the Bit3 board, not the TV display.
Our game screens had terrain maps of many colors. Making all the colors match for a nice overall display takes a great deal of time, normally. However, with the Bit3 & debugger, we could change the color register values immediately, and see the results on the TV. We could also change colors inside of DLI handlers (as we segmented the screen vertically many times) directly, to get the colors right. This saved us many reassemblies with the large amount of time they eat up.
I will skip the descriptions of many, many other situations where the power of two displays, one watching the 6502 and memory, and the other being the ANTIC-generated TV display, made the debugging go much faster. I would estimate this technique cut two weeks of frustrating debugging time out of our project, by greatly easing the debugging task.
And, this brings us to why we used the very crude ASM/ED debugger: it works with the Bit3 board. DDT does not. OMNIMON does not. It takes a debugger that uses CIO and E: for output, which Bit3 redirects to its 80-column circuitry, to work properly. The cartridge was the only debugger we could find that did so.
To be sure, we are not masochists. We would not use the ASM/ED cartridge for debugging if we had any choice. Only because there was no alternative did we reluctantly dig the cartridge out of our junk box. By doing so, we subjected ourselves to a number of bad features. The cartridge:
- Uses lots of Page Zero locations, so you can not use those locations without having the cartridge trip over them. To make things worse, the locations that are used are not documented properly in the ASM/ED manual.
- Does not trace through a CPY #nn instruction. This is extremely annoying, as indexing is a key to nearly any 6502 program. This bug can be gotten around, however; do something like this:
EIGHTEEN .BYTE 18
- Resets vertical blank vectors (without telling you) on any [BREAK] key press or (00) BRK instruction, so you can not debug them properly; we had to use DLI's to get around this.
- Is not relocatable and takes up 8K In high memory.
There are a few things you should know about when using this combination. First, the Bit3 board, to quote Elmer Fudd, is "Tewwiibly, tewwibly sensitive" about a number of things. To begin with, you must not alter DINDEX or the cursor display locations, ROWCRS/COLCRS, as Bit3 uses those to figure out current Graphics Mode (0-11) and cursor location. If the Bit3 board thinks that you are no longer in Graphics 0 text mode (DINDEX = 0), you're out of luck; it shuts itself off. And if you alter the cursor registers (example, if you draw a line on-screen using the OS draw routines) then the Bit3 will get confused as to where it should output data. In my case, I was using a GR. 8 display and drawing lines, which set DINDEX to 8 and threw the cursor values down to around :100; the Bit3 board went wild.
Next, the Bit3 board uses the lowest 32 bytes of the stack area as temporary memory. The idea here is that the lower part of the stack never gets used (unless a program is not returning from subroutines properly and is about to crash anyway), thus, this area is available as free storage. This use of Page One is both good and bad. The "good" is that Page Six, Page Four and other popular places to stash things are used, so you don't have conflicts. (Ever noticed how every other utility on the market seems to use Page Six, making them all mutually exclusive?)
The "bad" is that MAC/65, the extremely powerful assembler we were using, ALSO uses the lower part of the stack when assembling, and will crash if used with an 80-column board. So for some time we had to switch out of 80-column mode to do an assembly. Finally, however, OSS gave us a fix; all references to the lower stack area were moved up $20 bytes, into the not-so-low stack area. (Oh, well). All then worked fine. (Buyers of OSS products should note that the support for these products is among the best I have seen in the Atari market).
Finally, in the "Twilight Zone" series of weird debugger problems, unless an initial "JSR" is made to whatever code you are trying to debug, to move the stack pointer off the very top of the stack, you will spectacularly crash on any [BREAK] key press or 00 (BRK) instruction. I don't know why; I have my speculations about the 6502 using locations $100 and $1FF for storage if it is at the very top of the stack, but don't know. (With the Bit3 board constantly resetting at $100, this seems like a logical reason for this to be the problem.) The easy fix is just to make a JSR the first thing in your program.
Okay, so you have decided to get a Bit3 board. Other advantages are now yours. You can edit your code in 80 columns, which is a whole new world. Why this is important is: 1) you get twice as much information displayed on-screen (1920 chars instead of 960). If you are heavily into comments, as I am, then you will appreciate this greatly; it makes reading and editing go much faster. Just as an example, in 40-col mode, provided you use a number of comments, you will have about 12 lines displayed per screen, because of wraparounds. In 80-col mode, you get 24, plus all the comments are to the right of what they are commenting, versus underneath. Readability and comprehension both increase greatly; if you spend ten less seconds on each display understanning what's go- ing on, you will save hours in the long run. It sure helped us.
MAC/65's powerful editor is compatible with the Bit3 board in editing mode, and with the above fix, in assembly mode.
So, those are our debugging tools. We strongly recommend them to any other programmers who want to get their display-oriented programs debugged quickly. Next article we will consider your alternatives in disk drives.
Dave and Sandy Small are professional programmers working with ATARI computers and ATARI-compatible peripherals ann software to produce commercial software to run on ATARls. They begin here to share some discoveries, insights, experiences and secrets of interest to others at or near their level of practice. Each article is intended to stand alone, but articles are seqential and full value may depend on reading the whole series. Questions or suggestions can be addressed to them care of- ANTIC. Responsive answers are not guaranteed, but may be made individually by mail (if self-addressed stamped envelope is provided) or publicly in this department. -ANTIC ED