From 4d282a5f7d4a89d1515a7a5c98e9c79cfa178cb5 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 30 Oct 2018 13:07:22 -0400 Subject: [PATCH] Some improvements Fix minor bugs (pong, pong2 now works) Add fontset support Still outstanding bugs: pong doesn't keep track of score, aliens reappear. --- main.c | 65 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/main.c b/main.c index b6d1f46..1516997 100644 --- a/main.c +++ b/main.c @@ -5,7 +5,7 @@ #include #include -#define DEBUG 1 +#define DEBUG 0 #define TDISP 0 typedef uint8_t byte; @@ -23,6 +23,26 @@ typedef struct { byte stack_pointer; } emulator_state_s; +byte chip8_fontset[80] = +{ + 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 + 0x20, 0x60, 0x20, 0x20, 0x70, // 1 + 0xF0, 0x10, 0xF0, 0x80, 0xF0, // 2 + 0xF0, 0x10, 0xF0, 0x10, 0xF0, // 3 + 0x90, 0x90, 0xF0, 0x10, 0x10, // 4 + 0xF0, 0x80, 0xF0, 0x10, 0xF0, // 5 + 0xF0, 0x80, 0xF0, 0x90, 0xF0, // 6 + 0xF0, 0x10, 0x20, 0x40, 0x40, // 7 + 0xF0, 0x90, 0xF0, 0x90, 0xF0, // 8 + 0xF0, 0x90, 0xF0, 0x10, 0xF0, // 9 + 0xF0, 0x90, 0xF0, 0x90, 0x90, // A + 0xE0, 0x90, 0xE0, 0x90, 0xE0, // B + 0xF0, 0x80, 0x80, 0x80, 0xF0, // C + 0xE0, 0x90, 0x90, 0x90, 0xE0, // D + 0xF0, 0x80, 0xF0, 0x80, 0xF0, // E + 0xF0, 0x80, 0xF0, 0x80, 0x80 // F +}; + byte keymap[0x10] = { SDL_SCANCODE_X, SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3, SDL_SCANCODE_Q, SDL_SCANCODE_W, SDL_SCANCODE_E, SDL_SCANCODE_A, SDL_SCANCODE_S, SDL_SCANCODE_D, SDL_SCANCODE_Z, SDL_SCANCODE_C, SDL_SCANCODE_4, SDL_SCANCODE_R, SDL_SCANCODE_F, SDL_SCANCODE_V }; @@ -41,6 +61,7 @@ int main(int argc, char **argv) { emulator_state_s state = { 0 }; // initialize everything to 0 state.program_counter = 0x200; // chip8 programs start at 0x200 address space + memcpy(state.memory, chip8_fontset, 80); FILE *f = fopen(argv[1], "rb"); fread(&state.memory[0x200], 0x1000 - 0x200, 1, f); // see above comment @@ -75,7 +96,7 @@ int main(int argc, char **argv) { // SDL_PumpEvents(); const byte *keystate = SDL_GetKeyboardState(NULL); - for (int i = 0; i < 0x10 && !press; ++i) { + for (int i = 0; i < 0x10; ++i) { if (keystate[keymap[i]]){ state.input[i] = 1; press = 1; @@ -103,12 +124,10 @@ int main(int argc, char **argv) { case 0x0000: // screen clear or function return if (opcode == 0x00E0){ memset(state.screen, 0, 64 * 32); - SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF); - SDL_RenderClear(renderer); if (DEBUG) printf("Clearing screen "); } - else if (opcode = 0x00EE) { + else if (opcode == 0x00EE) { state.program_counter = state.stack[--state.stack_pointer]; if (DEBUG) printf("Returning to %x ", state.stack[state.stack_pointer]); } @@ -161,14 +180,14 @@ int main(int argc, char **argv) { case 0x6000: // set reg to constant reg = (opcode & 0x0F00) >> 8; - state.registers[reg] = opcode & 0x00FF; + state.registers[reg] = (byte) opcode; if (DEBUG) printf("Assigning %hx to %i", state.registers[reg], reg); break; case 0x7000: // add constant to reg reg = (opcode & 0x0F00) >> 8; - state.registers[reg] += opcode & 0x00FF; + state.registers[reg] += (byte) opcode; if (DEBUG) printf("Add %hi to reg %i (%hi)", opcode & 0x00FF, reg, state.registers[reg]); break; @@ -203,23 +222,23 @@ int main(int argc, char **argv) { unsigned int add = state.registers[first] + state.registers[second]; if (add > 255) state.registers[0xF] = 1; else state.registers[0xF] = 0; - state.registers[first] = add & 0x00FF; + state.registers[first] = (byte) add; if (DEBUG) printf("ADD register %i to %i (%hx) ", second, first, state.registers[first]); if (DEBUG) printf("VF is %hx", state.registers[0xF]); break; case 5: // X = X - Y, VF = X - Y < 0 state.registers[first] -= state.registers[second]; - if (state.registers[first] > state.registers[second]) state.registers[0xF] = 1; - else state.registers[0xF] = 0; + if (state.registers[first] > state.registers[second]) state.registers[0xF] = 0; + else state.registers[0xF] = 1; if (DEBUG) printf("SUB register %i from %i (%hx) ", second, first, state.registers[first]); if (DEBUG) printf("VF is %hx", state.registers[0xF]); break; case 6: // set least significant bit of X in VF, bitshift right - state.registers[0xF] = state.registers[first] & 0x000F; + state.registers[0xF] = state.registers[first] & 0b00000001; state.registers[first] /= 2; - if (DEBUG) printf("RS register %i (%hx) ", first, second, state.registers[first]); + if (DEBUG) printf("RS register %i (%hx) ", first, state.registers[first]); if (DEBUG) printf("VF is %hx", state.registers[0xF]); break; @@ -232,9 +251,9 @@ int main(int argc, char **argv) { break; case 0xE:; // set msot significant bit of X in VF, bitshift left - state.registers[0xF] = (state.registers[first] & 0xF000) >> 12; + state.registers[0xF] = (state.registers[first] & 0b10000000) >> 7; state.registers[first] *= 2; - if (DEBUG) printf("LS register %i (%hx) ", first, second, state.registers[first]); + if (DEBUG) printf("LS register %i (%hx) ", first, state.registers[first]); if (DEBUG) printf("VF is %hx", state.registers[0xF]); break; @@ -285,10 +304,13 @@ int main(int argc, char **argv) { for (int xpos = 0; xpos < 8; ++xpos) { int ypos = y + line; - if (ypos > 63) ypos -= 64; - if (!(data & (1 << xpos))) continue; - if (state.screen[x + (7 - xpos)][ypos]) state.registers[0xF] = 1; - state.screen[x + (7 - xpos)][ypos] ^= 1; + byte mask = 1 << 7 - xpos; + if (ypos > 31) ypos -= 32; + if (!(data & mask)) continue; + if (state.screen[x + xpos][ypos]){ + state.registers[0xF] = 1; + } + state.screen[x + xpos][ypos] ^= 1; } } @@ -348,7 +370,8 @@ int main(int argc, char **argv) { break; case 0x29: - break; // fontset not implemented yet + state.address_I = state.registers[reg] * 5; + break; case 0x33:; int value = state.registers[reg]; @@ -358,12 +381,12 @@ int main(int argc, char **argv) { break; case 0x55: - for (int i = 0; i < (reg + 1); ++i) + for (int i = 0; i <= reg; ++i) state.memory[state.address_I + i] = state.registers[i]; break; case 0x65: - for (int i = 0; i < (reg + 1); ++i) + for (int i = 0; i <= reg + 1; ++i) state.registers[i] = state.memory[state.address_I + i]; break;