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 cant 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;
|