Showing posts with label debugger. Show all posts
Showing posts with label debugger. Show all posts

Thursday, 20 November 2008

It's Refactor Time !

Well the debugger seems to be working great but I've become less happy about the structure of the code especially after strapping the GUI onto the emulation core and realising a short coming in the memory controller code. So, I'm taking stock and having a bit of a refactor before the project grows much larger.

What I'd missed in the memory controllers was the ability to bypass any side effects of reading or writing to a particular location. There are several places where custom chips react to a read or a write, and if I want to present the contents of memory through a debugger I have to be able to make these memory accesses transparent.

At the moment I manage memory by mapping the Amiga's memory to a simple array with 256 elements. I assign a specific "controller" instance to each "area" of memory. Using this method I can have separate classes that handle chip memory, CIA controllers, the custom chip set registers, reserved memory areas, ROM and so on. Each of the controllers implements a MemoryController interface that looks like this:


public interface MemoryController
{
void reset();
byte peekByte(int address);
short peekWord(int address);
int peekLong(int address);
void pokeByte(int address, byte value);
void pokeWord(int address, short value);
void pokeLong(int address, int value);
int peek(int address, DataSize size);
void poke(int address, int value, DataSize size);
}


As you can see though there is nothing that will let me access the memory in a transparent manner. I may need to add a few more methods such as debugPeekByte(...) or something similar to give me that functionality.

Memory accesses are handled by masking and shifting the requested address to give me an index into the memory map array and retrieving the appropriate controller. The request is then handed off to the controller to manage. This is all marshalled and encapsulated by a MemoryManager class which itself also implements the MemoryController interface. It's quite neat and is much nicer than a big switch statement or massive if/else if/else construct and no doubt a bit speedier too.

I'm also thinking I'm going to change my (not quite completed) breakpoint handling method with something simpler. At the moment I inject a special opcode at the address of the breakpoint and store the address in a map with the original opcode I replaced. The special Breakpoint instruction passes control to the CPU when invoked and also looks up the original code if disassembly is required. It's a bit ugly in it's implementation though and involves calling back and forth into several classes to determine the outcome, and of course it modifies code in memory. I think that it's waiting to bite me in the arse at a later point.

I think a better solution would be to handle the whole instruction execution cycle from a different method if we're running the debugger. This method could compare the current address to a list of breakpoints and handle them higher up the stack as it were. The overhead of doing this would only be while we were debugging. The "normal" execution loop wouldn't have the breakpoint checks in it.

Lots to do!

Monday, 17 November 2008

Debugger Alpha

I thought I just make a quick post to show the GUI debugger I've been working on the last week or so. It's incomplete but working well enough to put a grin on my face while stepping through code.

A quick screenshot:



The disassembly syncs nicely with the Program Counter as you step through and registers are all editable in place too.
Still to do are breakpoints and the memory views alongside the registers.
Bananas all round to those who noticed that I've borrowed the layout from Devpac's MonAm debugger ;)

Thursday, 6 November 2008

Hack n Slash

I'm still plodding on with writing the unit tests.  The end is in sight as I've nearly finished the instructions and I think I should be able to output tests a bit quicker when I haven't got to keep calculating opcodes by hand.

Unfortunately, last week I went an bought a copy of Fable II.  What a time sink that has been, and I would've finished the tests by now if it wasn't for that.  Cracking good game though.

Once the tests are complete the next step is to write a monitor/debugger application to wrap the CPU up in.  I want to be able to step through the emulated code and set breakpoints etc.  This will no doubt involve quite a bit of effort but is going to be crucial in keeping me sane as this project progresses.  Once I'm happy that I can accurately emulate the CPU and monitor the code running on it, I can start thinking about turning it into an Amiga.

Of course, I'm making a big assumption that the performance of my code is going to be adequate for the job, but that's a whole new kettle of fish that we'll have to wait for.  I'm just concentrating on developing a clean and robust model for now.