diff --git a/.cproject b/.cproject
new file mode 100644
index 0000000..e0a85ca
--- /dev/null
+++ b/.cproject
@@ -0,0 +1,234 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.directory b/.directory
new file mode 100644
index 0000000..83ab9e3
--- /dev/null
+++ b/.directory
@@ -0,0 +1,3 @@
+[Dolphin]
+Timestamp=2019,11,27,21,50,31
+Version=4
diff --git a/.project b/.project
new file mode 100644
index 0000000..51f0265
--- /dev/null
+++ b/.project
@@ -0,0 +1,26 @@
+
+
+ CHIP8-EMU
+
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.genmakebuilder
+ clean,full,incremental,
+
+
+
+
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
+ full,incremental,
+
+
+
+
+
+ org.eclipse.cdt.core.cnature
+ org.eclipse.cdt.managedbuilder.core.managedBuildNature
+ org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
+
+
diff --git a/.settings/language.settings.xml b/.settings/language.settings.xml
new file mode 100644
index 0000000..be97d5f
--- /dev/null
+++ b/.settings/language.settings.xml
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Debug/CHIP8-EMU b/Debug/CHIP8-EMU
new file mode 100755
index 0000000..6c3eaad
Binary files /dev/null and b/Debug/CHIP8-EMU differ
diff --git a/Debug/makefile b/Debug/makefile
new file mode 100644
index 0000000..4c7abef
--- /dev/null
+++ b/Debug/makefile
@@ -0,0 +1,43 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+-include ../makefile.init
+
+RM := rm -rf
+
+# All of the sources participating in the build are defined here
+-include sources.mk
+-include src/subdir.mk
+-include subdir.mk
+-include objects.mk
+
+ifneq ($(MAKECMDGOALS),clean)
+ifneq ($(strip $(C_DEPS)),)
+-include $(C_DEPS)
+endif
+endif
+
+-include ../makefile.defs
+
+# Add inputs and outputs from these tool invocations to the build variables
+
+# All Target
+all: CHIP8-EMU
+
+# Tool invocations
+CHIP8-EMU: $(OBJS) $(USER_OBJS)
+ @echo 'Building target: $@'
+ @echo 'Invoking: GCC C Linker'
+ gcc -o "CHIP8-EMU" $(OBJS) $(USER_OBJS) $(LIBS)
+ @echo 'Finished building target: $@'
+ @echo ' '
+
+# Other Targets
+clean:
+ -$(RM) $(EXECUTABLES)$(OBJS)$(C_DEPS) CHIP8-EMU
+ -@echo ' '
+
+.PHONY: all clean dependents
+
+-include ../makefile.targets
diff --git a/Debug/objects.mk b/Debug/objects.mk
new file mode 100644
index 0000000..54b7836
--- /dev/null
+++ b/Debug/objects.mk
@@ -0,0 +1,8 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+USER_OBJS :=
+
+LIBS := -lncurses
+
diff --git a/Debug/sources.mk b/Debug/sources.mk
new file mode 100644
index 0000000..a1c58f7
--- /dev/null
+++ b/Debug/sources.mk
@@ -0,0 +1,17 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+OBJ_SRCS :=
+ASM_SRCS :=
+C_SRCS :=
+O_SRCS :=
+S_UPPER_SRCS :=
+EXECUTABLES :=
+OBJS :=
+C_DEPS :=
+
+# Every subdirectory with source files must be described here
+SUBDIRS := \
+src \
+
diff --git a/Debug/src/chip8.d b/Debug/src/chip8.d
new file mode 100644
index 0000000..b83fd48
--- /dev/null
+++ b/Debug/src/chip8.d
@@ -0,0 +1,3 @@
+src/chip8.o: ../src/chip8.c ../src/include/chip8.h
+
+../src/include/chip8.h:
diff --git a/Debug/src/chip8.o b/Debug/src/chip8.o
new file mode 100644
index 0000000..f28069b
Binary files /dev/null and b/Debug/src/chip8.o differ
diff --git a/Debug/src/main.d b/Debug/src/main.d
new file mode 100644
index 0000000..b93fd95
--- /dev/null
+++ b/Debug/src/main.d
@@ -0,0 +1,3 @@
+src/main.o: ../src/main.c ../src/include/chip8.h
+
+../src/include/chip8.h:
diff --git a/Debug/src/main.o b/Debug/src/main.o
new file mode 100644
index 0000000..c994a39
Binary files /dev/null and b/Debug/src/main.o differ
diff --git a/Debug/src/subdir.mk b/Debug/src/subdir.mk
new file mode 100644
index 0000000..c7e9041
--- /dev/null
+++ b/Debug/src/subdir.mk
@@ -0,0 +1,27 @@
+################################################################################
+# Automatically-generated file. Do not edit!
+################################################################################
+
+# Add inputs and outputs from these tool invocations to the build variables
+C_SRCS += \
+../src/chip8.c \
+../src/main.c
+
+OBJS += \
+./src/chip8.o \
+./src/main.o
+
+C_DEPS += \
+./src/chip8.d \
+./src/main.d
+
+
+# Each subdirectory must supply rules for building sources it contributes
+src/%.o: ../src/%.c
+ @echo 'Building file: $<'
+ @echo 'Invoking: GCC C Compiler'
+ gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@)" -o "$@" "$<"
+ @echo 'Finished building: $<'
+ @echo ' '
+
+
diff --git a/README.md b/README.md
index 2d1812f..a2bfba8 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,22 @@
# CHIP8-EMU
-A CHIP8 emulator written in C.
\ No newline at end of file
+A CHIP8 emulator written in C.
+
+## Eclipse IDE import:
+
+> File > Import > Existing Code as Makefile project
+
+## Building:
+Eclispe IDE:
+> Right click project > Build Project.
+
+Terminal:
+> cd Debug
+> make
+
+## Running:
+> ./CHIP8-EMU \
+
+## Known issues:
+ - [] Implement key pad
+
diff --git a/roms/15PUZZLE b/roms/15PUZZLE
new file mode 100644
index 0000000..3ef0bc8
Binary files /dev/null and b/roms/15PUZZLE differ
diff --git a/roms/BLINKY b/roms/BLINKY
new file mode 100644
index 0000000..235cf98
Binary files /dev/null and b/roms/BLINKY differ
diff --git a/roms/BLITZ b/roms/BLITZ
new file mode 100644
index 0000000..0d2effa
Binary files /dev/null and b/roms/BLITZ differ
diff --git a/roms/BRIX b/roms/BRIX
new file mode 100644
index 0000000..ad639d9
Binary files /dev/null and b/roms/BRIX differ
diff --git a/roms/CONNECT4 b/roms/CONNECT4
new file mode 100644
index 0000000..200a67a
Binary files /dev/null and b/roms/CONNECT4 differ
diff --git a/roms/GUESS b/roms/GUESS
new file mode 100644
index 0000000..36f783d
Binary files /dev/null and b/roms/GUESS differ
diff --git a/roms/HIDDEN b/roms/HIDDEN
new file mode 100644
index 0000000..bd6b18d
Binary files /dev/null and b/roms/HIDDEN differ
diff --git a/roms/INVADERS b/roms/INVADERS
new file mode 100644
index 0000000..f7db5f5
Binary files /dev/null and b/roms/INVADERS differ
diff --git a/roms/KALEID b/roms/KALEID
new file mode 100644
index 0000000..a1bc7cc
Binary files /dev/null and b/roms/KALEID differ
diff --git a/roms/MAZE b/roms/MAZE
new file mode 100644
index 0000000..152ae7d
Binary files /dev/null and b/roms/MAZE differ
diff --git a/roms/MERLIN b/roms/MERLIN
new file mode 100644
index 0000000..747843a
Binary files /dev/null and b/roms/MERLIN differ
diff --git a/roms/MISSILE b/roms/MISSILE
new file mode 100644
index 0000000..310e2de
Binary files /dev/null and b/roms/MISSILE differ
diff --git a/roms/PONG b/roms/PONG
new file mode 100644
index 0000000..e371e91
Binary files /dev/null and b/roms/PONG differ
diff --git a/roms/PONG2 b/roms/PONG2
new file mode 100644
index 0000000..295ce91
Binary files /dev/null and b/roms/PONG2 differ
diff --git a/roms/PUZZLE b/roms/PUZZLE
new file mode 100644
index 0000000..bec7af0
Binary files /dev/null and b/roms/PUZZLE differ
diff --git a/roms/SYZYGY b/roms/SYZYGY
new file mode 100644
index 0000000..b0653ef
Binary files /dev/null and b/roms/SYZYGY differ
diff --git a/roms/TANK b/roms/TANK
new file mode 100644
index 0000000..ca4bbab
Binary files /dev/null and b/roms/TANK differ
diff --git a/roms/TETRIS b/roms/TETRIS
new file mode 100644
index 0000000..9f5e087
Binary files /dev/null and b/roms/TETRIS differ
diff --git a/roms/TICTAC b/roms/TICTAC
new file mode 100644
index 0000000..4d4bc99
Binary files /dev/null and b/roms/TICTAC differ
diff --git a/roms/UFO b/roms/UFO
new file mode 100644
index 0000000..7fa5a15
Binary files /dev/null and b/roms/UFO differ
diff --git a/roms/VBRIX b/roms/VBRIX
new file mode 100644
index 0000000..07f4006
Binary files /dev/null and b/roms/VBRIX differ
diff --git a/roms/VERS b/roms/VERS
new file mode 100644
index 0000000..b0fe240
Binary files /dev/null and b/roms/VERS differ
diff --git a/roms/WIPEOFF b/roms/WIPEOFF
new file mode 100644
index 0000000..2d5e513
Binary files /dev/null and b/roms/WIPEOFF differ
diff --git a/roms/rom.bin b/roms/rom.bin
new file mode 100644
index 0000000..0dca981
Binary files /dev/null and b/roms/rom.bin differ
diff --git a/src/chip8.c b/src/chip8.c
new file mode 100644
index 0000000..0c2a84c
--- /dev/null
+++ b/src/chip8.c
@@ -0,0 +1,388 @@
+#include "include/chip8.h"
+#include
+#include
+#include
+
+int chip8_dump(chip8_t *chip, const char *filename) {
+ if (chip == NULL)
+ return -1;
+ if (filename == NULL)
+ return -2;
+
+ FILE *file = fopen(filename, "w");
+ if (file == NULL)
+ return -3;
+
+ uint16_t i;
+ fprintf(file, "CHIP8 DUMP FILE\n\n");
+ fprintf(file, "REGISTERS:\n V: ");
+ for (i = 0; i < 16; i++) {
+ fprintf(file, "%02x", chip->cpu.V[i]);
+ if (i < 15)
+ fprintf(file, " ");
+ else
+ fprintf(file, "\n");
+ }
+ fprintf(file, " SP: %02x\n", chip->cpu.SP);
+ fprintf(file, " TS: %02x\n", chip->cpu.TS);
+ fprintf(file, " TD: %02x\n", chip->cpu.TD);
+ fprintf(file, " PC: %04x\n", chip->cpu.PC);
+ fprintf(file, " I: %04x\n\n", chip->cpu.I);
+ fprintf(file, "MEMORY:\n RAM: ");
+ for (i = 0; i < 4096; i++) {
+ fprintf(file, "%02x", chip->mem.RAM[i]);
+ if (i % 64 < 63) {
+ if (i == chip->cpu.PC - 1)
+ fprintf(file, "[");
+ else if (i == chip->cpu.PC + 1)
+ fprintf(file, "]");
+ else if (i == chip->cpu.I)
+ fprintf(file, "-");
+ else
+ fprintf(file, " ");
+ } else {
+ fprintf(file, " %04x | %04x\n", i - 63, i);
+ if (i < 4095)
+ fprintf(file, " ");
+ }
+ }
+ fprintf(file, " STK: ");
+ for (i = 0; i < 24; i++) {
+ fprintf(file, "%04x", chip->mem.STK[i]);
+ if (i < 23)
+ fprintf(file, " ");
+ else
+ fprintf(file, "\n");
+ }
+ fprintf(file, "\nIO:\n KEYS: ");
+ for (i = 0; i < 24; i++) {
+ fprintf(file, "%02x", chip->io.KEYS[i]);
+ if (i < 23)
+ fprintf(file, " ");
+ else
+ fprintf(file, "\n");
+ }
+ fprintf(file, " DSP: ");
+ for (i = 0; i < 2048; i++) {
+ fprintf(file, "%s", chip->io.DSP[i] ? "XX" : "..");
+ if (i % 64 == 63) {
+ fprintf(file, "\n");
+ if (i < 2047)
+ fprintf(file, " ");
+ }
+ }
+
+ fclose(file);
+
+ return 0;
+}
+
+int chip8_init(chip8_t *chip) {
+ if (chip == NULL)
+ return -1;
+
+ uint16_t i;
+
+ for (i = 0; i < 16; i++)
+ chip->cpu.V[i] = 0x00;
+ chip->cpu.SP = 0x00;
+ chip->cpu.TS = 0x00;
+ chip->cpu.TD = 0x00;
+ chip->cpu.PC = 0x0200;
+ chip->cpu.I = 0x0000;
+
+ for (i = 0; i < 4096; i++)
+ chip->mem.RAM[i] = 0x00;
+ for (i = 0; i < 24; i++)
+ chip->mem.STK[i] = 0x00;
+ //font "0"
+ chip->mem.RAM[0] = 0b11110000;
+ chip->mem.RAM[1] = 0b10010000;
+ chip->mem.RAM[2] = 0b10010000;
+ chip->mem.RAM[3] = 0b10010000;
+ chip->mem.RAM[4] = 0b11110000;
+ //font "1"
+ chip->mem.RAM[5] = 0b00100000;
+ chip->mem.RAM[6] = 0b01100000;
+ chip->mem.RAM[7] = 0b00100000;
+ chip->mem.RAM[8] = 0b00100000;
+ chip->mem.RAM[9] = 0b01110000;
+ //font "2"
+ chip->mem.RAM[10] = 0b11110000;
+ chip->mem.RAM[11] = 0b00010000;
+ chip->mem.RAM[12] = 0b11110000;
+ chip->mem.RAM[13] = 0b10000000;
+ chip->mem.RAM[14] = 0b11110000;
+ //font "3"
+ chip->mem.RAM[15] = 0b11110000;
+ chip->mem.RAM[16] = 0b00010000;
+ chip->mem.RAM[17] = 0b11110000;
+ chip->mem.RAM[18] = 0b00010000;
+ chip->mem.RAM[19] = 0b11110000;
+ //font "4"
+ chip->mem.RAM[20] = 0b10010000;
+ chip->mem.RAM[21] = 0b10010000;
+ chip->mem.RAM[22] = 0b11110000;
+ chip->mem.RAM[23] = 0b00010000;
+ chip->mem.RAM[24] = 0b00010000;
+ //font "5"
+ chip->mem.RAM[25] = 0b11110000;
+ chip->mem.RAM[26] = 0b10000000;
+ chip->mem.RAM[27] = 0b11110000;
+ chip->mem.RAM[28] = 0b00010000;
+ chip->mem.RAM[29] = 0b11110000;
+ //font "6"
+ chip->mem.RAM[30] = 0b11110000;
+ chip->mem.RAM[31] = 0b10000000;
+ chip->mem.RAM[32] = 0b11110000;
+ chip->mem.RAM[33] = 0b10010000;
+ chip->mem.RAM[34] = 0b11110000;
+ //font "7"
+ chip->mem.RAM[35] = 0b11110000;
+ chip->mem.RAM[36] = 0b00010000;
+ chip->mem.RAM[37] = 0b00100000;
+ chip->mem.RAM[38] = 0b01000000;
+ chip->mem.RAM[39] = 0b01000000;
+ //font "8"
+ chip->mem.RAM[40] = 0b11110000;
+ chip->mem.RAM[41] = 0b10010000;
+ chip->mem.RAM[42] = 0b11110000;
+ chip->mem.RAM[43] = 0b10010000;
+ chip->mem.RAM[44] = 0b11110000;
+ //font "9"
+ chip->mem.RAM[45] = 0b11110000;
+ chip->mem.RAM[46] = 0b10010000;
+ chip->mem.RAM[47] = 0b11110000;
+ chip->mem.RAM[48] = 0b00010000;
+ chip->mem.RAM[49] = 0b11110000;
+ //font "A"
+ chip->mem.RAM[50] = 0b11110000;
+ chip->mem.RAM[51] = 0b10010000;
+ chip->mem.RAM[52] = 0b11110000;
+ chip->mem.RAM[53] = 0b10010000;
+ chip->mem.RAM[54] = 0b10010000;
+ //font "B"
+ chip->mem.RAM[55] = 0b11100000;
+ chip->mem.RAM[56] = 0b10010000;
+ chip->mem.RAM[57] = 0b11100000;
+ chip->mem.RAM[58] = 0b10010000;
+ chip->mem.RAM[59] = 0b11100000;
+ //font "C"
+ chip->mem.RAM[60] = 0b11110000;
+ chip->mem.RAM[61] = 0b10000000;
+ chip->mem.RAM[62] = 0b10000000;
+ chip->mem.RAM[63] = 0b10000000;
+ chip->mem.RAM[64] = 0b11110000;
+ //font "D"
+ chip->mem.RAM[65] = 0b11100000;
+ chip->mem.RAM[66] = 0b10010000;
+ chip->mem.RAM[67] = 0b10010000;
+ chip->mem.RAM[68] = 0b10010000;
+ chip->mem.RAM[69] = 0b11100000;
+ //font "E"
+ chip->mem.RAM[70] = 0b11110000;
+ chip->mem.RAM[71] = 0b10000000;
+ chip->mem.RAM[72] = 0b11110000;
+ chip->mem.RAM[73] = 0b10000000;
+ chip->mem.RAM[74] = 0b11110000;
+ //font "F"
+ chip->mem.RAM[75] = 0b11110000;
+ chip->mem.RAM[76] = 0b10000000;
+ chip->mem.RAM[77] = 0b11110000;
+ chip->mem.RAM[78] = 0b10000000;
+ chip->mem.RAM[79] = 0b10000000;
+
+ for (i = 0; i < 16; i++)
+ chip->io.KEYS[i] = 0x00;
+ for (i = 0; i < 2048; i++)
+ chip->io.DSP[i] = 0x00;
+
+ chip->flags.draw = 0x00;
+
+ return 0;
+}
+
+int chip8_load(chip8_t *chip, const char *filename) {
+ if (chip == NULL)
+ return -1;
+ if (filename == NULL)
+ return -2;
+
+ FILE *file = fopen(filename, "rb");
+ if (file == NULL)
+ return -3;
+
+ fseek(file, 0L, SEEK_END);
+ long size = ftell(file);
+ if (size < 1L) {
+ fclose(file);
+ return -4;
+ }
+ fseek(file, 0L, SEEK_SET);
+ if (fread(chip->mem.RAM + 0x200, 1, size, file) < size) {
+ fclose(file);
+ return -5;
+ }
+ fclose(file);
+
+ return 0;
+}
+
+int chip8_cycle(chip8_t *chip) {
+ uint16_t opcode = (chip->mem.RAM[chip->cpu.PC] << 8) | chip->mem.RAM[chip->cpu.PC + 1];
+ uint8_t nibble[4] = { opcode >> 12, (opcode >> 8) & 0x000F, (opcode >> 4) & 0x000F, opcode & 0x000F };
+
+ uint16_t i;
+
+ if (opcode == 0x00E0) {
+ for (i = 0; i < 2048; i++)
+ chip->io.DSP[i] = 0x00;
+ chip->flags.draw = 0x01;
+ chip->cpu.PC += 2;
+ } else if (opcode == 0x00EE) {
+ chip->cpu.SP--;
+ chip->cpu.PC = chip->mem.STK[chip->cpu.SP] + 2;
+ } else if (nibble[0] == 0x01) {
+ chip->cpu.PC = opcode & 0x0FFF;
+ } else if (nibble[0] == 0x02) {
+ chip->mem.STK[chip->cpu.SP] = chip->cpu.PC;
+ chip->cpu.SP++;
+ chip->cpu.PC = opcode & 0x0FFF;
+ } else if (nibble[0] == 0x03) {
+ if (chip->cpu.V[nibble[1]] == (opcode & 0x00FF))
+ chip->cpu.PC += 2;
+ chip->cpu.PC += 2;
+ } else if (nibble[0] == 0x04) {
+ if (chip->cpu.V[nibble[1]] != (opcode & 0x00FF))
+ chip->cpu.PC += 2;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x5000) {
+ if (chip->cpu.V[nibble[1]] == chip->cpu.V[nibble[2]])
+ chip->cpu.PC += 2;
+ chip->cpu.PC += 2;
+ } else if (nibble[0] == 0x06) {
+ chip->cpu.V[nibble[1]] = opcode & 0x00FF;
+ chip->cpu.PC += 2;
+ } else if (nibble[0] == 0x07) {
+ chip->cpu.V[nibble[1]] += opcode & 0x00FF;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8000) {
+ chip->cpu.V[nibble[1]] = chip->cpu.V[nibble[2]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8001) {
+ chip->cpu.V[nibble[1]] |= chip->cpu.V[nibble[2]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8002) {
+ chip->cpu.V[nibble[1]] &= chip->cpu.V[nibble[2]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8003) {
+ chip->cpu.V[nibble[1]] ^= chip->cpu.V[nibble[2]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8004) {
+ if ((uint16_t) chip->cpu.V[nibble[1]] + (uint16_t) chip->cpu.V[nibble[2]] > 0x00FF)
+ chip->cpu.V[0xF] = 0x01;
+ else
+ chip->cpu.V[0xF] = 0x00;
+ chip->cpu.V[nibble[1]] += chip->cpu.V[nibble[2]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8005) {
+ if (chip->cpu.V[nibble[1]] > chip->cpu.V[nibble[2]])
+ chip->cpu.V[0xF] = 0x01;
+ else
+ chip->cpu.V[0xF] = 0x00;
+ chip->cpu.V[nibble[1]] -= chip->cpu.V[nibble[2]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8006) {
+ chip->cpu.V[0x0F] = chip->cpu.V[nibble[1]] & 0x01;
+ chip->cpu.V[nibble[1]] >>= 1;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x8007) {
+ if (chip->cpu.V[nibble[2]] > chip->cpu.V[nibble[1]])
+ chip->cpu.V[0xF] = 0x01;
+ else
+ chip->cpu.V[0xF] = 0x00;
+ chip->cpu.V[nibble[1]] = chip->cpu.V[nibble[2]] - chip->cpu.V[nibble[1]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x800E) {
+ chip->cpu.V[0x0F] = chip->cpu.V[nibble[1]] & 0x80;
+ chip->cpu.V[nibble[1]] <<= 1;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF00F) == 0x9000) {
+ if (chip->cpu.V[nibble[1]] != chip->cpu.V[nibble[2]])
+ chip->cpu.PC += 2;
+ chip->cpu.PC += 2;
+ } else if (nibble[0] == 0x0A) {
+ chip->cpu.I = opcode & 0x0FFF;
+ chip->cpu.PC += 2;
+ } else if (nibble[0] == 0x0B) {
+ chip->cpu.PC = (opcode & 0x0FFF) + chip->cpu.V[0x00];
+ } else if (nibble[0] == 0x0C) {
+ chip->cpu.V[nibble[1]] = (rand() % 256) & (opcode & 0x00FF);
+ chip->cpu.PC += 2;
+ } else if (nibble[0] == 0x0D) {
+ uint8_t j, last, x = chip->cpu.V[nibble[1]], y = chip->cpu.V[nibble[2]];
+ chip->cpu.V[0x0F] = 0x00;
+ for (i = 0; i < nibble[3]; i++) {
+ for (j = 0; j < 8; j++) {
+ last = chip->io.DSP[(y + i) * 64 + x + j];
+ chip->io.DSP[(y + i) * 64 + x + j] ^= (chip->mem.RAM[chip->cpu.I + i] >> (7 - j)) & 0x01;
+ if (!chip->io.DSP[(y + i) * 64 + x + j] && last)
+ chip->cpu.V[0x0F] = 0x01;
+
+ }
+ }
+ chip->flags.draw = 0x01;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xE09E) {
+ if (chip->io.KEYS[nibble[1]])
+ chip->cpu.PC += 2;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xE0A1) {
+ if (!(chip->io.KEYS[nibble[1]]))
+ chip->cpu.PC += 2;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF007) {
+ chip->cpu.V[nibble[1]] = chip->cpu.TD;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF00A) {
+ for (i = 0; i < 16; i++)
+ if (chip->io.KEYS[i]) {
+ chip->cpu.PC += 2;
+ break;
+ }
+ } else if ((opcode & 0xF0FF) == 0xF015) {
+ chip->cpu.TD = chip->cpu.V[nibble[1]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF018) {
+ chip->cpu.TS = chip->cpu.V[nibble[1]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF01E) {
+ chip->cpu.V[0x0F] = chip->cpu.I + (uint16_t) chip->cpu.V[nibble[1]] > 0x0FFF;
+ chip->cpu.I += chip->cpu.V[nibble[1]];
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF029) {
+ chip->cpu.I = nibble[1] * 5;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF033) {
+ chip->mem.RAM[chip->cpu.I] = chip->cpu.V[nibble[1]] / 100;
+ chip->mem.RAM[chip->cpu.I + 1] = (chip->cpu.V[nibble[1]] / 10) % 10;
+ chip->mem.RAM[chip->cpu.I + 2] = chip->cpu.V[nibble[1]] % 10;
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF055) {
+ for (i = 0; i < nibble[1]; i++) {
+ chip->mem.RAM[chip->cpu.I] = chip->cpu.V[i];
+ chip->cpu.I++;
+ }
+ chip->cpu.PC += 2;
+ } else if ((opcode & 0xF0FF) == 0xF065) {
+ for (i = 0; i < nibble[1]; i++) {
+ chip->cpu.V[i] = chip->mem.RAM[chip->cpu.I];
+ chip->cpu.I++;
+ }
+ chip->cpu.PC += 2;
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/src/include/chip8.h b/src/include/chip8.h
new file mode 100644
index 0000000..7f95646
--- /dev/null
+++ b/src/include/chip8.h
@@ -0,0 +1,28 @@
+#ifndef SRC_INCLUDE_CHIP8_H_
+#define SRC_INCLUDE_CHIP8_H_
+
+#include
+
+typedef struct {
+ struct {
+ uint8_t V[16], SP, TS, TD;
+ uint16_t PC, I;
+ } cpu;
+ struct {
+ uint8_t RAM[4096];
+ uint16_t STK[24];
+ } mem;
+ struct {
+ uint8_t KEYS[16], DSP[2048];
+ } io;
+ struct {
+ uint8_t draw;
+ } flags;
+} chip8_t;
+
+int chip8_dump(chip8_t *, const char *);
+int chip8_init(chip8_t *);
+int chip8_load(chip8_t *, const char *);
+int chip8_cycle(chip8_t *);
+
+#endif
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..1bc57de
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,144 @@
+#include
+#include
+#include
+#include
+#include "include/chip8.h"
+
+void chip8_keys_clear(chip8_t *chip) {
+ for (uint8_t i = 0; i < 16; i++)
+ chip->io.KEYS[i] = 0x00;
+}
+
+int main(int argc, char **argv) {
+
+ if (argc < 2) {
+ printf("No ROM files specified!\n");
+ return -1;
+ }
+
+ chip8_t chip;
+ chip8_init(&chip);
+ srand(time(NULL));
+ chip8_load(&chip, argv[1]);
+
+ struct timespec ts = { .tv_nsec = 2000000, .tv_sec = 0 };
+ float timer_delay = 0.0F, timer_sound = 0.0F;
+
+ noecho();
+ cbreak();
+ timeout(0);
+ int ch;
+
+ while (1) {
+
+ for (int i = 0; i < 16; i++)
+ chip.io.KEYS[i] = 0x01;
+
+ ch = getch();
+ chip8_keys_clear(&chip);
+ switch (ch) {
+ case '1':
+ chip.io.KEYS[0x1] = 0x01;
+ break;
+ case '2':
+ chip.io.KEYS[0x2] = 0x01;
+ break;
+ case '3':
+ chip.io.KEYS[0x3] = 0x01;
+ break;
+ case '4':
+ chip.io.KEYS[0xC] = 0x01;
+ break;
+ case 'q':
+ chip.io.KEYS[0x4] = 0x01;
+ break;
+ case 'w':
+ chip.io.KEYS[0x5] = 0x01;
+ break;
+ case 'e':
+ chip.io.KEYS[0x6] = 0x01;
+ break;
+ case 'r':
+ chip.io.KEYS[0xD] = 0x01;
+ break;
+ case 'a':
+ chip.io.KEYS[0x7] = 0x01;
+ break;
+ case 's':
+ chip.io.KEYS[0x8] = 0x01;
+ break;
+ case 'd':
+ chip.io.KEYS[0x9] = 0x01;
+ break;
+ case 'f':
+ chip.io.KEYS[0xE] = 0x01;
+ break;
+ case 'z':
+ chip.io.KEYS[0xA] = 0x01;
+ break;
+ case 'x':
+ chip.io.KEYS[0x0] = 0x01;
+ break;
+ case 'c':
+ chip.io.KEYS[0xB] = 0x01;
+ break;
+ case 'v':
+ chip.io.KEYS[0xF] = 0x01;
+ break;
+ default:
+ break;
+ }
+
+ if (chip.cpu.TD) {
+ timer_delay += 2.0F;
+ if (timer_delay >= 1000.0F / 60.0F) {
+ timer_delay -= 1000.0F / 60.0F;
+ chip.cpu.TD--;
+ if (chip.cpu.TD == 0)
+ timer_delay = 0.0F;
+ }
+ }
+
+ if (chip.cpu.TS) {
+ timer_sound += 2.0F;
+ if (timer_sound >= 1000.0F / 60.0F) {
+ timer_sound -= 1000.0F / 60.0F;
+ chip.cpu.TS--;
+ if (chip.cpu.TS == 0)
+ timer_sound = 0.0F;
+ }
+ }
+
+ if (chip.flags.draw) {
+ chip.flags.draw = 0x00;
+ printf("\033[0;0H");
+ for (int x = 0; x < 66; x++)
+ printf("##");
+ printf("\n");
+ for (int y = 0; y < 32; y++) {
+ printf("##");
+ for (int x = 0; x < 64; x++) {
+ if (chip.io.DSP[y * 64 + x])
+ printf("██");
+ else
+ printf(" ");
+ }
+ printf("##\n");
+ }
+ for (int x = 0; x < 66; x++)
+ printf("##");
+ printf("\n");
+ }
+
+ if (chip8_cycle(&chip)) {
+ printf("Invalid opcode 0x%04x!\n", (chip.mem.RAM[chip.cpu.PC] << 8) | chip.mem.RAM[chip.cpu.PC + 1]);
+ return -2;
+ }
+
+ nanosleep(&ts, &ts);
+ ts.tv_nsec = 2000000;
+ ts.tv_sec = 0;
+ }
+
+ return 0;
+}