Monitor/Debugger

Fuse features a moderately powerful, completely transparent monitor/debugger, which can be activated via the Machine > Debugger… menu option. A debugger window will appear, showing the current state of the emulated machine: the top-left ‘pane’ shows the current state of the Z80 and the last bytes written to any emulated peripherals. The bottom-left pane lists any active breakpoints. Moving right, the next pane shows a disassembly, which by default starts at the current program counter, although this can be modified either by the ‘disassemble’ command (see below) or by dragging the scrollbar next to it. The next pane shows the current stack, and the next pane has any ‘events’ which are due to occur and could affect emulation. Below the events pane is the Spectrum’s 64K memory map (the W? and C? indicate whether each displayed chunk is writable or contended respectively). Fuse tracks the memory mapping of the overall address space in 2KB chunks but will summarise the mapped pages where they are part of the same page of the underlying memory source (e.g. 8KB page sizes in the Spectrum 128K and 4KB pages in the Timex clones’ DOCK and EXROM banks). Below the displays are an entry box for debugger commands, and five buttons for controlling the debugger:

BUTTON DESCRIPTION
Evaluate Evaluate the command currently in the entry box.
Single Step Run precisely one Z80 opcode and then stop emulation again.
Continue Restart emulation, but leave the debugger window open. Note that the debugger window will not be updated while emulation is running.
Break Stop emulation and return to the debugger.
Close Close the debugger window and restart emulation.


Double-clicking on an entry in the stack pane will cause emulation to run until the program counter reaches the value stored at that address, while double-clicking on an entry in the ‘events’ pane will cause emulation to run until that time is reached.

The main power of the debugger is via the commands entered into the entry box, which are similar in nature (but definitely not identical to or as powerful as) to those in the gdb debugger. In general, the debugger is case-insensitive, and numbers will be interpreted as decimal, unless prefixed by either ‘0x’ or ‘$’ when they will be interpreted as hex. Each command can be abbreviated to the portion not in curly braces.

COMMAND DESCRIPTION
ba{se} number Change the debugger window to displaying output in base number. Available values are 10 (decimal) or 16 (hex).
br{eakpoint} [address] [if condition] Set a breakpoint to stop emulation and return to the debugger whenever an opcode is executed at address and condition evaluates true. If address is omitted, it defaults to the current value of PC.
br{eakpoint} p{ort} (re{ad}|w{rite}) port [if condition] Set a breakpoint to trigger whenever IO port port is read from or written to and condition evaluates true.
br{eakpoint} (re{ad}|w{rite}) [address] [if condition] Set a breakpoint to trigger whenever memory location address is read from (other than via an opcode fetch) or written to and condition evaluates true. Address again defaults to the current value of PC if omitted.
br{eakpoint} ti{me} time [if condition] Set a breakpoint to occur time tstates after the start of every frame, assuming condition evaluates true (if one is given).
br{eakpoint} ev{ent} area:detail [if condition] Set a breakpoint to occur when the event specified by area detail occurs and condition evaluates to true. The events which can be caught are listed below.
cl{ear} [address] Remove all breakpoints at address or the current value of PC if address is omitted. Port read/write breakpoints are unaffected.
cond{ition} id [condition] Set breakpoint id to trigger only when condition is true, or unconditionally if condition is omitted.
co{ntinue} Equivalent to the Continue button.
del{ete} [id] Remove breakpoint id, or all breakpoints if id is omitted.
di{sassemble} address Set the centre panel disassembly to begin at address.
fi{nish} Exit from the current CALL or equivalent. This isn’t infallible: it works by setting a temporary breakpoint at the current contents of the stack pointer, so will not function correctly if the code returns to some other point or plays with its stack in other ways. Also, setting this breakpoint doesn’t disable other breakpoints, which may trigger before this one. In that case, the temporary breakpoint remains, and the `continue’ command can be used to return to it.
i{gnore} id count Do not trigger the next count times that breakpoint id would have triggered.
n{ext} Step to the opcode following the current one. As with the `finish’ command, this works by setting a temporary breakpoint at the next opcode, so is not infalliable.
o{ut} port value Write value to IO port port.
se{t} address value Poke value into memory at address.
se{t} $variable value Set the value of the debugger variable variable to value.
se{t} area:detail value Set the value of the system variable area : detail to value. The available system variables are listed below.
s{tep} Equivalent to the Single Step button.
t{breakpoint} [options] This is the same as the breakpoint command in its various forms, except that the breakpoint is temporary: it will trigger once and once only, and then be removed.


Addresses can be specified in one of two forms: either an absolute addresses, specifed by an integer in the range 0x0000 to 0xFFFF or as a ‘source:page:offset’ combination, which refers to a location offset bytes into the memory bank page, independent of where that bank is currently paged into memory. RAM and ROM pages are indicated, respectively, by ‘RAM’ and ‘ROM’ sources (e.g. offset 0x1234 in ROM 1 is specified as ROM:1:0x1234). Other available sources are: ‘Betadisk’, ‘“Didaktik 80 RAM”’, ‘“Didaktik 80 ROM”’, ‘“DISCiPLE RAM”’, ‘“DISCiPLE ROM”’, ‘“DivIDE EPROM”’, ‘“DivIDE RAM”’, ‘“DivMMC EPROM”’, ‘“DivMMC RAM”’, ‘If1’, ‘If2’, ‘“Multiface RAM”’, ‘“Multiface ROM”’, ‘“Opus RAM”’, ‘“Opus ROM”’, ‘PlusD RAM’, ‘PlusD ROM’, ‘SpeccyBoot’, ‘Spectranet’, ‘“Timex Dock”’, ‘“Timex EXROM”’, ‘ZXATASP’ and ‘ZXCF’.

Please, note that spaces in memory sources should be escaped, e.g.,break Didaktik\ 80\ ROM:0:0x1234. The 48K machines are treated as having a permanent mapping of page 5 at 0x4000, page 2 at 0x8000 and page 0 at 0xC000; the 16K Spectrum is treated as having page 5 at 0x4000 and no page at 0x8000 and 0xC000.

Anywhere the debugger is expecting a numeric value, except where it expects a breakpoint id, you can instead use a numeric expression, which uses a restricted version of C’s syntax; exactly the same syntax is used for conditional breakpoints, with ‘0’ being false and any other value being true. In numeric expressions, you can use integer constants (all calculations are done in integers), system variables, debugger variables, parentheses, the standard four numeric operations (‘+’, ‘-‘, ‘*’ and ‘/’), the (non-)equality operators ‘==’ and ‘!=’, the comparision operators ‘>’, ‘<’, ‘>=’ and ‘<=’, bitwise and (‘&’), or (‘|’) and exclusive or (‘^’) and logical and (‘&&’) and or (‘||’).

System Events

EVENT DESCRIPTION
beta128:page The Beta 128 interface is paged into memory.
beta128:unpage The Beta 128 interface is paged out of memory.
didaktik80:page The Didaktik 80 interface is paged into memory.
didaktik80:unpage The Didaktik 80 interface is paged out of memory.
disciple:page The DISCiPLE interface is paged into memory.
disciple:unpage The DISCiPLE interface is paged out of memory.
divide:page The DivIDE interface is paged into memory.
divide:unpage The DivIDE interface is paged out of memory.
divmmc:page The DivMMC interface is paged into memory.
divmmc:unpage The DivMMC interface is paged out of memory.
if1:page The Interface 1 shadow ROM is paged into memory.
if1:unpage The Interface 1 shadow ROM is paged out of memory.
multiface:page The Multiface One/128/3 is paged into memory.
multiface:unpage The Multiface One/128/3 is paged out of memory.
opus:page The Opus Discovery is paged into memory.
opus:unpage The Opus Discovery is paged out of memory.
plusd:page The +D interface is paged into memory.
plusd:unpage The +D interface is paged into memory.
speccyboot:page The SpeccyBoot interface is paged into memory.
speccyboot:unpage The SpeccyBoot interface is paged out of memory.
spectranet:page The Spectranet interface is paged into memory.
spectranet:unpage The Spectranet interface is paged out of memory.
rzx:end An RZX recording finishes playing.
tape:play The emulated tape starts playing.
tape:stop The emulated tape stops playing.
zxatasp:page The ZXATASP interface is paged into memory.
zxatasp:unpage The ZXATASP interface is paged out of memory.
zxcf:page The ZXCF interface is paged into of memory.
zxcf:unpage The ZXCF interface is paged out of memory.


In all cases, the event can be specified as area:* to catch all events from that area.

System Variables

System variables are specified via an ‘area:detail’ syntax. The available system variables are:

SYSTEM VARIABLE DESCRIPTION
ay:current The current AY‐3‐8912 register.
divmmc:control The last byte written to DivMMC control port.
spectrum:frames The frame count since reset. Note that this variable can only be read, not written to.
tape:microphone The current level of the tape input connected to the ‘EAR’ port. Note that this variable can only be read, not written to.
ula:last The last byte written to the ULA. Note that this variable can only be read, not written to.
ula:mem1ffd The last byte written to memory control port used by the ZX Spectrum +2A/3; normally addressed at 0x1ffd, hence the name.
ula:mem7ffd The last byte written to primary memory control port used by the ZX Spectrum 128 and later; normally addressed at 0x7ffd, hence the name.
ula:tstates The number of tstates since the last interrupt.
z80: register name The value of the specified register. Both 8‐bit registers and 16‐bit register pairs are supported. The MEMPTR / WZ hidden register is also supported. The (presumable) Q hidden register is also supported.
z80:im The current interrupt mode of the Z80.
z80:iff1 1 if the interrupt flip‐flop is currently set, or 0 if it is not set.
z80:iff2 1 if the interrupt flip‐flop is currently set, or 0 if it is not set.