-
Notifications
You must be signed in to change notification settings - Fork 0
Description
I found this gem while looking for something completely different on cosmacelf.com. It is a nice project, and a very different take on the topic, so first of all welcome to the CHIP-8 world!
I had a quick look over the CHIP-8 interpreter and found various issues. A bunch of them might be connected to the use of Cowgod's technical reference and I made an errata for that: https://github.com/gulrak/cadmium/wiki/CTR-Errata
The main issue of the 8xyn opcodes is, that VF is set before Vx, but x could be 15, so the assignments could be in conflict. For that case the result of the opcodes must be the VF result (so 0 or 1) not the math result from Vx.
The flags errors can also be found with the 4-flags.ch8 test program from the very good CHIP-8 test suite by Timendus (https://github.com/Timendus/chip8-test-suite) that comes with an excellent readme.
Besides that, the key opcodes Ex9E/ExA1 do something like this:
x = (instruction&0x0F00)>>8;
if (keydown[x]!=0) {This seems to use x as the key number, but the opcodes are expected to use the lower 4bit of Vx, so more like:
x = (instruction&0x0F00)>>8;
if (keydown[V[x] & 0xF]!=0) {The masking is not only protecting from array-out-of-bounds access in case Vx is greater than 15, but is actual the expected behavior, and that is valid for original CHIP-8 as well as it's 90s revivals on the HP-48 (like SuperCHIP).
Btw, e.g. the integrated Invaders (by David Winter), apart from fixing the key opcodes, expects the SuperCHIP shift quirk. Quirks are little differences (mainly because of misunderstandings and sub-par documentation) in various CHIP-8 variants and the shift quirk is about 8xy6/8xyE just shifting Vx instead of using Vy. The y parameter is simply ignored.
Also, the Dxyn, the sprite drawing, is implemented with what is called the wrapping quirk, that is, it wraps all pixels that would fall outside the left/lower border. That is not how original CHIP-8 works, instead it only wraps the initial position, so the drawing starts at xpos = V[x] % num_cols and ypos = V[y] % num_rows and any subsequent pixels that would be outside the right or lower border are simply not drawn. This makes it necessary to use temps for vx and vy, as the register themselves should not be changed. Wrapping came only later with variants like XO-CHIP (in Octo, another Javascript IDE for CHIP-8 at https://johnearnest.github.io/Octo).
I See Fx0A is not implemented yet. Be aware, that contrary to some documentations it should be waiting for a key to be released, not pressed, and there are games/programs using Fx0A back to back with more key opcodes that will fail if the key returned by Fx0A is still pressed. Often Fx0A is implemented by decrementing the PC (or in your case not incrementing) if the conditions are not met and thus letting the program re-execute the opcode until that happened.
I can't say if that is all, and Javascript is not my strongest language, but fixing these should enhance the compatibility of the implementation.
As another resource for the opcode differences of a bunch of CHIP-8 variants I made this little reference opcode table that might come in handy: https://chip8.gulrak.net - Opcodes makes with a yellowish background are influenced by quirks or show different behavior on different variants. It's not a perfect replacement of opcode description as I kept the descriptions brief, but might still help.