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!
Monday, August 04, 2008
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.
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.
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.
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.
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.
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.
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!
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....
Wednesday, July 30, 2008
Slow going....
You know C# is great and all, and you do code things faster, but the ground work reall does take some time to lay. I've found this at work as well where I use C# all the time, it just takes longer. When we started out current project it took us much longer than we thought it would to get the base application framework running. Of course once thats done you really do go quicker, and a few things are quicker right off the bat! I implemented a symbol table last night using my ISymbolTable interface, and using a few Dictionarys I was able to write it in about 15 minuets. In the past I've had to do a binary tree so I can do symbol lookups quickly, but Dictionarys in C# are very quick so I just dont have to worry about it.
I've also been slowly adding the basic 6502 dissassembler while at the same time trying to make it more C# than all the last versions. I've more or less just cut-and-pasted if from the old version (which is the same one I've been using since Minus4 DOS days!), so I want to make it a little prettier.
I decided a little while back that I just dont want to use C/C++ anymore unless i really have to, as C# and managed code is just so much nicer. I'm stuck with things like SNASM and Minus4 of course because they are pretty old and would be a major task to rewrite, and thats not something I want to do just now.
Anyways..... I'm slowly laying all the groundwork and I'm almost ready to start dissassembling stuff to the screen. Once I have that then steppng code will be the next big thing, but that appears to be a long way off for now. I'm actually looking forward to adding support for this to minus4 since while the debugger in Minus4 is actually one of the best in emulators, its still pretty poor. Also, once I have the module to do tracing in Minus4, I'll release that and see if i can't get someone to implement it in VICE and YAPE which would make my day.
(I also secretly hope that I can do a PC Engine module and get it added to Magic Engine, and possibly do a proper remote debugger for the real hardware too - one day!)
I've also been slowly adding the basic 6502 dissassembler while at the same time trying to make it more C# than all the last versions. I've more or less just cut-and-pasted if from the old version (which is the same one I've been using since Minus4 DOS days!), so I want to make it a little prettier.
I decided a little while back that I just dont want to use C/C++ anymore unless i really have to, as C# and managed code is just so much nicer. I'm stuck with things like SNASM and Minus4 of course because they are pretty old and would be a major task to rewrite, and thats not something I want to do just now.
Anyways..... I'm slowly laying all the groundwork and I'm almost ready to start dissassembling stuff to the screen. Once I have that then steppng code will be the next big thing, but that appears to be a long way off for now. I'm actually looking forward to adding support for this to minus4 since while the debugger in Minus4 is actually one of the best in emulators, its still pretty poor. Also, once I have the module to do tracing in Minus4, I'll release that and see if i can't get someone to implement it in VICE and YAPE which would make my day.
(I also secretly hope that I can do a PC Engine module and get it added to Magic Engine, and possibly do a proper remote debugger for the real hardware too - one day!)
Monday, July 28, 2008
Debugger plugins
I've now got the debugger loading both CPU and COMMS plugins and have added a new ISymbolTable interface to deal with multiple symbol table formats. The idea obviously being that you can select different symbol table file formats that are independent of the CPU and COMMS control systems.
I've been thinking about the interface needed to both the comms and the cpu modules and I think a simplistic interface will work. I'll expand the CPU model to deal with breakpoints instead of the debugger just write break instructions, this does mean there will be an upper limit to breakpoints, something I didn't have to worry about before. Still, the monitor only has to have 2 for effective debugging, although MIPS debugging with a delay slot would be.... interesting. :)
I've also had to make an interface DLL rather than just have the .EXE hold everything, otherwise development would be difficult due to circular dependancies. However, its not amazingly important - just annoying.
I've been thinking about the interface needed to both the comms and the cpu modules and I think a simplistic interface will work. I'll expand the CPU model to deal with breakpoints instead of the debugger just write break instructions, this does mean there will be an upper limit to breakpoints, something I didn't have to worry about before. Still, the monitor only has to have 2 for effective debugging, although MIPS debugging with a delay slot would be.... interesting. :)
I've also had to make an interface DLL rather than just have the .EXE hold everything, otherwise development would be difficult due to circular dependancies. However, its not amazingly important - just annoying.
Sunday, July 27, 2008
Debugging....
Its just occured to me that if I modularise this debugger then it could be even more useful than just talking to a debug stub on a remote machine. If I have a UDP connection (keeping it as simple as possible), then theres nothing to really stop emulators adding this simple functionality either. Now I've been fed up with emulator debuggers for ages, all ofthem are rubbish and even Minus4's has quite a few issues due to the way I'd initially implemented it. So imagine doing a simple API where you can either write your own comms connection, OR implement a simple Serial/UDP stub on a remote machine or emulator and suddenly everyone could use this as a front end debugger to their own projects.
Now, I susupect it will take some time to get that API correct so it works across so many differnt machines/platforms but in the end it should be kind-of like DevStudio. It can plug into any system and do full debugging on it. As long as the debugger has a CPU plugin (starting with 6502), it can get a query for various high level things like get dissassembly (which could also return a source level view I guess), Step/Trace, Run, Stop, Get/Set Registers, Get/Set Memory, Get/Set breakpoints and all the rest - then it should be possible to make it completely modular.
I'll have to give this some thought as I carry on writing the new version.....
Now, I susupect it will take some time to get that API correct so it works across so many differnt machines/platforms but in the end it should be kind-of like DevStudio. It can plug into any system and do full debugging on it. As long as the debugger has a CPU plugin (starting with 6502), it can get a query for various high level things like get dissassembly (which could also return a source level view I guess), Step/Trace, Run, Stop, Get/Set Registers, Get/Set Memory, Get/Set breakpoints and all the rest - then it should be possible to make it completely modular.
I'll have to give this some thought as I carry on writing the new version.....
Saturday, July 26, 2008
Proper Remote Debugging
I've decided to continue my remote debugger I started ages ago with the view to gettting it up and running on the Plus4 and C64. I had to look around to try and find the source to the bugger but I eventually found it and was shocked to discover that it was in C++ and not in C#; bugger. This means I'll now have to rewrite most of it so that I can get it into a much easier to maintain format. Bugger.That aside, I have also been looking at the actual debug stub on the plus4 side and its a bit ugly to say the least. I've decided to get it into a much simpler form so that its easy to get into a game. This involves jumping through a coulple of hoops but I've now (mostly) got it running inside XeO3. All I now need to add is a call at the very start of an interrupt routine to the debug stub and it handles the rest. Theres currently a problem with tracing as it doesn't appear to keep registers in sync but I can stop/start the game and try and single step. The image here shows what happens when I click the STOP button. Now once I rewrite all this stuff into C# I'll add symbols etc. so that its easier to use, then I'll try and get it working on the C64.
This may seem like a bit of a departure but theres a couple of very good reasons. First when coding the MMC file loader it was a NIGHTMARE to debug as no emulator current emulates the MMC hardware (pitty), and means that writing code for real hardware becomes much simpler. Secondly it means I can extend it and actually debug SuperCPU code which nothing emulates currently. This is another major advantage and again helps speed up development hugely. I've lost count of the time I've lost because all I could do was change the border colour, or print a hex number when things go wrong,
Now this is likely to take some time to write (and port) but I expect it to be time well spent, and I'll then release the debugger and debug stub to everyone else. For the time being I'll carry on using the user port (since it allows you to program the SCPU or MMC etc.) but at somepoint I will try and allow the RR-NET as well in case you want to debug code for the user port! As a little side note.... If I can create a Plus4 ClockPort, it means I could use the RRNET on that as well, and that would let me do an MMC card on the USER PORT, which is so simple its not funny! Since the Plus4 has ROM space internally, you could supply a userport MMC card and a ROM for all basic functionality without any real problems!
So..first things first.... Get the debugger into a workable state.....
Subscribe to:
Comments (Atom)