descriptionChip-8 emulator written in C99 using SDL2
owneralessio.chiapperini@nullbuffer.com
last changeFri, 1 Apr 2022 16:49:21 +0000 (1 18:49 +0200)
content tags
add:
README.md

CHIP-8 logo

c8emul

CHIP-8 emulator implemented in C99 using the SDL2 multimedia library. It implements all the opcodes of a standard CHIP-8 but without sound.

Features

Limitations

Build dependencies

Other than SDL2, the only other dependency is a toolchain supporting the following flags:

CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic \
        -Walloca -Wcast-qual -Wconversion -Wformat=2 -Wformat-security \
        -Wnull-dereference -Wstack-protector -Wvla -Warray-bounds \
        -Wbad-function-cast -Wconversion -Wshadow -Wstrict-overflow=4 -Wundef \
        -Wstrict-prototypes -Wswitch-default -Wfloat-equal \
        -Wpointer-arith -Wswitch-enum \
        -D_FORTIFY_SOURCE=2 \
        `sdl2-config --cflags` \
        -fstack-protector-strong -fPIE -fstack-clash-protection

LDFLAGS = -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-z,separate-code

Otherwise you can just remove the security flags and compile it with

CFLAGS = -std=c99 -O2 -Wall -Wextra -Wpedantic `sdl2-config --cflags`
LDFLAGS =

or pass your own flags to make

make CC=gcc CFLAGS=... LDFLAGS=...

Installation

Clone this repository then

$ make PREFIX=/usr install

This will install the compiled binary under PREFIX (/usr/bin) in this case, if not specified PREFIX will default to /usr/local. For staged installs, DESTDIR is also supported.

Usage

c8emul receives as input a ROM file and executes it displaying the output in a window of default size 64x32 and with a delay between each cycle of 3ms. The ROM file however, can be omitted, in this case the program takes the input from the standard input until EOF or ^D is reached.

The options are as follows:

Examples

Load ROM from stdin and display it in 640x320 with the default 3ms cycle delay:

$ c8emul -s 10

Load ROM from file and scale the window to 640x320 with a 2ms cycle delay:

$ c8emul -s 10 -d 2 Chip8_Picture.ch8

Test suite

The test suite consists of a series of unit tests, one for each opcode (excluding Cxkk and Dxyn) and for the intialization of the emulator. The suite is contained in the test folder. It's output is similar to googletest's and it can be invoked with make check which, if everything is working should output something similar to

./tests
[----------] Test environment set-up.
[==========] Running test cases.
[ RUN      ] PC set to 0x200
[       OK ] PC set to 0x200
[ RUN      ] Font is loaded
[       OK ] Font is loaded
[ RUN      ] 00E0: display cleared
[       OK ] 00E0: display cleared
[ RUN      ] 00EE: RET from subroutine
[       OK ] 00EE: RET from subroutine
[ RUN      ] 1123: JMP to location 0x123
[       OK ] 1123: JMP to location 0x123
[ RUN      ] 2456: call subroutine at addr 0x456
[       OK ] 2456: call subroutine at addr 0x456
[ RUN      ] 3879: skip next instruction, V8 = 0x79
[       OK ] 3879: skip next instruction, V8 = 0x79
[ RUN      ] 4123: skip next instruction, V1 != 0x23
[       OK ] 4123: skip next instruction, V1 != 0x23
[ RUN      ] 5210: skip next instruction, V2 = V1
[       OK ] 5210: skip next instruction, V2 = V1
[ RUN      ] 6456: set V4 = 0x56
[       OK ] 6456: set V4 = 0x56
[ RUN      ] 7789: set V7 = 0x89
[       OK ] 7789: set V7 = 0x89
[ RUN      ] 8980: set V9 = V8
[       OK ] 8980: set V9 = V8
[ RUN      ] 8981: set V9 = V9 OR V8
[       OK ] 8981: set V9 = V9 OR V8
[ RUN      ] 8982: set V9 = V9 AND V8
[       OK ] 8982: set V9 = V9 AND V8
[ RUN      ] 8983: set V9 = V9 XOR V8
[       OK ] 8983: set V9 = V9 XOR V8
[ RUN      ] 8984: set V9 = V9 + V8, VF = carry
[       OK ] 8984: set V9 = V9 + V8, VF = carry
[ RUN      ] 8985: set V9 = V9 - V8, VF = not borrow
[       OK ] 8985: set V9 = V9 - V8, VF = not borrow
[ RUN      ] 8986: set V9 = V9 SHR 1
[       OK ] 8986: set V9 = V9 SHR 1
[ RUN      ] 8987: set V9 = V8 - V9, VF = not borrow
[       OK ] 8987: set V9 = V8 - V9, VF = not borrow
[ RUN      ] 898E: set V9 = V9 SHL 1
[       OK ] 898E: set V9 = V9 SHL 1
[ RUN      ] 9120: skip next instruction, V1 != V2
[       OK ] 9120: skip next instruction, V1 != V2
[ RUN      ] A123: set I to 0x123
[       OK ] A123: set I to 0x123
[ RUN      ] B345: jump to location 0x345 + 0x12 (V0)
[       OK ] B345: jump to location 0x345 + 0x12 (V0)
[ RUN      ] E69E: skip next instruction, key with value of V6 is pressed
[       OK ] E69E: skip next instruction, key with value of V6 is pressed
[ RUN      ] E1A1: skip next instruction, key with value of V1 is not pressed
[       OK ] E1A1: skip next instruction, key with value of V1 is not pressed
[ RUN      ] F507: set V5 to delay timer value
[       OK ] F507: set V5 to delay timer value
[ RUN      ] F20A: key 'x' is pressed, V2 = 0
[       OK ] F20A: key 'x' is pressed, V2 = 0
[ RUN      ] F515: set delay timer = V5
[       OK ] F515: set delay timer = V5
[ RUN      ] F718: set sound timer = V7
[       OK ] F718: set sound timer = V7
[ RUN      ] F01E: set I = I + V0
[       OK ] F01E: set I = I + V0
[ RUN      ] F929: set I to location of sprite of '2'
[       OK ] F929: set I to location of sprite of '2'
[ RUN      ] F333: store BCD representation of V3 in memory locations I, I+1, I+2
[       OK ] F333: store BCD representation of V3 in memory locations I, I+1, I+2
[ RUN      ] F255: store registers V0-V2 in memory starting from location I
[       OK ] F255: store registers V0-V2 in memory starting from location I
[ RUN      ] F165: read registers V0-V1 in memory starting from location I
[       OK ] F165: read registers V0-V1 in memory starting from location I
[==========] 34 test cases ran.
[  PASSED  ] 34 tests.
[  FAILED  ] 0 tests.
[----------] Test environment teardown.

Static analysis

Static analysis on the code base is done by using clang's static analyzer run through scan-build.sh which wraps the scan-build utility. The checkers used are part of the Experimental Checkers (aka alpha checkers):

Contributing

Send patches on the mailing list, report bugs on the issue tracker.

License

BSD 2-Clause FreeBSD License, see LICENSE.

shortlog
2022-04-01 Alessio ChiapperiniUpdate mailing listmaster
2021-12-03 Alessio ChiapperiniAdd Contributing and License sections in README.md
2021-11-17 Alessio ChiapperiniClarify command for running unit tests
2021-11-17 Alessio ChiapperiniCite SDL2 as dependency in README.md
2021-11-16 Alessio ChiapperiniFix spacing of error codes in usage string
2021-11-16 Alessio ChiapperiniAdd README.md
2021-11-16 Alessio ChiapperiniAdd man page
2021-11-16 Alessio ChiapperiniFix usage string
2021-11-16 Alessio ChiapperiniAdd opcode number to each test status string
2021-11-16 Alessio ChiapperiniAdd scan-build.sh wrapper
2021-11-16 Alessio ChiapperiniUse common (gcc/clang) security flags
2021-11-14 Alessio ChiapperiniUpdate license headers to conform BSD's 2-clause
2021-11-13 Alessio ChiapperiniAdd unit tests for nibbles F
2021-11-10 Alessio ChiapperiniAdd testcases for nibbles E
2021-11-10 Alessio ChiapperiniUse delay and scale factor from cmdline parameters
2021-11-10 Alessio ChiapperiniChange delay cmd-line parameter to unsigned
...
heads
2 years ago master