loading...
All Genesis articles | Back to top

SEGA Genesis: Debugging

CRASH!

Debugging SEGA Genesis code can be tricky, as there currently isn't an all-in-one IDE that allows step debugging and memory inspection.

Most of these features are available in emulators, though, and different emulators are suited for different tasks.

It is possible to debug your ROM in the multi-system emulator MAME with symbols generated from your code, and it will be explained below how to do this. However, MAME lacks sophisticated visualization of graphics memory, and inspecting or modifying other parts of memory is confusingly organized. Other emulators might be a better choice for debugging graphics issues.

Debugging the state of the VDP graphics chip and VRAM can be performed in the Regen and Exodus emulators. Exodus has a lot of debugging features, but Regen is more lightweight and can be used effectively for iterative work, so they might be useful in different situations.

First, we will look at how to debug ROMs in MAME.

MAME Debugging

MAME Debugging window

If you require step debugging of Genesis ROMs and want symbols to help navigate the code, MAME is a decent choice. First off, we will look at starting the MAME debugger.

If you invoke MAME like this, you will get a debug window:

mame64 genesis -debug -dfontsize 11 -window -cart myrom.gen

The disassembly will point to the entry point specified in the ROM header, and execution will start out paused.

You can step through the code with F11. When debugging interrupts, it can be useful to use F7 to run until the next interrupt.

The main debug window shows beamx and beamy, which is the horizontal and vertical position of the TV electron beam, useful for figuring out issues with hblank and vblank interrupts.

Below are all the registers, including the program counter (PC) and the stack pointer (SP/A7).

Ctrl+M opens a new Memory window, where memory can be viewed and edited. The drop-down menu selects which memory to inspect. This list has some confusing and non-functional entries, but a few useful ones are:

 RAM  : memory/:maincpu/0/00e00000-00e0ffff
 CRAM : Sega 315-5313 Megadrive VDP:/gen_vdp/0/m_cram.get()
 VRAM : Sega 315-5313 Megadrive VDP:/gen_vdp/0/m_vram.get()
 ROM  : Region ':mdslot:cart:rom'

A few MAME debugger hotkeys:

F10     Step over
F11     Step into
F7      Run until interrupt
Ctrl-M  Show memory

And commands:

go [ADDR]  Run until reaching ADDR
help       The most important command of all

Even though MAME has a disassembly view, debugging your ROM can still be confusing, because the disassembly is a direct translation of the machine code in the ROM, which is similar to, but not the same as, your assembly source code. First of all, all labels are missing, so you'll have to recognize the code itself without the context of naming. Secondly, VASM and other assemblers slightly modifies the instructions used from the ones written in the code, if there are obvious candidates for optimization, e.g. the MOVE instruction can be modified to a MOVEA or MOVEQ instruction, depending on the arguments. Finally, the emulator disassembler can't really know whether a block of memory contains code or data, so data will be shown as code, and to compound the confusion, machine code is ambiguous: the same bytes can be disassembled to different instructions, depending on where the program counter is supposed to point inside the memory.

Dedicated debugging tools often support loading symbols for a binary from an external file, such as a .PDB file. Next, we will look at a way to show symbols from your source code in the MAME disassembly window.

MAME Disassembly with Symbols

MAME disassembly with symbols

To show symbols from your code in the MAME disassembly window, we can use a VASM assembler program lists and the MAME debug comment feature, along with a small translation script.

First off, comments can be added to instructions in the MAME debugger with this command:

comadd [addr],comment

and viewed in the disassembly by pressing Ctrl+N.

To automate creating comments, we can use the VASM list file feature. If you run VASM like this:

vasm -L myrom.lst -Fbin mycode.asm -o myrom.gen 

VASM will generate myrom.lst, which has a full program listing with extra metadata. At the end of myrom.lst is a list of symbols:

Symbols:
vblank LAB (0x2bc) sec=CODE 
hblank LAB (0x318) sec=CODE 
EntryPoint LAB (0x210) sec=CODE 
rom_header LAB (0x0) sec=CODE 
...

This list has (label,address)-pairs that we can convert to comments in MAME. The following Ruby script mamelabels-vasm.rb generates a MAME debugger script from 'myrom.lst':

 lines=File.readlines("myrom.lst")
 mode=:skip
 lines.each do |line|
   if line == "Symbols:\n" then
     mode=:symbols
   end
   if mode == :symbols then
     if line.include?("LAB")
       words = line.split(" LAB ")
       addr = words[1][3..-2].to_i(16).to_s(16)
       puts "comadd #{addr},#{words[0]}"
     end
   end
 end

When you run

ruby `mamelabels-vasm.rb` > mamesymbols

'mamesymbols' will contain a list of MAME comment commands:

comadd 2bc,vblank
comadd 318,hblank
comadd 0,rom_header
comadd 210,EntryPoint

Now, we can start MAME using this command:

mame64 genesis -debug -dfontsize 11 -debugscript mamesymbols -window -cart myrom.gen

We can now press Ctrl+N in the disassembly window and we will have our labels listed to the right of the disassembled instructions.

To make this easy to use, we can make a BAT file that assembles, creates the MAME symbols, and starts MAME in debug mode with symbols:

set MAME_OPTS=-debug -dfontsize 11 -debugscript mamesymbols -window
 
vasm -quiet -L myrom.lst -Fbin mycode.asm -o myrom.gen 
ruby mamelabels-vasm.rb > mamesymbols
mame64 genesis %MAME_OPTS% -cart myrom.gen

MAME is good for debugging certain issues, but for debugging SEGA Genesis graphics, Regen or Exodus might be better choices.

Debugging Graphics with Regen

Regen is a emulator with graphics debugging functionality.

While working on some scrolling code, I encountered a VDP bug that was tricky to track down. I was trying to set the VDP register $0D (HScroll) to the value $34, and had accidentally written:

    move.w #$8D43,vdp_control ; set VDP reg. $0D = $43

See the problem?

It should have been this:

    move.w #$8D34,vdp_control ; set VDP reg. $0D = $34

Debugging this using mednafen or MAME was difficult, and Regen was a better choice. It has a VDP debug view that was very informative, as it shows the values of all VDP registers. Now I could easily see that register $0D (shown as #13) was set to $34 instead of $43.

Debuggin with Exodus

Exodus has a extensive suite of debugging windows, including disassembly, RAM viewer/editor, VDP register viewer/editor, VRAM pattern viewer, and more.

The emulator is very useful for debugging, even if it could benefit from a bit more online documentation.

Exodus emulator

Debugging with Mednafen

mednafen can also be used for basic debugging. Starting mednafen from the command-line with the debugger enabled and paused on the first instruction can be done like this:

    mednafen -debugger.autostepmode 1 roms\test1.gen 

A few important mednafen debug commands:

R                      Run
S                      Step
Up/Down, Page Up/Down  Navigate code
Space                  Set breakpoint
Alt+1                  CPU debugger view
Alt+3                  Memory view

See Mednafen Debugger Documentation.

References

Emulators:

Tools: