CHIP-8 emulators inconsistent behavior
CHIP-8 arithmetic behavior and VF variable
I’ve been fiddling with CHIP-8 and writing a sample program in Octo - a CHIP-8 IDE/assembler with a nicer scripting language than raw opcodes.
I wanted to make a demo to try out various opcodes and while doing that found a bug in my CHIP-8 emulator within the arithmetic operations.
The demo (and its source code )
VF as a destination
I’ve encountered a different behavior between my emulator emuchip8 and Octo (which I use as a reference) and got somewhat. Octo implements the >= pseudo-operation as by using the subtraction instructions -= and =- and querying vf - this was broken on my emulator.
Given the following program:
6008
6F20
8F07
What should be the value of vf after the 8F07 opcode executes? (so vf = v0 - vf; vf = 0x08 - 0x20 = 0xe8).
I think it should it be 0 because the borrow flag has a priority over the subtraction result, but several emulators online seem to take the opposite priority (in comparison to Octo) .
The original documentation COSMAC_VIP_Instruction_Manual_1978.pdf (archive.org) says the VF is used for overflow in the arithmetic operations, but I didn’t get around to disassembling the original interpreter :).
So the result should be saved in VX first, then the flag in VF.
VF when vx == vy
In addition, the VF subtraction behavior seems to be wrong in one other edge case as well in these open-source emulators - the original docs say that (for 8XY5): VX = VX - VY (VF= 0 if vx < vx; VF = 1 if vx >= vy).
Again, found emulators online that implements it as:
vf = vx > vy ? 1 : 0;
The code above yields incorrect result in the case when vx equals vy
.
If vx == vy
the result in VF should be 1 according to RCA COSMAC VIP manual. Wikipedia is right as well, specifying that VF is set to 0 when there’s a borrow, and 1 when there isn’t. - there is no borrow when you do 9-9, so it’s not wrong either.
This can be tested with the following ROM :
0x6004 # v0 := 4
0x8005 # v0 -= v0
0xFF29 # set i to sprite 0 or 1 based on the value of vf
0xD005 # should draw sprite of 1