Vanity Project: System Emulator
Having played with pico-8 (which I love!), I was wondering about creating an emulated computer system from scratch. I couldn't really figure out what the point would be.
A demonstration system for secondary students? - probably too complicated.
A competitor to pico-8? - just why? pico-8 is awesome.
A replacement for LMC? - probably too complicated.
A nostalgia trip about tinkering with the Commodore 64 back in the day? - maybe.
Just for fun? - ...
Well I eventually accepted the idea that I am actually crazy enough to enjoy putting together a virtual system for no other reason that it might be interesting to try. With that in mind, I chose to do it in C# because I hadn't used MonoDevelop in ages. (Writing a VM which runs inside the .NET VM does feel a little VM-ception though).
I decided to start from a 6502-style instruction set, with Load Immediate and such (although I'll probably pass on the more complicated addressing modes), but I thought I'd make the fundamental unit 32-bit instead of 8. This would make working with floats feasible, as well as increasing the memory-size cap way beyond anything I'd actually need.
The bytecode CPU is simple enough: an array of register values and a giant switch() statement does perfectly fine. Likewise with the memory controller: read that location into this register, etc. I/O devices and the boot sequence though? When it's me making up my own rules, what counts as cheating?
In the interests of future flexibility, I decided to use an interface somewhat similar to the I2C bus in embedded systems. The CPU will have a pair of instructions which can set/get a numbered register on a numbered device.
I then settled on a target of making the simplest possible interface that would allow the machine to be programmed via its own interface. That would need a basic OS with keyboard input, text output and commands to set/display memory values and copy to/from persistent storage.
For some reason, I decided I wanted the system to load a BIOS program first, which would search for some kind of boot sector on a storage device, load code from that sector into memory, then run it. I allowed the BIOS to parse hex from a text file rather than resorting to a hex editor (I'm still not sure how I feel about cutting that corner ;)).
And today's progress means I now have a BIOS program which outputs the word 'blah' to the console via CPU instructions to set registers on a 'ConsoleOutputDevice'.
...
Well, somehow I still feel proud of this. :)
I think the future rules of my facile little game will include: hardware can be implemented in C# but any and all software, interrupt routines, drivers, etc. should be implemented through the system's own interface.
So yeah, that's...a thing.
I definitely feel like I've plumbed new depths of weird...
A demonstration system for secondary students? - probably too complicated.
A competitor to pico-8? - just why? pico-8 is awesome.
A replacement for LMC? - probably too complicated.
A nostalgia trip about tinkering with the Commodore 64 back in the day? - maybe.
Just for fun? - ...
Well I eventually accepted the idea that I am actually crazy enough to enjoy putting together a virtual system for no other reason that it might be interesting to try. With that in mind, I chose to do it in C# because I hadn't used MonoDevelop in ages. (Writing a VM which runs inside the .NET VM does feel a little VM-ception though).
I decided to start from a 6502-style instruction set, with Load Immediate and such (although I'll probably pass on the more complicated addressing modes), but I thought I'd make the fundamental unit 32-bit instead of 8. This would make working with floats feasible, as well as increasing the memory-size cap way beyond anything I'd actually need.
The bytecode CPU is simple enough: an array of register values and a giant switch() statement does perfectly fine. Likewise with the memory controller: read that location into this register, etc. I/O devices and the boot sequence though? When it's me making up my own rules, what counts as cheating?
In the interests of future flexibility, I decided to use an interface somewhat similar to the I2C bus in embedded systems. The CPU will have a pair of instructions which can set/get a numbered register on a numbered device.
I then settled on a target of making the simplest possible interface that would allow the machine to be programmed via its own interface. That would need a basic OS with keyboard input, text output and commands to set/display memory values and copy to/from persistent storage.
For some reason, I decided I wanted the system to load a BIOS program first, which would search for some kind of boot sector on a storage device, load code from that sector into memory, then run it. I allowed the BIOS to parse hex from a text file rather than resorting to a hex editor (I'm still not sure how I feel about cutting that corner ;)).
And today's progress means I now have a BIOS program which outputs the word 'blah' to the console via CPU instructions to set registers on a 'ConsoleOutputDevice'.
...
Well, somehow I still feel proud of this. :)
I think the future rules of my facile little game will include: hardware can be implemented in C# but any and all software, interrupt routines, drivers, etc. should be implemented through the system's own interface.
So yeah, that's...a thing.
I definitely feel like I've plumbed new depths of weird...
Comments
Post a Comment