diff options
-rw-r--r-- | chip8.c | 25 | ||||
-rw-r--r-- | main.c | 46 |
2 files changed, 59 insertions, 12 deletions
@@ -133,7 +133,7 @@ chip8_beep() void unknown_opcode(uint16_t bad_opcode) { - fprintf(stderr, "unknown opcode: 0x%02X at 0x%02X\n", bad_opcode, PC); + fprintf(stderr, "unknown opcode: 0x%02X at 0x%02X\n", bad_opcode, PC-2); // minus 2 because we increment PC by 2 at the start of decoding } void chip8_cycle() @@ -145,7 +145,7 @@ chip8_cycle() /* * 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 + * we left 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]; @@ -155,7 +155,8 @@ 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); + PC += 2; // TODO: remove switch (opcode & 0xF000) { /* @@ -172,17 +173,32 @@ chip8_cycle() draw_flag = 1; break; case 0x00EE: /* ret (return from subroutine) */ + // TODO: test, check for out of bounds? + PC = stack[--SP]; break; default: unknown_opcode(opcode); } break; } + case 0x1000: /*JP addr (jump to memory address nnn) */ + PC = nnn; + break; + case 0x2000: /* CALL addr (call subroutine at addr, increment SP and put current PC on top of stack, set PC to nnn) */ + // TODO: test, bounds check? + stack[SP++] = PC; + PC = nnn; + break; case 0x6000: /* LD Vx, byte (load byte in register x) */ { V[x] = kk; break; } - + case 0x7000: /* ADD Vx, byte (add byte to Vx and store result in Vx) */ + V[x] = V[x] + kk; + break; + case 0x8000: /* LD Vx, Vy (load Vy into Vx register) */ + V[x] = V[y]; + break; default: unknown_opcode(opcode); } @@ -194,5 +210,4 @@ chip8_cycle() chip8_beep(); sound_timer--; } - PC += 2; } @@ -10,9 +10,11 @@ * http://mattmik.com/files/chip8/mastering/chip8.html (lots of info) * http://devernay.free.fr/hacks/chip8/C8TECH10.HTM#0.1 * http://www.emulator101.com/chip-8-sprites.html + * https://slack-files.com/T3CH37TNX-F3RKEUKL4-b05ab4930d?nojsmode=1 */ #define VIDEO_SCALE 5 +#define STEPPING 1 // set to 1 to step manually through program SDL_Window *window; SDL_Renderer *renderer; @@ -29,6 +31,8 @@ void handle_key_up(int keycode); uint8_t get_chip8_key(int keycode); void print_registers(); +int step_cycle = 0; + extern uint32_t video[WIDTH*HEIGHT]; extern int draw_flag; extern uint8_t key[KEY_SIZE]; @@ -38,6 +42,7 @@ extern uint16_t PC; extern int8_t SP; extern uint8_t delay_timer; extern uint8_t sound_timer; +extern uint16_t stack[STACK_SIZE]; void usage(char *program) @@ -86,13 +91,21 @@ toggle_pixel(int x, int y) void print_registers() { - puts("REGISTER DUMP"); + puts("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); + // minus 2 on PC because we increment PC by 2 at the start of decoding + printf("PC = 0x%03X\nI = 0x%03X\nSP = 0x%02X\ndelay_timer = 0x%02X\nsound_timer = 0x%02X\n", PC-2, I, SP, delay_timer, sound_timer); + puts("STACK:"); + for (int i = 0; i < 16; i++) + { + printf("[%d] = 0x%03X", i, stack[i]); + if (i == 7) puts(""); + } + puts(""); puts("--------------------------"); } @@ -103,6 +116,7 @@ handle_key_down(int keycode) { /* detect interpreter debug keys */ case SDLK_p: print_registers(); break; + case SDLK_PERIOD: step_cycle = 1; break; default: break; } @@ -191,7 +205,7 @@ int main(int argc, char *argv[]) init_video(); - const int fps = 2; + const int fps = 1; const int frame_delay = 1000/fps; uint32_t frame_start; uint32_t frame_time; @@ -232,12 +246,30 @@ int main(int argc, char *argv[]) // logic do_quit = handle_sdl_events(); - chip8_cycle(); + if (STEPPING) + { + if (step_cycle == 1) + { + chip8_cycle(); + + if (draw_flag) + { + update_video(); + draw_flag = 0; + } - if (draw_flag) + step_cycle = 0; + } + } + else { - update_video(); - draw_flag = 0; + chip8_cycle(); + + if (draw_flag) + { + update_video(); + draw_flag = 0; + } } frame_time = SDL_GetTicks() - frame_start; |