jamesgriffin / chip-8-emulator Goto Github PK
View Code? Open in Web Editor NEWA CHIP-8 emulator in C++
License: GNU General Public License v2.0
A CHIP-8 emulator in C++
License: GNU General Public License v2.0
While working on my own emulator I implemented unit tests for the basic opcodes to avoid breaking things when working on it. I wanted to verify my tests by letting other implementations run against them, and as yours was among the candidates I tried, I wanted to give you the findings from it. I don't claim this is the only way to see these commands, but my tests are written quirk agnostic (e.g. testing shift opcodes only with X == Y
, so the type of shift implemented doesn't matter), so the results should be the same for any conforming CHIP-8. For reference I also tried the well established Octo with the C version c-octo against my suite and among others it passes all tests.
VF
needs to be set after the operation, and the operation can use the same register for both. That seems to break on this implementation as it needs VY
for VF
calculation, and that is gone when X==Y
.
TEST SUITE: BasicOpcodes
TEST CASE: 8xy4 - vx += vy, set vF to 1 on overflow, 0 if not
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 1 == 0 )
logged:
After step #4
COMMENT: v3 += v3, vF should be set as this overflows
PRE: V0:00 V1:33 V2:00 V3:b4 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:00 I:0000 SP:0 PC:0206 O:8334
POST: V0:00 V1:33 V2:00 V3:68 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:00 I:0000 SP:0 PC:0208 O:6f84
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 0 == 1 )
logged:
After step #6
COMMENT: vF += v3, vF is also carry flag, should be cleared
PRE: V0:00 V1:33 V2:00 V3:68 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:84 I:0000 SP:0 PC:020a O:8f34
POST: V0:00 V1:33 V2:00 V3:68 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:01 I:0000 SP:0 PC:020c O:6fda
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 1 == 0 )
logged:
After step #8
COMMENT: vF += v3, vF is also carry flag, should be set
PRE: V0:00 V1:33 V2:00 V3:68 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:da I:0000 SP:0 PC:020e O:8f34
POST: V0:00 V1:33 V2:00 V3:68 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:00 I:0000 SP:0 PC:0210 O:0000
This implementation sets VF
before the operation, overwriting it in case of VF
as the result register.
TEST SUITE: BasicOpcodes
TEST CASE: 8xy5 - vx -= vy, set vF to 0 if underflow, 1 if not
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 1 == 206 )
logged:
After step #6
COMMENT: vF -= v1, vF is also carry flag, should be set to 1 as no underflow
PRE: V0:00 V1:33 V2:00 V3:fe V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:84 I:0000 SP:0 PC:020a O:8f15
POST: V0:00 V1:33 V2:00 V3:fe V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:ce I:0000 SP:0 PC:020c O:6f30
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 0 == 205 )
logged:
After step #8
COMMENT: vF -= v1, vF is also carry flag, should be set to 0, as there is underflow
PRE: V0:00 V1:33 V2:00 V3:fe V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:30 I:0000 SP:0 PC:020e O:8f15
POST: V0:00 V1:33 V2:00 V3:fe V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:cd I:0000 SP:0 PC:0210 O:0000
Wether one implements VX >>= VX
or VX := (VY>>1)
, VF
needs to be set to the shifted out bit after setting VX
.
TEST SUITE: BasicOpcodes
TEST CASE: 8xx6 - vx >>= vx, lost bit in vF, basic shift test is quirk agnostic
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 1 == 0 )
logged:
After step #7
COMMENT: vF >>= vF, vF set to 1
PRE: V0:00 V1:0c V2:00 V3:00 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:83 I:0000 SP:0 PC:020c O:8ff6
POST: V0:00 V1:0c V2:00 V3:00 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:00 I:0000 SP:0 PC:020e O:0000
Also this opcode should set VF
after setting VX so in case of X==F the underflow flag needs to erase the result.
TEST SUITE: BasicOpcodes
TEST CASE: 8xy7 - vx = vy-vx, set vF to 0 if underflow, 1 if not
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 1 == 206 )
logged:
After step #6
COMMENT: vF = v3-vF, vF is also carry flag, should be set to 1 as no underflow
PRE: V0:00 V1:9c V2:00 V3:cf V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:84 I:0000 SP:0 PC:020a O:8f37
POST: V0:00 V1:9c V2:00 V3:cf V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:ce I:0000 SP:0 PC:020c O:6fa0
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 0 == 156 )
logged:
After step #8
COMMENT: vF = v1-vF, vF is also carry flag, should be set to 0, as there is underflow
PRE: V0:00 V1:9c V2:00 V3:cf V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:a0 I:0000 SP:0 PC:020e O:8f17
POST: V0:00 V1:9c V2:00 V3:cf V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:9c I:0000 SP:0 PC:0210 O:0000
Same as 8xy6.
TEST SUITE: BasicOpcodes
TEST CASE: 8xxE - vx <<= vx, lost bit in vF, basic shift test is quirk agnostic
.../test/basic_opcode_tests.cpp:71: ERROR: CHECK( expected.v[0xF] == chip8->getV(0xF) ) is NOT correct!
values: CHECK( 1 == 2 )
logged:
After step #5
COMMENT: vF <<= vF, vF set to 1
PRE: V0:00 V1:88 V2:00 V3:00 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:84 I:0000 SP:0 PC:0208 O:8ffe
POST: V0:00 V1:88 V2:00 V3:00 V4:00 V5:00 V6:00 V7:00 V8:00 V9:00 VA:00 VB:00 VC:00 VD:00 VE:00 VF:02 I:0000 SP:0 PC:020a O:6f43
From my experience I can also recommend the CHIP8-test-suite by Timendus as a way to verify opcode/flag issues as that helped me a lot.
The correct method on choosing a random number should be 0-255 (inclusive). rand() % 0xFF
will not allow 255 to be inclusive. So the code should instead be rand() % 0xFF + 1
case 0xC000:
V[(opcode & 0x0F00) >> 8] = (rand() % 0xFF) & (opcode & 0x00FF);
pc += 2;
break;
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.