Back in the early '80s I was a VIC-20 owner, and got pretty comfortable writing 6502 machine code (also known as Machine Language, or ML). The tools of the day were very primitive by todays' standards, and I ended-up writing my own assembler/disassembler tools to make my life easier. Those tools were better-suited to my requirements than anything else I could find for the VIC at the time (he said modestly) but even so they fell far short of the features offered by similar products available today, such as DASM. Eventually I moved on to other, more powerful machines, and left my 6502 days behind.
Fast-forward to 2001, and I started to re-kindle my lapsed interest in the 6502 when I downloaded and played with Stella, the Atari VCS emulator. After a few months, I realised that there was a thriving community of coders out there actually writing VCS games and other stuff, using DASM or whatever their tool of choice was, and running their code in Stella. That was too tempting to pass up, and in fairly short order I was immersed in the delights of synchronised time-critical video generator code, and having things bouncing around in an emulated VCS on my PC.
Now this particular exercise made something quite apparent - although DASM (which I quickly became a fan of) was massively powerful and extremely pleasant to assemble 6502 code with, it was and is still left to the coder to count instruction cycles when writing time-critical code, and that is error-prone. Just a single clock-cycle out, and your entire VCS game screen turns to rolling garbage because the timing of the instructions dosen't quite fit a scan-line exactly, which means you lose vertical synchronisation, and all you see is junk.
I realised that what I needed was an 'assembling editor' that would automatically tally instruction cycles for me as I wrote the code, and thus make subtle errors in timing quite apparent. Since the 6502 is very well documented, all the instruction timings are readily available, as well as the variations induced by circumstantial conditions - like the fact that a branch takes longer to execute when taken than when not, or that there's sometimes a timing cost associated with crossing a memory page boundary. So having a routine do all the counting, and also accomodating those variations whilst doing it, seemed pretty simple to my mind.
I made a couple of prototypes, but was never quite satisfied - it always seemed to me that there was something vaguely inelegant about writing a basic lookup mechanism and then trying to find rules that would reliably incorporate the myriad variations in timing that can occur as the 6502 executes the instructions. Eventually it dawned on me that the best way to make all this happen would be if the 6502 itself was executing the instructions as you typed them, and reporting back on the actual time it took - naturally including the variations because it would 'really' be running the code in-situ. And that meant that before I could get the editor working, I needed a good 6502 emulation.
And that meant that I needed to write an emulator that would do all the things that any other 6502 emulator does (i.e. execute instructions and reflect register states, etc) but also include things like an open port into which I could feed a single instruction and an environment state and get back a timing value. Sounds simple if you say it fast. ;)
Anyway, this series of blog posts will document from the very beginning my creation of such a 6502 emulator. I'll be hosting the C# sourcecode in Google Code once it's reasonably stable (my code, not Google Code ;)) so if you want, you can tag along and build the thing yourself at the end - and naturally if you see a way to do something better, I hope you'll use the comments facility here to tell me and everyone else about it. No doubt it'll be an entertaining ride as I make progress, break something, reverse, and move forward again; but hopefully I'll end up with something that works, and that I can use in the way I want.
Fast-forward to 2001, and I started to re-kindle my lapsed interest in the 6502 when I downloaded and played with Stella, the Atari VCS emulator. After a few months, I realised that there was a thriving community of coders out there actually writing VCS games and other stuff, using DASM or whatever their tool of choice was, and running their code in Stella. That was too tempting to pass up, and in fairly short order I was immersed in the delights of synchronised time-critical video generator code, and having things bouncing around in an emulated VCS on my PC.
Now this particular exercise made something quite apparent - although DASM (which I quickly became a fan of) was massively powerful and extremely pleasant to assemble 6502 code with, it was and is still left to the coder to count instruction cycles when writing time-critical code, and that is error-prone. Just a single clock-cycle out, and your entire VCS game screen turns to rolling garbage because the timing of the instructions dosen't quite fit a scan-line exactly, which means you lose vertical synchronisation, and all you see is junk.
I realised that what I needed was an 'assembling editor' that would automatically tally instruction cycles for me as I wrote the code, and thus make subtle errors in timing quite apparent. Since the 6502 is very well documented, all the instruction timings are readily available, as well as the variations induced by circumstantial conditions - like the fact that a branch takes longer to execute when taken than when not, or that there's sometimes a timing cost associated with crossing a memory page boundary. So having a routine do all the counting, and also accomodating those variations whilst doing it, seemed pretty simple to my mind.
I made a couple of prototypes, but was never quite satisfied - it always seemed to me that there was something vaguely inelegant about writing a basic lookup mechanism and then trying to find rules that would reliably incorporate the myriad variations in timing that can occur as the 6502 executes the instructions. Eventually it dawned on me that the best way to make all this happen would be if the 6502 itself was executing the instructions as you typed them, and reporting back on the actual time it took - naturally including the variations because it would 'really' be running the code in-situ. And that meant that before I could get the editor working, I needed a good 6502 emulation.
And that meant that I needed to write an emulator that would do all the things that any other 6502 emulator does (i.e. execute instructions and reflect register states, etc) but also include things like an open port into which I could feed a single instruction and an environment state and get back a timing value. Sounds simple if you say it fast. ;)
Anyway, this series of blog posts will document from the very beginning my creation of such a 6502 emulator. I'll be hosting the C# sourcecode in Google Code once it's reasonably stable (my code, not Google Code ;)) so if you want, you can tag along and build the thing yourself at the end - and naturally if you see a way to do something better, I hope you'll use the comments facility here to tell me and everyone else about it. No doubt it'll be an entertaining ride as I make progress, break something, reverse, and move forward again; but hopefully I'll end up with something that works, and that I can use in the way I want.

0 comments:
Post a Comment