Spectrum Windowed Debugger
an idea by Chris Wild
www.icemark.com
 

Having spent much of my time hacking games on the spectrum or creating data formats for them using my PC. I have over the years dropped into a set way of looking at the code. This has involved either special tools that I have written a spectrum or an emulator. I can’t bear to use my spectrum anymore so I use an emulator, however none of the emulators support debugging to a standard that you would find in PC development tools – but then, why should they. However, I am looking for a change that if executed would allow myself or people like me – good access to debugging or reverse engineering spectrum games.

I am looking for a version of an emulator that is driven from the debugger side. This is ideally having a windows based debugger that uses the emulator engine to execute the Z80 code or by adding the debugger features into a current emulator.

DLL based emulation
This option could be to have an existing emulator ( or even new one ) be controlled by another external program without displaying itself. The emulator could exist as a DLL which exposes functions something like the following.

function perameters description
Init   Allows the emulator DLL to initialise itself
LoadSnapshot filename Loads a snapshot into memory
LoadBookmark *bookmark Loads from a bookmark
SaveBookmark *bookmark Saves to a bookmark
FreeBookmark *bookmark allows the emulator to delete the bookmark data
SetExecuteAddress address Sets the Current execution address
ExecuteNext count, output Executes the next n instructions until, -1 = infinite, show output if requested. The output may be in a window or full screen. If full screen it must return to windows mode after exit of this instruction.
GetMemoryBank bank, address returns a 16k memory chunk from the specified page
SetMemoryBank bank, address set a 16k memory chunk at the specified page
GetRegistersAndPorts **register structure returns all registers and ports
SetRegistersAndPorts **register structure sets all registers and ports
GetInfo **info structure returns info about the status of the spectrum virtual machine
SetBreakpoints *breakpoints, count sets the array of breakpoints
DisassembleInstruction addr, buffer, count fills the buffer with a disassembly of the instruction and returns the number of bytes used by the opcode
GetBankExeBitArray bank returns a bitarray for a memory bank, a bit is set if the address has been executed or was part of an opcode being executed. ie: all bytes making up an opcode will be flagged if the opcode is executed.
DeInit   allows the emulator to deinit

* defined later in document
** to be defined by an emulator author!

This emulator could then be controlled by a separate program . This would allow for the Debugger to be developed separately from the emulator and by emulator independent. This would mean less work for the emulator authors and move the guts of the tools over to the tools writers.

The Debugger could be styled like Microsoft Visual C/C++ debugger. This is a pretty powerful and user friendly environment. And one that I am familiar with. This would then incorporate all the added features I require.

Added Features 
Debug Commands

command action
Go
- F5
Executes code from the current statement until a breakpoint is reached or the end of the program is reached.
Restart
- CTRL R
Resets execution to the first line of the program. This command reloads the program into memory.
Step Into
- F11
Single-steps through instructions in the program, and enters each function call that is encountered.
Step Over
- F10
Single-steps through instructions in the program. If this command is used when you reach a function call, the function is executed without stepping through the function instructions.
Step Out
– SHIFT F11
Executes the program out of a function call, and stops on the instruction immediately following the call to the function. Using this command, you can quickly finish executing the current function.
Run to Cursor
- CTRL F10
Executes the program as far as the line that contains the insertion point. This command is equivalent to setting a temporary breakpoint at the insertion point location.
Bookmark Takes a snap of memory and registers at the current execution stage.
Goto Bookmark Returns the program to the state as of the previous bookmark.
Skip to Cursor The current execution address is set to the current insertion point.
Toggle Breakpoint
- F9
Sets or clears breakpoint at the current insertion point
View Set Watchpoint Goto the Watch Window
View Set Breakpoints Goto the breakpoint Window
Search Goto the Search Window
View Variables Goto the Variables Window
View Disassembly Goto the Disassembly Window
View Memory Goto the Memory Window
View Stack Goto the Stack Window
View Output Window Goto the Output Window

Registers Window
Traditional view of registers and flags.

Memory Windows
View memory by setting location, optional format and element size.

Disassembly Window
This window can be viewed RAW as straight code or FORMATTED using the Labels file.

The disassembly window should be able to scroll up and down through and view any part of the program. Interaction with the output would allow for keyboard setting of commands. Eg. Set Breakpoints, Clear Breakpoint, Run to Cursor.

Symbols Window
In my Z80 disassembler I use a file that contains symbols from the program. It is in the format;

address address in memory
name name of symbol, if left blank the symbol defaults to LXXXX. Where XXXX is the address in hex.
comment optional comment
type type of data that follows the address. CODE, BYTES, WORDS, ASCII, REFWORD
size optional chunk size. if a label points to an area of memory then the whole chunk can be defined without needing to set a terminating label. After the data has been exhausted the next chunk reverts to the type of the previous.
elements optional no of elements per line. If a label points to BYTES and the data is accessed as a table of 6 byte entries then 6 bytes would be displayed per line

Using this file allows the output of the disassembly window to be accurately produced.

Either a version of this file should be supported or the ability to create this information during the sessions should be added. All symbols that are within this system can then be typed in place of memory addresses anywhere in the debugger.

Watch Windows
Set watches on addresses and registers. if a register is watched then putting the register in brackets uses the address that the register points to.

Variable Windows
Like the watch window but automatically shows all variables that have be set in the symbol file.

Breakpoints
Breakpoints can be set at a location.
Breakpoints can be set if a memory address is changed or accessed.
Breakpoints can be set if any byte within a memory range is changed or accessed.

typedef struct {
	break_t	type;
	u16		start;
	u16		end;
} beakpoint_t ;
types might be;
enum break_t {
	BRK_NONE,			/* unused */
	BRK_SINGLE,		/* break at address start*/
	BRK_SINGLE_WRITE, 		/* break if data address written to */
	BRK_SINGLE_READ,		/* break if data address read */
	BRK_SINGLE_READWRITE,	/* break if data address read or written */
	BRK_RANGE,		/* as above for address between start-end */
	BRK_RANGE_READ,
	BRK_RANGE_WRITE,
	BRK_RANGE_READWRITE,
};

View Output
View the screen output in a window while in the debuggers. This window can have attributes turned on or off and can also have a optional memory address assigned to it. This allows the viewing of secondary buffers.

Search
Search for bytes or sequence of bytes. These can be typed in as hex or ascii.

Analysis
An extended function would be to analyse the executing program and add information to the Symbols Table. A quick execution would allow a memory map to be created and then worked on. Eg any memory addresses access are likely to be data whereas address execute are code.

Bookmarks
Bookmarks are a structure that points to a memory snapshot. This snapshot is identical to the emulators native snapshot format ie. .z80 .sna. This data could then be written to a file or reloaded from memory by the emulator. This gives the option for quick load/saving or remembering the machine state during execution.

The Bookmark structure would look something like;

typedef struct {
	void*	data;
	int	size;
} bookmark_t;

back to Sinclair Spectrum
back to sinclair spectrum