diff options
-rw-r--r-- | chip8.c | 72 | ||||
-rw-r--r-- | chip8.h | 2 | ||||
-rw-r--r-- | main.c | 35 |
3 files changed, 105 insertions, 4 deletions
@@ -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; } @@ -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 @@ -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) { |