BitMagic The Complete Development Environment for the Commander X16.

Debugging

Once you press F5, BitMagic behaves like any other VSCode debugger: stepping, breakpoints, hovers, disassembly, memory and jump to cursor, all covered below. Its own views, like the memory and layer viewers, are on The Debugger.

Launch configuration

A session is configured the same way as any VSCode debugger: a type: bmasm entry in the workspace’s .vscode/launch.json. See The launch config for its properties and how to add one. debugArgs takes the same flags as the standalone emulator, for example ["--warp"].

Build errors

If a build fails, the compiler’s errors appear as problems in the editor (a red marker on the offending line and an entry in the Problems panel), with the full log in the BitMagic output channel.

Stepping

Continue, step over, step into and step out all work against your .bmasm source lines, including code generated by the template engine. Where a line generated multiple instructions, stepping walks the instructions. The exception is code built up in a string variable and output as a block: it steps into a separate generated file instead of the original lines, see Multiline Template Code.

Breakpoints

  • Source breakpoints: click the gutter next to a line.
  • Conditional, hit-count and logpoints: see Watches and Breakpoints.
  • Function breakpoints: not a named procedure, but a call typed into VSCode’s function breakpoint box. vram(0x1b000) breaks on any read or write to that VRAM address; add a second address for a range, and "R", "W" or "RW" to limit the direction, for example vram(0x1b000, 0x1b200, "W"). vsync() breaks on the next frame, and vsync(100) on a specific frame number.
  • Instruction breakpoints: set in the disassembly view.
  • Exception breakpoints: three filters in the Breakpoints panel. Code Exception fires when an .exception directive is hit (on by default), File IO Exception when a LOAD call returns an error code (on by default), and BRK Hit when a BRK instruction executes (off by default).
  • Startup breakpoints: the breakpoints array in the project file is a list of addresses to break on as soon as the machine starts.

Hovering over code

Hover over a name or an operand in a .bmasm file to see what it is and what it works out to. This works while you’re editing as well as while debugging; while a session is paused, the hover shows the machine as it is now.

While you’re editing, the hover comes from the last build that worked, which BitMagic makes in the background as you type:

  • A name shows its full path, its type (constant, label, procedure, byte, ushort and so on), whether it’s private, and its value. Names are looked up from the line you’re on, so loop inside a procedure finds that procedure’s loop. Private names in other scopes still show, as in the debugger.
  • An operand shows the value the build used and the addressing mode, then each name in it with its value, and the expression with the values put in.
  • A directive such as .const or .byte shows what its expression works out to, the same way.
  • Template code (@(...)) shows the line it compiled to, and that line’s value.
  • A KERNAL routine also shows its documentation.
.const COUNT $10
    adc #COUNT+1    ; hover: `#COUNT+1` = `$11` (17), immediate
                    ;        `COUNT` App:Main:COUNT, constant, `$10` (16)
                    ;        `$10+1`

Until a broken edit builds again, the hover shows the previous build, so a name you’ve only just added won’t have one yet.

While a session is paused, the hover is the value now, and expanding it shows how it was worked out:

  • A variable shows its current value, read as its type.
  • An indexed or indirect operand shows the value it loads now. Expanding it shows the register, the pointer for (ptr),y and (ptr,x), and the address it ends up at.
  • An address from $a000 up is read from the current RAM or ROM bank, and says which.
  • IO registers ($9f00 to $9fff) aren’t read, as reading some of them changes the machine (VERA_DATA0 moves VERA’s address on). The hover shows the address and says so.
    lda (ptr),y     ; paused, Y = 3: $99 (153)
                    ;   pointer  $4000 at $22
                    ;   address  $4003

The debugger’s hover uses the build being debugged, so it stays right while you edit during a session.

Disassembly

Open the disassembly view to step through raw instructions, including ROM code. Symbols from the symbols files and jump tables are applied, so KERNAL calls show by name.

Memory

The Variables pane exposes CPU.Ram, VERA.VRam, the RAM and ROM banks, and the SD card as memory blocks. VSCode’s hex editor can open any of them, and memory is writable while paused. The same memory can be read as typed values in an expression, for example CPU.Ram[0x0000].Short; see Watches and Breakpoints.

Jump to cursor

“Run to cursor” and setting the next statement are supported; the CPU’s PC is moved to the chosen line.

Not available

VSCode’s native data breakpoints (right-click a variable and choose Break on Value Change) aren’t supported; a vram() function breakpoint covers the VRAM case. Editing a value directly in the Variables pane isn’t supported either; use the hex editor instead.

Running in the official emulator

The command Run Project In The Official Emulator builds the project and runs it in the official X16 emulator instead of BitMagic’s. This is useful for checking behaviour against the reference implementation. It needs the official emulator, which the extension can download for you (see Settings).