Some improvements

Fix minor bugs (pong, pong2 now works)
Add fontset support
Still outstanding bugs: pong doesn't keep track of score, aliens reappear.
This commit is contained in:
2018-10-30 13:07:22 -04:00
parent 6bd3a22e5b
commit 4d282a5f7d

65
main.c
View File

@@ -5,7 +5,7 @@
#include <time.h> #include <time.h>
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#define DEBUG 1 #define DEBUG 0
#define TDISP 0 #define TDISP 0
typedef uint8_t byte; typedef uint8_t byte;
@@ -23,6 +23,26 @@ typedef struct {
byte stack_pointer; byte stack_pointer;
} emulator_state_s; } 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, 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_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 }; 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 emulator_state_s state = { 0 }; // initialize everything to 0
state.program_counter = 0x200; // chip8 programs start at 0x200 address space state.program_counter = 0x200; // chip8 programs start at 0x200 address space
memcpy(state.memory, chip8_fontset, 80);
FILE *f = fopen(argv[1], "rb"); FILE *f = fopen(argv[1], "rb");
fread(&state.memory[0x200], 0x1000 - 0x200, 1, f); // see above comment fread(&state.memory[0x200], 0x1000 - 0x200, 1, f); // see above comment
@@ -75,7 +96,7 @@ int main(int argc, char **argv) {
// SDL_PumpEvents(); // SDL_PumpEvents();
const byte *keystate = SDL_GetKeyboardState(NULL); 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]]){ if (keystate[keymap[i]]){
state.input[i] = 1; state.input[i] = 1;
press = 1; press = 1;
@@ -103,12 +124,10 @@ int main(int argc, char **argv) {
case 0x0000: // screen clear or function return case 0x0000: // screen clear or function return
if (opcode == 0x00E0){ if (opcode == 0x00E0){
memset(state.screen, 0, 64 * 32); memset(state.screen, 0, 64 * 32);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0xFF);
SDL_RenderClear(renderer);
if (DEBUG) printf("Clearing screen "); if (DEBUG) printf("Clearing screen ");
} }
else if (opcode = 0x00EE) { else if (opcode == 0x00EE) {
state.program_counter = state.stack[--state.stack_pointer]; state.program_counter = state.stack[--state.stack_pointer];
if (DEBUG) printf("Returning to %x ", 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 case 0x6000: // set reg to constant
reg = (opcode & 0x0F00) >> 8; 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); if (DEBUG) printf("Assigning %hx to %i", state.registers[reg], reg);
break; break;
case 0x7000: // add constant to reg case 0x7000: // add constant to reg
reg = (opcode & 0x0F00) >> 8; 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]); if (DEBUG) printf("Add %hi to reg %i (%hi)", opcode & 0x00FF, reg, state.registers[reg]);
break; break;
@@ -203,23 +222,23 @@ int main(int argc, char **argv) {
unsigned int add = state.registers[first] + state.registers[second]; unsigned int add = state.registers[first] + state.registers[second];
if (add > 255) state.registers[0xF] = 1; if (add > 255) state.registers[0xF] = 1;
else state.registers[0xF] = 0; 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("ADD register %i to %i (%hx) ", second, first, state.registers[first]);
if (DEBUG) printf("VF is %hx", state.registers[0xF]); if (DEBUG) printf("VF is %hx", state.registers[0xF]);
break; break;
case 5: // X = X - Y, VF = X - Y < 0 case 5: // X = X - Y, VF = X - Y < 0
state.registers[first] -= state.registers[second]; state.registers[first] -= state.registers[second];
if (state.registers[first] > state.registers[second]) state.registers[0xF] = 1; if (state.registers[first] > state.registers[second]) state.registers[0xF] = 0;
else 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("SUB register %i from %i (%hx) ", second, first, state.registers[first]);
if (DEBUG) printf("VF is %hx", state.registers[0xF]); if (DEBUG) printf("VF is %hx", state.registers[0xF]);
break; break;
case 6: // set least significant bit of X in VF, bitshift right 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; 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]); if (DEBUG) printf("VF is %hx", state.registers[0xF]);
break; break;
@@ -232,9 +251,9 @@ int main(int argc, char **argv) {
break; break;
case 0xE:; // set msot significant bit of X in VF, bitshift left 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; 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]); if (DEBUG) printf("VF is %hx", state.registers[0xF]);
break; break;
@@ -285,10 +304,13 @@ int main(int argc, char **argv) {
for (int xpos = 0; xpos < 8; ++xpos) for (int xpos = 0; xpos < 8; ++xpos)
{ {
int ypos = y + line; int ypos = y + line;
if (ypos > 63) ypos -= 64; byte mask = 1 << 7 - xpos;
if (!(data & (1 << xpos))) continue; if (ypos > 31) ypos -= 32;
if (state.screen[x + (7 - xpos)][ypos]) state.registers[0xF] = 1; if (!(data & mask)) continue;
state.screen[x + (7 - xpos)][ypos] ^= 1; 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; break;
case 0x29: case 0x29:
break; // fontset not implemented yet state.address_I = state.registers[reg] * 5;
break;
case 0x33:; case 0x33:;
int value = state.registers[reg]; int value = state.registers[reg];
@@ -358,12 +381,12 @@ int main(int argc, char **argv) {
break; break;
case 0x55: 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]; state.memory[state.address_I + i] = state.registers[i];
break; break;
case 0x65: 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]; state.registers[i] = state.memory[state.address_I + i];
break; break;