For anyone interested I’ve been working on a Jack VM (16-bit) to run into Octo. When reading the stack source linked from this years jam I got the idea of building my own automated testing suite as well… and this is working out MUCH better than I ever thought… you just add tests cases and they are auto-magically registered with the test runner…
Ref: https://www.nand2tetris.org/
Here is an example of the kind of thing I have working so far:
test "simple add"
vm_start
o_push_constant 1 # 0x80 0x00 0x01
o_push_constant 2 # 0x80 0x00 0x02
o_add # 0x04
vm_stop
pop_into_reg vC # returns a 16 bit value in vC-vD
assert_equal vC 0
assert_equal vD 3
success
;
Note, that vm_start
and stop wire up the VM runner… so o_*
instructions are NOT generating CHIP-8 code, they are generating the binary shown - Jack VM bytecode. The course itself never gets into defining bytecode for the Jack VM - but it wasn’t too hard to conceptualize. And of course we’re adding our own opcodes as well so that we still have low-level access to things like clear
, etc… The Jack VM is stack based, so our opcodes vary from 1-4 bytes (mostly 1 or 2). With things like function dispatch being the most complex and ops like add
being a single byte.
vm_start
preserves the address, pushes the org forward 2 bytes (to save room to a jump we’ll insert later to skip over the VM code and jump past vm_stop
… then vm_stop
inserts a o_halt
opcode (that instructs the VM to stop and return) and then sets the VM’s PC to the start of the mini-program and then boots it. Oh, it also quickly goes back and adds the jump now that we know where we need to jump TO.
So now each time a test hits a VM block the VM fires up, runs the code, and then we test the results to verify correctness. And of course there will be a tiny little UI for this as well.
The overall idea is we fit the VM engine into the first 4.25kb of RAM (we have a jump opcode table at the end of 4k for opcode dispatch) and then that leaves 60kb or so for program code (since it’s now abstracted by the VM). Right now I have most of the Jack “basic” opcodes implemented (other than flow control) along-side my test suite and I’m sitting at 2.6kb of low RAM used - so I think this doable.
I still need to figure out:
- delay
- sound
- inputs (memory mapped?)
- sprites
Step two would be writing (or repurposing) a Jack compiler in JavaScript to generate Octo flavored Jack bytecode… even better would be pairing it with an editor so all this was available on a simple web page where you could write a Jack program, compile it, paste it into Octo and run it. :-) A “compiled” program would just be a blob of binary/data + the VM runtime.
If anyone is interested (or wants to help) I’d be happy to share more or answer questions.