Sunday, August 10, 2008

Slow going....

I've not been doing much on the debugger as I've been busy with real life, but I did get some time today to mess around. I've been updating the plugin system to make it more flexible and so that I can do some work on the command line arguments system. Currently I can specify which modules I want to use on the command line (along with symbol table loader and symbol file), and the next step is to spawn a monitor window using the selected modules.

I've rearranged all code so that multiple monitor windows are possible, in theory this will allow debugging of secondard CPU modules as long as the debugging stub or interface supports it - although thats a long way off yet.

Thursday, August 07, 2008

Future plans....

There was a question about using the RR-NET instead of the serial port, so I thought I'd answer in depth here.....

Currently I'm debugging via the user port on a Commodore Plus/4 and the parallel port on the PC, but the plan is to then do two C64 versions using both the userport AND the RR-NET (since the RR-NET is far easier to get a hold of). However the user port version would allow you to develop more hardware as you can't always use RR-NET if your trying to develop for a bit of hardware where theres no passthrough, or it's simply not available (The current cart disables the pass through when in use.)

That said, for normal apps and games, I hope the MMC64/RR-NET (and the MMC Replay) will be invaluable for getting things working on real hardware. Theres nothing quite like debugging on a real machine, particually if you are using the MMC64 file loader stuff I did in the framework, as thats currently impossible to develop with via an emulator. Of course someone could also implement a SilverSurfer stub as well - nothing to stop them!

In between these versions (probably at the same time as the RR-NET version), I'll write my first emulator plugin and get Minus4 working using it. This will then be given away for everyone to use. I then hope that new modules will start popping up as all the hard work should be done, and emulators should just be able to plug it in. Once we have some simple CPU types (Z80, 6502 etc.) then all an emulator should have to do is implement the STUB and it'll all magically work.

The idea is to give away the source to the 6502 module, the COMMS modules, all the STUBS that I end up doing, and the Symbol table module. This should allow you to write whatever system you want, without having to implement all the crap around it that makes up the debugger - in theory. It also means you can easily adapt modules for your own use; so the 6502 one could be changed to be a 65816 one, or a 65c02 etc. allowing for new machines like the SNES or PC Engine to be added easily.

Lastly.... if theres ever any real problems with getting a particular machine to work using the interface provided, then all you need to do is put both modules in the same DLL (comms and cpu) then you can add extra interfaces to expand or alter the behaviour. Lets say you couldn't implement single stepping in the way thats assumed you would, then you can add a new comms command that only YOUR cpu module knows about and call it instead.

Thats the theory......

Wednesday, August 06, 2008

Bingo!!

I've now fixed the tracing system so I can trace without a problem. I managed to single step through quite a bit of XeO3 which is a good sign. It appears to be pretty solid, I can stop/start and trace without any issue now - which is great. That means I have the core functionality now needed to progress. The current CPU and COMMS interface does have an issue however.... Single stepping on the spectrum (a 48k one at anyrate) isn't easy, and in order to make it better you really need to get the target to execute the single step so it can do it best for itself. However, getting the stub to do that takes quite a bit of memory and I dont want that, so I need to think about it a little longer....

Almost there!

I've now got things almost working, single stepping is rock solid and I now have the RTS instruction being simulated fine. There appears to be a slight glitch where on a specific instruction in XeO3 it doesn't step properly but jumps off to $FFFF for some reason - no idea why as yet. While I'm trying to figure this out I'll start adding breakpoints to the interface and then get the symbol table loaded.

I suddenly realised that I shouldn't be passing the an interface top the symbol table to the CPU model, but an interface to an expression evaluation module. This means the CPU code could evaluate expressions if it needs to, and that leaves me to deal with symbol table lookups inside the expression evaluation without having to worry about it. You'll still be able to write your own symbol table so that you can load funny symbol file formats, and you'll still be able to query for symbols but this time it'll go through the evaluation system instead.

I'll pinch the expression stuff from SNasm and put an interface around it, this means it'll handle anything SNasm could (which was a lot!). It also means that watches (with their complex expressions) should be a breeze to process, all I need to do is add the new [..] context to get memory from the target. Should be fun when its all working! I'm still not sure how fast its all gonna run, as getting lots of memory over a parallel cable isn't quick, still emulators should be very fast and at least you'll be using a common interface then!

I also realised that each module (ICPU, ISymbolTable and IComms) needs to be able to change some options, so I'll add a new interface that means it can pop up an options box and allow you to change things. For example, the CPU module might allow you to enable undocumented opcodes which aren't on by default.

So there you go! Its going pretty well so far! Once I get it to a basic level, I'll need to see if I can get some other coders to try it out and give me some feedback. of course, having only SNasm labels might hinder things a little, but then again it would be a good opportunity to have someone else write a module and tell me how easy or hard it was!

Monday, August 04, 2008

Step, Step, Pause, Step step, step step

I didn't get much done tonight, but single stepping is a lot more stable now. I've updated the window update so that it doesn't request the current view every time you single step. This obviously won't work for self-modifying code, but for now it makes it much quicker to single step. I'm trying to get the RTS instruction to work but the register update doesn't appear to be working yet. The idea is to simulate RTS and RTI (and possibly JSR, JMP and all the branches) but this involves updating the registers to their new values.

I'll need to clean the monitor code up once its all working, as its getting a little messy just now. Also I'm still having trouble debugging this code as devstudio doesn't appear to want to load the symbols for all the modules its loaded....very annoying!

Sunday, August 03, 2008

Squeezing it all in.

Now that things are working better I've started to try and squeeze it all down a little. It's not finished by any means, but I think it's at a reasonable stage where I can start to think about the memory foot print. The inital goal was to have the stub take up around 1k, but I now have it down to under 0.5k which is great news. I'm sure there's going to be more added to it, but its pretty complete for now. As a default setup, I've put the debug variables on the unused bits of the stack ($100 to $138) which is usually free - although since I'll give away the source - you can put it where you like. I only use 5 bytes of zero page $FA-$FF so as along as you avoid these locations, all should be well.

I've made pretty good progress today, and while tracing still isn't finished (still jumps off into the wilds now and then), it's now progressing nicely. I'll fix up JSRs, RTSs, RTIs and branches tomorrow night if I get time, then I can move on to making the dissassembly window nicer along with a user controlable BAR for scrolling the view around, and then start on the symbol table and displaying a proper symbolic dissassembly.

AT LAST!!!!

I've finally figured out what I was doing wrong...what a twat! Okay, so in the old remote debugger I hadn't delt with the +2 of the BRK instruction and I have here, so that wasn't it this time around. I was begining to think the 7501 was slightly different from the 6502 and all the docs I had would be wrong for it, but no. The REAL reason was far simpler..... I had 2 interrupt routines.

Now I figered you only need to check for a debugger in one of them since its only checking comms and waiting a frame there doesn't matter, but the more I tested this BRK thing, the more confusing it became.

I was able to make a test where it was out right ignoring BRK instructions! I simply couldn't figure that out, that is until I realised you need to call the debug stub EVERY interrupt so it can ALSO check for BRK instructions. Otherwise it'll just exit the IRQ and carry on like nothing happened.

So, that really annoying bug fixed, and I can now single step/run/stop in a rock solid manner - at last! Now I need to emulate RTS and RTI instructions so that the debugger works properly, and I'll probably emulate branches as well since it means I only need one breakpoint. Although I'll allow RTI via the monitor, you wont't be able to debug interrupts, this is just for emulator support as it WILL be able to debug interrupts. Because a real machine uses BRK's for breakpoints, its stub is inside an interrupt, but emulators dont have to do that, they can single step anywhere and dont need to write BRK's, they can just have a breakpoint table and check to the current PC which makes them very powerful.

I have to say I'm relieved, it was starting to get to me. I usually don't spend long on bugs, but this one was pushing it.... Still, all fixed and now we can really push on with some monitor features! It'll be great to get real watches and multiple memory windows without having to do to much. The comm's speed will probably hurt the update of watch windows, but we can probably put in a bit of smarts and a FORCE UPDATE button or something to help. Watches are probably the most powerful thing I've missed as you can ask for a variable and tell it the type and number of entrys you want displayed. i.e.

DestAdd,w:        $2881
SrcTable,w,3: $8002, $8100, $8132
SpriteData,64: $00,$01,$02,$03,$04....(up to 64 bytes)
[Temp,w]+y,5: $10,$22,$44,$86,$00


The other great thing about watches is that you only get the memory you need, not a whole memory window just to watch a single byte! You'll also notice I hope to do expression evaluation like "[Temp,w]+Y". This would get the word contents of Temp and add on the Y - or something like this. this is of course way down the line, but features like this will come, and everyone that uses the STUB interface will benifit without having to do it themselves.

Progress? Who knows....

Here's another little test app and this one's pretty simple, but it does show up the flaw.
58C9  CE 15 FF      dec $FF15
58CC EA nop
58CD EA nop
58D0 00 brk
58D1 EA nop
58D4 EA nop
58D5 4C C9 58 jmp $58C9

Now on entry to the debugger I adjust the stack to point to the BRK instruction so that we know exactly where its stopped. This works fine. But on exit I expect it to re-execute the BRK and not do anything, however this one does not. When I run it again the screen colour changes, and its not supposed to. I suspect this is the problem, BRK's are not being restarted properly, but at least now I have a test case, I should manage to fix it easily enough - I think.

Saturday, August 02, 2008

Trouble ahead.

I really am struggling with getting this thing to single step properly, its a nightmare! The actual monitor code is pretty easy but I think I have something wrong on the stub end that means its just now working right. I have a single breakpoint that I place after the current instruction (lets ignore branchs and calls just now), and I then resume execution. The idea being that it runs a single instruction and hits the new breakpoint (however its been implemented) and jumps back into the debugger again.

The problem is, its just not working like that. Now RUN and STOP work great, so I know jumping in and out the debugger is fine, and I have tested BRK instructions as well and they are okay too. Whenever I hit a break I subtract 2 off the PC (as its moved on entry to the interrupt routine), and I can then resume again.

So far so good.... but if I drop in some more BRK's, they don't seem to be getting hit properly at all. I can't of course debug the stub either so I'm left with just looking at code. I suspect I'll need to start a new, simple project to try and figure out why its not working, as staring at code doesn't seem to help.

So heres the loop Im trying to debug, and its interesting coz aside from not doing much, it shows up several issues.
58D1 CE 15 FF    dec $FF15
58D4 A9 01 lda #$01
58D6 A2 02 ldx #$02
58D8 A0 03 ldy #$03
58DA EA nop
58DB CA dex
58DC D0 FC bne $58DA
58DE B9 00 10 lda $1000,y
58E1 88 dey
58E2 4C D1 58 jmp $58D1


First, if I try and single step $58DA, the whole thing dies a horrible death. IF I try and step $58D6, then $FF15 is increased and Y is decreased to 1 (which is impossible).

Its all very odd, but there must be a logical solution - somewhere!

Friday, August 01, 2008

New we're getting some where!


So with most of the ground work done I've now managed to get registers from the client and can dissassemble the current view (as shown). I'm using a rich text box (after some head scratching) and it appears to work fine. I have a stack of new interfaces and classes that people will use to write their own debugging aids, and Russell says he wants to do a Z80 one and plug it into my noddy spectrum emulator. (which I had forgotten all about). This means when I get the basic one going, he's going to write a TCP/IP (or UDP) version and that can be given away free for folk to include in their own code. These stubs will be in C++ so most emulators should be able to use them.

I did start to port my spectrum emulator over to C# but never got around to finishing it - perhaps something to do on my next holiday.....

So the current state of play is I can stop the target, run it again, and get its registers and a dissassembly view of it. Next I need to be able to STEP an instruction, and then things will get really interesting! While you're using a PC to debug the Plus/4, its easy to forget that it's a slow beasty and the more watches, memory windows and the like you have, the slower its going to go! downloading all that memory will take time! So if its too slow, closing a memory window will probably speed things up quite a bit!

The debugger is also designed so that one day I can add source level debugging as well. This means you can step through your actual source code and not just some abstract view. It also means you'll get all your comments while stepping and viewing code. This will be pretty cool indeed. Minus4Dos actually did this. It was the last feature I added before stopping its development, and it was pretty cool so I'm looking forward to getting that feature back. I'll need to expand SNasm's output support so that it does index files which will eventually enable me to do this, but that should be pretty easy....