summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--chip8.c132
-rw-r--r--main.c6
3 files changed, 122 insertions, 18 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bda00bc..9f3f950 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,7 +10,7 @@ add_executable(
chip8
main.c chip8.c chip8.h)
-target_compile_options(chip8 PRIVATE -Wall)
+target_compile_options(chip8 PRIVATE -Wall -Wextra)
target_link_libraries(chip8 PRIVATE SDL2::SDL2)
diff --git a/chip8.c b/chip8.c
index 32803bb..748cca4 100644
--- a/chip8.c
+++ b/chip8.c
@@ -96,10 +96,8 @@ chip8_draw_sprite(int startx, int starty, uint16_t mem, uint8_t size)
/*
* draw sprite located at loc of height size at startx,starty
*/
-
uint8_t byte = 0;
uint8_t mask = 0x1;
- V[0xF] = 0; /* set collision register to 0 */
for (uint8_t byteoffset = 0; byteoffset < size; byteoffset++)
{
/* loop through each byte from mem to mem+size */
@@ -110,12 +108,10 @@ chip8_draw_sprite(int startx, int starty, uint16_t mem, uint8_t size)
if (byte & mask)
{
uint32_t pixel = WIDTH*(starty%HEIGHT)+((startx%WIDTH)+bit);
- if (video[pixel] != 0)
- {
- /* if the video bit is already set, we need to set the collision register */
- V[0xF] = 1;
- }
+ /* if the video bit is already set, we need to set the collision register */
+ V[0xF] = (video[pixel] != 0) ? 1 : 0;
video[pixel] ^= PIXEL_COLOR;
+ draw_flag = 1;
}
bit++;
}
@@ -155,7 +151,7 @@ chip8_cycle()
uint8_t x = (opcode >> 8) & 0x000F; // lower 4 bits of the high byte, we discard the low byte by right shifting it out
uint8_t y = (opcode >> 4) & 0x000F; // upper 4 bits of the low byte, so we need to discard the lower 4 bits
uint8_t kk = opcode & 0x00FF; // lowest 8 bits
- printf("parsing at 0x%03X\n", PC);
+ printf("parsing at 0x%03X opcode = 0x%04X\n", PC, opcode);
PC += 2; // TODO: remove
switch (opcode & 0xF000)
{
@@ -189,18 +185,15 @@ chip8_cycle()
break;
case 0x3000: /* SE Vx, byte (skip next instruction if Vx = kk) */
// TODO: not tested
- if (V[x] == kk)
- PC += 2;
+ PC += (V[x] == kk) ? 2 : 0;
break;
case 0x4000: /* SN Vx, byte (skip next instruction if Vx != kk) */
// TODO: not tested
- if (V[x] != kk)
- PC += 2;
+ PC += (V[x] != kk) ? 2 : 0;
break;
case 0x5000: /* SE Vx, Vy (skip next instruction if Vx == Vy) */
// TODO: not tested
- if (V[x] == V[y])
- PC += 2;
+ PC += (V[x] == V[y]) ? 2 : 0;
break;
case 0x6000: /* LD Vx, byte (load byte in register x) */
{
@@ -264,6 +257,117 @@ chip8_cycle()
break;
default: unknown_opcode(opcode);
}
+ break;
+ }
+ case 0x9000: /* SNE Vx, Vy (skip next instruction if Vx != Vy) */
+ // TODO: not tested
+ PC += (V[x] != V[y]) ? 2 : 0;
+ break;
+ case 0xA000: /* LD I, addr (load register I with addr) */
+ // TODO: not tested
+ I = nnn;
+ break;
+ case 0xB000: /* JP V0, addr (set PC to location nnn + V0) */
+ // TODO: not tested
+ PC = V[0] + nnn;
+ break;
+ case 0xC000: /* RND Vx, byte (set Vx to a random byte and AND it by kk) */
+ // TODO: not tested
+ V[x] = (rand() % 256) & kk; // random number between 0 and 255
+ break;
+ case 0xD000: /* DRW Vx, Vy, n (read n bytes from starting starting at address in register I, and draws then at coordinates x,y */
+ // TODO: not tested
+ chip8_draw_sprite(V[x], V[y], I, n);
+ break;
+ case 0xE000: /* key input */
+ {
+ switch(kk)
+ {
+ case 0x9E: /* SKP Vx (skip next instruction if key Vx is pressed) */
+ // TODO: not tested
+ PC += (key[V[x]] == 1) ? 2 : 0;
+ break;
+ case 0xA1: /* SKNP Vx (skip next instruction if key Vx is not pressed) */
+ // TODO: not tested
+ PC += (key[V[x]] == 0) ? 2 : 0;
+ break;
+ default: unknown_opcode(opcode);
+ }
+ break;
+ }
+ case 0xF000:
+ {
+ switch (kk)
+ {
+ case 0x07: /* LD Vx, DT (load Vx with the value of delay timer register) */
+ // TODO: not tested
+ V[x] = delay_timer;
+ break;
+ case 0x0A: /* LD Vx, K (all execution stops until a key is pressed, then that key is put into Vx) */
+ {
+ // TODO: not tested
+ int found_key = 0;
+ for (int i = 0; i < 15; i++)
+ {
+ V[x] = key[i];
+ if (V[x] == 1)
+ found_key = 1;
+ }
+ PC -= (found_key == 0) ? 2 : 0;
+ break;
+ }
+ case 0x15: /* LD DT, Vx (delay timer is set to the value of Vx */
+ // TODO: not tested
+ delay_timer = V[x];
+ break;
+ case 0x18: /* LD ST, Vx (sound timer is set to the value of Vx */
+ // TODO: not tested
+ sound_timer = V[x];
+ break;
+ case 0x1E: /* ADD I, Vx (set I register to I + Vx) */
+ // TODO: not tested
+ I += V[x];
+ break;
+ case 0x29: /* LD F, Vx (set register I to location of the hex sprite Vx) */
+ // TODO: not tested
+ I = V[x] * 5;
+ break;
+ case 0x33: /* LD B, Vx (store BCD representation of Vx in memory locations I, I+1 and I+2) */
+ // TODO: not tested
+ memory[I] = (V[x] % 1000) / 100;
+ memory[I+1] = (V[x] % 100) / 10;
+ memory[I+2] = (V[x] % 10);
+ break;
+ case 0x55: /* LD [I], Vx (store registers V0 through Vx starting at memory location I) */
+ {
+ // TODO: not tested
+ int reg = 0;
+ do
+ {
+ memory[I+reg] = V[reg];
+ reg++;
+ }
+ while (reg <= V[x]);
+ break;
+ }
+ case 0x65: /* LD Vx, [I] (read registers V0 through Vx from memory starting at I) */
+ {
+ // TODO: not tested
+ int reg = 0;
+ int target = V[x];
+ do
+ {
+ V[reg] = memory[I+reg];
+ reg++;
+ }
+ while (reg < target);
+ break;
+ }
+ break;
+
+ default: unknown_opcode(opcode);
+ }
+ break;
}
default: unknown_opcode(opcode);
}
diff --git a/main.c b/main.c
index 3b8183e..ae6f34d 100644
--- a/main.c
+++ b/main.c
@@ -14,7 +14,7 @@
*/
#define VIDEO_SCALE 5
-#define STEPPING 1 // set to 1 to step manually through program
+#define STEPPING 0 // set to 1 to step manually through program
SDL_Window *window;
SDL_Renderer *renderer;
@@ -205,13 +205,14 @@ int main(int argc, char *argv[])
init_video();
- const int fps = 1;
+ const int fps = 500;
const int frame_delay = 1000/fps;
uint32_t frame_start;
uint32_t frame_time;
int do_quit = 0;
+ /*
chip8_draw_sprite(0, 0, 0xD*5, 0x5);
chip8_draw_sprite(5, 0, 0xE*5, 0x5);
chip8_draw_sprite(10, 0, 0xA*5, 0x5);
@@ -230,7 +231,6 @@ int main(int argc, char *argv[])
chip8_draw_sprite(30, 9, 0xE*5, 0x5);
chip8_draw_sprite(35, 9, 0xf*5, 0x5);
- /*
chip8_draw_sprite(0, 20, 0x200, 0x6);
chip8_draw_sprite(8, 20, 0x200, 0x6);
chip8_draw_sprite(16, 20, 0x200, 0x6);