Originally appeared at the D-Bug forum

Preliminaries


Even when starting Bugaboo there is some sort of flexibility! Well, not built in really, but using an external program provided in the Turbo Assembler package (L_XXXXXX.PRG), you can load Bugaboo to any possible address from start of program area up to the Physical screen. This is very handy especially when you have lots of memory because you can load it high enough so it won't interfere with a code you're trying to trace through and it has to load at a specific address.

Bugaboo is a very special debugger in my opinion, as you can use it using shortcut keys AND/OR CLI commands. When you load it you can see the top 2 lines containing 20 useful functions. These can be invoked using F-keys (top line) and Shift-F-Keys (second line). Let me cover briefly the most important of those functions.

  • Trace (F1): Well, it traces thru a single command. Enters bsr/jsr subroutines too.
  • Do PC (F2): Executes the code until the next command relative to the current is reached. So you can pass a dbra loop without having to trace each step. Useful!
  • Tracrts (F3): Traces until an RTS instruction is reached. So you can quickly pass by a subroutine. CAUTION! You should use this BEFORE the stack is tampered by the subroutine!!! So if a subroutine immediately saves registers to the stack you must press F3 before this happens, or else you'll most probably bomb out!
  • Ttraps (F4): Identical to Trace, but lets you enter a trap vector and trace it. Useful for tracing through O/S or a custom trap.
  • Skip PC (F5): Just skips to the next instruction.
  • Source (F6): If you assemble a source from Turbo Assembler to Bugaboo then you can see the source this way.
  • Hexdump (F7): Produces a hex dump of the memory at PC. Also you can use the 'm' command on the CLI. Just type

m [#no_of_lines_to_display]

So, typing
m $200000


will produce a memory dump of $200000 onwards. However if you only need to display 3 lines (this is mosty because you don't want to overwrite other information being displayed) you can use
m $200000#3

  • Disassm (F8): Produces a diassembly of the memory at PC. Like F7 there is a CLI equivalent:
d [#no_of_lines_to_display]

  • List (F9): Produces a re-assembly of the memory at PC. Like F7 and F8 we have:
l [#no_of_lines_to_display]


Now, when you press F7, F8 or F9 you will see a listing that resembles these:

F7:
$200000>,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00


F8:
$200000>/0000,0000    ; ori.b #0,d0


F9:
$200000>!     ori.b #0,d0


What Bugaboo does here is to provide the listing in CLI style. This is default and I don't think it can be changed. What most people don't realize here is that what is printed there can be changed at will. In fact you don't need to type any command to change any memory place, if you know the syntax. Let's break the lines down a bit. (taking F8 as an example)

$200000>

This is of course the memory address. The '>' is essential for Bugaboo to parse the command properly. When you see a '>>' character it means that the PC is in that address.

/0000,0000

This is the disassembled opcode actually.

; ori.b #0,d0

This is actually a comment just to help you. Bugaboo stops parsing a line when it encounters the 1st ';'. In this case it shows you the instruction at that address.

So, let's say you want to change $200000 to have a nice nop instruction instead! What you can do is go to a clean line in the CLI (navigate using the cursor keys) and write the following:

$200000>/4e71;

(the ';' is essential if the line is not 100% and contains some other characters after our opcode) Press Return and voila! Instruction changed! If you don't remember the hex value of the opcode you can of course use:

$200000>!nop;

If you want to see the changed listing just type:

l $200000;

It is a personal preference of mine to end the commands I enter using a ';' because this way I don't have to worry about finding an empty line or cleaning it up.

  • Switch (F10): Switches between Bugaboo's screen and the user screen.

Let's take a small break here and discuss some stuff. Bugaboo is a highly crash-proof debugger. It manages that by hooking to every vector possible (just about) and using its own custom interface, keyboard interrupt, mouse driver, palette, etc. So games that disable vectors don't actually do anything to Bugaboo, as it switches between states (debugger mode, user mode) every time that is needed (i.e. when you trace an instruction). Also, any interrupts that the program sets don't affect Bugaboo at all since too are saved and restored when it's needed. It's also reset proof.

  • Tractre (Shift-F3): Like F3, but for RTEs. Careful with this!
  • Go (Shift-F4): Runs the program until it exits or an exception is reached or a breakpoint.
  • Marker (Shift-F6): Lists all defined markers (more on this later)
  • Breakp (Shift-F7): Lists all defined breakpoints (later as well)
  • Quit (Shift-F10): Exits to the O/S (if you haven't trashed all memory that is ;))

A bit more on the Bugaboo screen


Line 3 of the Bugaboo screen writes the following:

 PC=200000 USP=3F7FF8 SSP=100000 SR=TS210XNZVC ori   #0,d0

Clicking on any of the 3 numbers in PC, USP, SSP takes the cursor there and lets you change the value on the spot. Clicking on any letter on the SR (except 'T') lets you toggle any bits on it. Handy eh? :-)

Line 4 and 5 are like this:

A0-A7 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000


As you expect, if you click on any of those numbers they can be changed.

But, what are the two arrows doing there? Well, this is a very nice feature (unique perhaps?) that in spite of a better name I'd like to call 'backtracing'. Let's say you traced thru a few commands and you suddenly realize that you wanted to see what d0 was 5 instructions ago. Oops! Usually this would mean restarting the trace from the beginning, which can get very tedious. But if you click on the left arrow then you can actually see the state of the PC and registers one instruction back! Bugaboo keeps quite some of those states (32?) and you have the added bonus that you can actually set that state to be the current! What this means is that you can reverse the trace! (of course the memory can't be altered back) What you need to do to achieve this is click on the "close box" character that appears on the 3rd line (on top of the arrows) when you go back some states. You can also do this by pushing alt+left or right buttons, and alt+insert to go back to a previous state.

Now that we covered a few things about the CLI, let's discuss a few more useful commands. First of all:

Loading stuff into memory


  • The easiest way to enter stuff into Bugaboo is to have Turbo Assembler assemble to the debugger memory! This way when you enter Bugaboo, you have your program ready to be traced, and the PC set up.

  • Another way is to load an executable or data file into memory. But first we need to learn to navigate through the directories using the CLI. When you type DIR at the cli, the directory is displayed in the following format:

dir CODE\  ;0   11:15:30 20-02-2007 sub dir STUFF\ ;0   04:43:40 20-01-2003 sub lo  file1.ggn  ;.3358 17:56:11 11-01-2001 lo  file2.ggn  ;.1000 13:56:11 11-01-2001 le  exe1.prg   ;.5640 18:54:11 11-01-2001 le  exe2.tos   ;.5640 11:56:11 11-01-2001


I guess at this point most people that haven't read the previous text will switch off bugaboo :-). But we know better, right? What you might have figured out reading this listing is that these are actually commands generated to be executed by the CLI by navigating the cursor to the desired line, pressing Return and have the command executed.

The same as before apply: everything after a ';' is discarded and is usually provided for your info, so we're left with much less stuff than is displayed. So, executing the 'dir' commands will actually change the directory path to the one selected and display the directory listing. The 'lo' command will load a binary file to the address of the PC. Finally the 'le' command will load the file as a gemdos relocatable file. Bugaboo makes the decision on whether to generate a 'le' or 'lo' command by the file's extension: 'tos', 'ttp', 'app' and 'prg' will generate 'le' by default. Of course if you know that a file is gemdos executable just change the 'lo' to 'le', press return and the file will be loaded as executable.

  • Lastly, you can read a sector from disk! The 'readsector' command is used for this. It's syntax is:

readsector ,,,

So, if you want to trace thru a boot demo/game/whatever you can put the disk in drive a and type:

read ,1,,pc

Then set supervisor mode on and start tracing :-)

Some more misc stuff on the CLI


If you took a close look at the directory listing above, you must have noticed that after the comment the file's size, date and time is printed. On the file size you see that the number is prefixed by a '.'. This is because Bugaboo parses that as a decimal number. Not using a prefix on a number implies hexadecimal numbers, and a '%' implies binary numbers. Here are some examples:

? 1000+.256+%1; $1101 .4353 %1000100000001 "...." save testfile,^a0,^m0+^d0-100; Save TESTFILE from $100 to $3000 =.12032 Bytes. Do you want to save? (y/n) $200000>!move.w #^m0+^m1,d0;

The first example evaluates that expression and prints the result using 3 different formats, for your convenience. The second writes the memory from where A0 points to where marker M0 plus D0 points minus $100. Lastly the third assembles that command to $200000, evaluating the expression and producing the result.

Notice that I use ';' after each command. In practice you'll understand why! Also, as you see if you want to omit a parameter, just sikp it with a comma.

Another handy hint (these posts are all about handy hints anyway :-)): If you want to execute an instruction without having to assemble it to memory and tracing thru it you can use the '|'. So if you want to move the contents of $ff8240 to d0 (without having to actually produce a mem dump and a set) you can type:

|move.w $8240.w,d0;


This will be executed on the spot.

Setting variables (~ and LET)


There are lots of stuff that can be set, and fortunately it is done using the same mechanism.

LET =value ~=value


(both are equivalent)

So let's have a few examples of setting stuff:

~b0=PC ;sets breakpoint 0 at PC ~b1=PC-^a1+^d5+200 ; sets breakpoint 1 at PC - (value of a1) + (value of d5) + $200 ~m0=^b0+100 ;sets marker 0 at breakpoint 0 + $100 ~m0=.somelabel ;this works if you have assembled your program with debug symbols on    ;note that you have to use the full stop in front of the label


Yay, we finally set some breakpoints . Now, the breakpoint setting has some more tricks under its sleeve. For example:

~b0=PC?^d0=3


will set breakpoint to hit at PC, BUT will only stop execution when d0 is 3. Neat huh?  

Some misc commands


breakpoints or b


Simply displays all breakpoints

showmemory or showm


Sacrifices one line of display to show 16 bytes of consecutive memory. Very handy since everytime you trace an instruction the line gets updated (although this slows down speed a bit).

resident or resi


Makes Bugaboo resident and exits. After that it can be called from Turbo Assembler by pressing F2, or when an exception occurs (handy for debugging GFA inlines ).

observe trap,function


Stops execution when a certain function of a trap gets called.

help


Will give you a listing with all the built-in commands you can use

Some other random things that are nice


  • Pressing both shifts when the program is running ceases execution (well of course for programs that steal the keyboard interrupt it won't work)
  • By putting BUGABOO.PRG in the auto folder and rebooting you get Bugaboo resident automatically. If you press a certain combo of alt/shift/ctrl (I usually press all) while it's loading you can enter Bugaboo without GEM.
  • By setting variables col0 and col1 you can change the colour scheme of bugaboo, just provide the rgb value in hex.