Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 71313f5a02
Fetching contributors…

Cannot retrieve contributors at this time

123 lines (111 sloc) 7.277 kb
Spiffy: Yet another ZX Spectrum emulator
Debugger manual.
The debugger is activated by pressing Esc or clicking the sickly green button with the picture of a bug. It can only be activated if a tty is present.
When the debugger is active, normal emulation will be halted and the debugger prompt ">" will appear in the tty.
You can get rudimentary help from within the debugger by entering "h" (for a command list) or "h h" (for a list of help sections).
=Running and Stepping the Z80=
"next", or "n", will step the Z80 by one instruction, or if Tstate stepping is enabled, by one Tstate.
Tstate stepping can be enabled with "1" and disabled with "!1"; there is also a command line option --[no-]Tstate.
"cont", or "c", will leave the debugger and continue normal emulation until a breakpoint is encountered or the debugger is activated again.
"quit", or "q", will exit Spiffy.
=Examining Z80 internal state=
"state", or "s", will display a compact readout of the Z80's internal state, the bus, and regions of memory around (PC), (HL), (SP), (BC), (DE), and (nn). nn refers to the contents of two internal Z80 registers which store 16-bit literal operands (eg. in LD rr,nn or LD r,(nn)).
"trace", or "t", will cause this readout to be displayed after each time the Z80 is single-stepped. "!t" disables.
You can enable or disable interrupts with "ei" and "di" respectively.
You can reset the Z80 with "reset", or "r".
To trigger an interrupt or NMI, use "int" or "nmi". "i" is short for "int". You can clear the INT/NMI lines with "!int" and "!nmi".
You can set a breakpoint at an address xxxx (in hex) with "break xxxx"; you can clear it with "!break xxxx". "break" can be shortened to "b".
You can list the current breakpoints with "list" or "l".
=Expressions ('p' command)=
p-expressions are given in Polish Notation; that is, every operator is a prefix operator. So, instead of writing "2+3", you write "+ 2 3"; instead of "[[STRMS+2.w]+8.b]", you write ".b + .w + @STRMS 2 8".
Going the other way, you would read that last expression as "The byte at (The sum of (The word at (The sum of STRMS and 2)) and 8)".
b Byte
w Word (16 bits, little endian)
f Float (Sinclair 5-byte format)
8 8-byte grid (good for characters of fonts)
R 16-byte row
.b 8ccc - byte at 0x8ccc.
.f dead - 5-byte float at 0xdead.
.w @VARS - word at VARS.
.8 + .w @CHARS 118 - 8 bytes from 280 bytes after the address pointed to by CHARS (0x5c36).
.b + #IX 25 - byte at IX+0x25.
= .b #DE .b #HL - copies a byte from [HL] to [DE], and prints the byte copied.
.b:AY 5 - byte from AY register 5.
<expression> ::= <unop> <expression> | <binop> <expression> <expression> | <sysvar> | <register> | <literal>
<unop> ::= '~' | <indirection> | <cast>
<binop> ::= '+' | '-' | '*' | '/' | '%' | '&' | '|' | '^' | '='
<cast> ::= '\'' <type>
<indirection>::= '.'<type> | '.'<type>':'<far>
<type> ::= 'b' | 'w' | 'f' | '8' | 'R'
<far> ::= 'AY' | 'ULAPLUS'
<sysvar> ::= '@'<sysvarname>
<register> ::= '#'<registername>
<literal> ::= <hex-literal> | <float-lit>
<hex-literal>::= <xdigit>*{1,4}
<float-lit> ::= '_'<float-val>
op types description & return type
~ bw8R Bitwise Complement. Return has type of operand.
+ numeric Sum. Common numeric type rules apply.
- As + Difference. Return type as +.
* As + Product. Return type as +.
/ As + Quotient. Return type as +.
% integer Remainder. Common integer type rules apply.
& As % Bitwise AND. Return type as %.
| As % Bitwise OR. Return type as %.
^ As % Bitwise XOR. Return type as %.
= lvalue Assignment. First operand must be an lvalue. Both operands must have same type. Returns first operand.
'T T-castable Typecast. Return type given by T.
.T bw Indirection. Return type given by T, and is an lvalue.
@ Return type is w, and is the address of the sysvar.
# Return type is b for 8-bit registers, w for 16-bit. Note that the 8-bit register names are *case sensitive*, because eg. "a" is the high byte of AF'.
hex-literal Return type is b if <=2 xdigits, else w.
_float-lit Return type is f.
=System Variables=
The command "sysvars", or "y", lists all the system variables and their values, in appropriate formats for their types.
"y <sysvar>" will display only the requested <sysvar>.
The formats are:
CHAR '%c' = %u = 0x%02x = '\\%03o'
FLAGS 0x%02x = %08b
ADDR 0x%04x
BYTES {hexadecimal bytes}
U8 \
U16 | These three display an 8/16/24-bit little-endian unsigned integer, in decimal
U24 /
XY This displays the first and second bytes as (%u,%u)
=Examining BASIC variables=
The BASIC variables can be listed, with their values, with "vars" or "v".
A specific variable can be examined, by passing it as an argument to "vars"; eg. "v mynumber".
You can examine arrays similarly, like "v a 1 2". If you don't want to subscript a numeric array, you have to use a subscript of "()", like "v a ()", to indicate that you want the array a() and not the variable a. This is because Sinclair BASIC allows both to exist concurrently.
The address displayed for a BASIC variable depends on its type, as follows:
Numeric single: Address is that of the 5-byte float
String single: Address is that of the variable name. The string data starts 3 bytes later
Numeric array : Address is that of the 5-byte float of the first element of the array
Char array : Address is that of the first element of the array
So for instance if a$ is an array[5][3], "v a$ 2" will give the address of a$(2)(1), while if b$ is a string, "v b$" will give the address of the metadata for b$, whereas "v b$ 1" will give the address of b$(1), the first character of the string. Numeric variables always give the address of a 5-byte float, allowing you to modify the variable directly with "p = .f addr _val".
=Examining the BASIC program=
The BASIC program can be listed with "k" (the name was chosen because "k" is the key for LIST on the Spectrum).
Using "kn" instead causes the embedded floating-point numbers in the source to be displayed.
You can list a specific line by passing it as an argument to "k" or "kn". For example "k 20" will display line 20.
=Inspecting peripherals=
If enabled, the AY chip can be inspected with "aystate" or "a". Its 16 registers can also be accessed with far-pointers (.T:AY) in the p[rint] command.
The 16 AY registers are:
AF,AC Fine & Coarse pitch for channel A
BF,BC ,, ,, ,, ,, ,, B
CF,CC ,, ,, ,, ,, ,, C
NO Noise pitch
MI Mixer (IOB IOA NC NB NA TC TB TA) active low
AV Volume for channel A (low 4 bits; 0x10 = Envelope flag)
BV ,, ,, ,, B
CV ,, ,, ,, C
EF,EC Fine & Coarse envelope duration
ES Envelope shape
IA,IB I/O ports A and B (not used in Spiffy)
If enabled, the ULAplus can be inspected with "ulaplus" or "u". Its palette registers can also be accessed with far-pointers (.T:ULAPLUS) in the p[rint] command.
For details on the semantics of ULAplus palette registers, see <>.
Jump to Line
Something went wrong with that request. Please try again.