summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip8.c72
-rw-r--r--chip8.h2
-rw-r--r--main.c35
3 files changed, 105 insertions, 4 deletions
diff --git a/chip8.c b/chip8.c
index 9933096..1d8de29 100644
--- a/chip8.c
+++ b/chip8.c
@@ -77,15 +77,17 @@ chip8_init()
//TODO: add whole alphabet, then can write a rom to write strings or something
for (uint8_t i = 0; i < FONT_BYTE_SIZE; i++)
{
- memory[ + i] = chip8_fontset[i];
+ memory[0x0 + i] = chip8_fontset[i];
}
+ /*
uint8_t sinv[] = {0xBA, 0x7C, 0xD6, 0xFE, 0x54, 0xAA};
// temp
for (uint8_t i = 0; i <= FONT_WIDTH; i++)
{
memory[PROGRAM_START+i] = sinv[i];
}
+ */
}
void
@@ -122,7 +124,75 @@ chip8_draw_sprite(int startx, int starty, uint16_t mem, uint8_t size)
}
void
+chip8_beep()
+{
+ // TODO: holy shit this is terrible, do something better
+ puts("\a");
+}
+
+void
+unknown_opcode(uint16_t bad_opcode)
+{
+ fprintf(stderr, "unknown opcode: 0x%02X at 0x%02X\n", bad_opcode, PC);
+}
+void
chip8_cycle()
{
+ /*
+ * fetch, decode, execute
+ */
+ /*
+ * the opcode is a 2 byte value, while our memory is 1 byte
+ * so to get our opcode we need to combine 2 bytes located at PC and PC+1
+ * we right shift the first byte by 8 (1 byte) to place it in the high byte
+ * and we store the second byte in the lower byte
+ */
+ opcode = (memory[PC] << 8) | memory[PC+1];
+
+ uint16_t nnn = opcode & 0x0FFF; // lowest 12 bits
+ uint8_t n = opcode & 0x000F; // lowest 4 bits
+ 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
+
+ switch (opcode & 0xF000)
+ {
+ /*
+ * decode highest 4 bits
+ * the highest 4 bits contains the instruction
+ */
+ case 0x0000:
+ {
+ switch (kk)
+ {
+ case 0x00E0: /* cls (clear screen) */
+ puts("clear");
+ memset(video, 0, (WIDTH*HEIGHT) * sizeof(uint32_t));
+ draw_flag = 1;
+ break;
+ case 0x00EE: /* ret (return from subroutine) */
+ break;
+ default: unknown_opcode(opcode);
+ }
+ break;
+ }
+ case 0x6000: /* LD Vx, byte (load byte in register x) */
+ {
+ V[x] = kk;
+ break;
+ }
+
+ default: unknown_opcode(opcode);
+ }
+
+ /* timers */
+ if (delay_timer > 0)
+ delay_timer--;
+ if (sound_timer > 0)
+ {
+ chip8_beep();
+ sound_timer--;
+ }
+ PC += 2;
}
diff --git a/chip8.h b/chip8.h
index 6779567..6d59ea8 100644
--- a/chip8.h
+++ b/chip8.h
@@ -25,5 +25,7 @@ int load_rom();
void chip8_init();
void chip8_draw_sprite(int startx, int starty, uint16_t mem, uint8_t size);
void chip8_cycle();
+void chip8_beep();
+void unknown_opcode(uint16_t bad_opcode);
#endif
diff --git a/main.c b/main.c
index 9a81c31..f58edf7 100644
--- a/main.c
+++ b/main.c
@@ -27,10 +27,17 @@ int handle_sdl_events();
void handle_key_down(int keycode);
void handle_key_up(int keycode);
uint8_t get_chip8_key(int keycode);
+void print_registers();
extern uint32_t video[WIDTH*HEIGHT];
extern int draw_flag;
extern uint8_t key[KEY_SIZE];
+extern uint8_t V[REGISTER_COUNT];
+extern uint16_t I;
+extern uint16_t PC;
+extern int8_t SP;
+extern uint8_t delay_timer;
+extern uint8_t sound_timer;
void
usage(char *program)
@@ -77,8 +84,28 @@ toggle_pixel(int x, int y)
}
void
+print_registers()
+{
+ puts("REGISTER DUMP");
+ puts("--------------------------");
+ for (int reg = 0; reg < REGISTER_COUNT; reg++)
+ {
+ printf("V[0x%01X] = 0x%02X\n", reg, V[reg]);
+ }
+ printf("PC = 0x%03X\nI = 0x%03X\nSP = 0x%02X\ndelay_timer = 0x%02X\nsound_timer = 0x%02X\n", PC, I, SP, delay_timer, sound_timer);
+ puts("--------------------------");
+}
+
+void
handle_key_down(int keycode)
{
+ switch (keycode)
+ {
+ /* detect interpreter debug keys */
+ case SDLK_p: print_registers(); break;
+ default: break;
+ }
+
uint8_t k = get_chip8_key(keycode);
if (k > 0xF) return; /* unknown key */
key[k] = 1;
@@ -154,17 +181,17 @@ int main(int argc, char *argv[])
exit(EXIT_FAILURE);
}
+ chip8_init();
+
if (!load_rom(argv[1]))
{
fprintf(stderr, "cannot start interpreter\n");
exit(EXIT_FAILURE);
}
- chip8_init();
-
init_video();
- const int fps = 60;
+ const int fps = 2;
const int frame_delay = 1000/fps;
uint32_t frame_start;
uint32_t frame_time;
@@ -189,6 +216,7 @@ 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);
@@ -196,6 +224,7 @@ int main(int argc, char *argv[])
chip8_draw_sprite(61, 25, 0x200, 0x6);
chip8_draw_sprite(50, 30, 0x200, 0x6);
+ */
while(!do_quit)
{