Fix some register bugs

This commit is contained in:
Doyle Thai 2017-04-06 02:18:41 +10:00
parent ac6d32d1b9
commit 2aa5bffb79
4 changed files with 148 additions and 36 deletions

View File

@ -10,6 +10,7 @@ enum Chip8State
{ {
chip8state_init, chip8state_init,
chip8state_load_file, chip8state_load_file,
chip8state_await_input,
chip8state_running, chip8state_running,
chip8state_off, chip8state_off,
}; };
@ -65,6 +66,7 @@ typedef struct Chip8CPU
u8 stackPointer; u8 stackPointer;
u16 stack[16]; u16 stack[16];
u8 keyToStoreToRegisterIndex;
enum Chip8State state; enum Chip8State state;
} Chip8CPU; } Chip8CPU;
@ -285,7 +287,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
if (cpu.state == chip8state_load_file) if (cpu.state == chip8state_load_file)
{ {
PlatformFile file = {}; PlatformFile file = {};
if (platform_open_file(L"roms/BLITZ", &file)) if (platform_open_file(L"roms/TETRIS", &file))
{ {
DQNT_ASSERT((cpu.INIT_ADDRESS + file.size) <= DQNT_ASSERT((cpu.INIT_ADDRESS + file.size) <=
memory.permanentMemSize); memory.permanentMemSize);
@ -305,6 +307,25 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
} }
#endif #endif
if (cpu.state == chip8state_await_input)
{
const u32 OFFSET_TO_CHIP_CONTROLS = key_7;
for (i32 i = OFFSET_TO_CHIP_CONTROLS; i < DQNT_ARRAY_COUNT(input.key);
i++)
{
KeyState checkKey = input.key[i];
if (checkKey.isDown)
{
u8 regIndex = cpu.keyToStoreToRegisterIndex;
u8 keyVal = (u8)i - OFFSET_TO_CHIP_CONTROLS;
DQNT_ASSERT(keyVal >= 0 && keyVal <= 0x0F);
cpu.registerArray[regIndex] = keyVal;
cpu.state = chip8state_running;
}
}
}
if (cpu.state == chip8state_running) if (cpu.state == chip8state_running)
{ {
u8 opHighByte = mainMem[cpu.programCounter++]; u8 opHighByte = mainMem[cpu.programCounter++];
@ -356,20 +377,20 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
{ {
u8 regNum = (0x0F & opHighByte); u8 regNum = (0x0F & opHighByte);
DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray)); DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
u8 *vx = &cpu.registerArray[regNum];
u8 valToCheck = opLowByte; u8 valToCheck = opLowByte;
// SE Vx, byte - 3xkk - Skip next instruction if Vx == kk // SE Vx, byte - 3xkk - Skip next instruction if Vx == kk
if (opFirstNibble == 0x30) if (opFirstNibble == 0x30)
{ {
if (cpu.registerArray[regNum] == valToCheck) if (*vx == valToCheck) cpu.programCounter += 2;
cpu.programCounter += 2;
} }
// SNE Vx, byte - 4xkk - Skip next instruction if Vx == kk // SNE Vx, byte - 4xkk - Skip next instruction if Vx == kk
else else
{ {
DQNT_ASSERT(opFirstNibble == 0x40); DQNT_ASSERT(opFirstNibble == 0x40);
if (cpu.registerArray[regNum] != valToCheck) if (*vx != valToCheck) cpu.programCounter += 2;
cpu.programCounter += 2;
} }
} }
break; break;
@ -383,11 +404,10 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
u8 secondRegNum = (0xF0 & opLowByte) >> 4; u8 secondRegNum = (0xF0 & opLowByte) >> 4;
DQNT_ASSERT(secondRegNum < DQNT_ARRAY_COUNT(cpu.registerArray)); DQNT_ASSERT(secondRegNum < DQNT_ARRAY_COUNT(cpu.registerArray));
if (cpu.registerArray[firstRegNum] == u8 *vx = &cpu.registerArray[firstRegNum];
cpu.registerArray[secondRegNum]) u8 *vy = &cpu.registerArray[secondRegNum];
{
cpu.programCounter++; if (*vx == *vy) cpu.programCounter += 2;
}
} }
break; break;
@ -398,16 +418,17 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray)); DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
u8 valToOperateOn = opLowByte; u8 valToOperateOn = opLowByte;
u8 *vx = &cpu.registerArray[regNum];
// LD Vx, byte - 6xkk - Set Vx = kk // LD Vx, byte - 6xkk - Set Vx = kk
if (opFirstNibble == 0x60) if (opFirstNibble == 0x60)
{ {
cpu.registerArray[regNum] = valToOperateOn; *vx = valToOperateOn;
} }
// ADD Vx, byte - 7xkk - Set Vx = Vx + kk // ADD Vx, byte - 7xkk - Set Vx = Vx + kk
else else
{ {
DQNT_ASSERT(opFirstNibble == 0x70); DQNT_ASSERT(opFirstNibble == 0x70);
cpu.registerArray[regNum] += valToOperateOn; *vx += valToOperateOn;
} }
} }
break; break;
@ -444,26 +465,31 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
// XOR Vx, Vy - 8xy3 - Set Vx = Vx XOR Vy // XOR Vx, Vy - 8xy3 - Set Vx = Vx XOR Vy
else if (opFourthNibble == 0x03) else if (opFourthNibble == 0x03)
{ {
u8 result = (*vx & *vy); u8 result = (*vx ^ *vy);
*vx = result; *vx = result;
} }
// ADD Vx, Vy - 8xy4 - Set Vx = Vx + Vy, set VF = carry // ADD Vx, Vy - 8xy4 - Set Vx = Vx + Vy, set VF = carry
else if (opFourthNibble == 0x04) else if (opFourthNibble == 0x04)
{ {
u16 result = (*vx + *vy); u16 result = (*vx + *vy);
*vx = (u8)result; *vx = (result > 255) ? (u8)(result - 256) : (u8)result;
if (result > 255) cpu.VF = (result > 255) ? 1 : 0; cpu.VF = (result > 255) ? 1 : 0;
} }
// SUB Vx, Vy - 8xy5 - Set Vx = Vx - Vy, set VF = NOT borrow // SUB Vx, Vy - 8xy5 - Set Vx = Vx - Vy, set VF = NOT borrow
else if (opFourthNibble == 0x05) else if (opFourthNibble == 0x05)
{ {
if (*vx > *vy) if (*vx > *vy)
{
cpu.VF = 1; cpu.VF = 1;
*vx -= *vy;
}
else else
{
cpu.VF = 0; cpu.VF = 0;
*vx = (u8)(256 + *vx - *vy);
}
*vx -= *vy;
} }
// SHR Vx {, Vy} - 8xy6 - Set Vx = Vx SHR 1 // SHR Vx {, Vy} - 8xy6 - Set Vx = Vx SHR 1
else if (opFourthNibble == 0x06) else if (opFourthNibble == 0x06)
@ -479,11 +505,16 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
else if (opFourthNibble == 0x07) else if (opFourthNibble == 0x07)
{ {
if (*vy > *vx) if (*vy > *vx)
{
cpu.VF = 1; cpu.VF = 1;
*vx = *vy - *vx;
}
else else
{
cpu.VF = 0; cpu.VF = 0;
*vx = (u8)(256 + *vy - *vx);
}
*vx = *vy - *vx;
} }
// SHL Vx {, Vy} - 8xyE - Set Vx = SHL 1 // SHL Vx {, Vy} - 8xyE - Set Vx = SHL 1
else else
@ -526,7 +557,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
// JP V0, addr - Bnnn - Jump to location (nnn + V0) // JP V0, addr - Bnnn - Jump to location (nnn + V0)
case 0xB0: case 0xB0:
{ {
u8 addr = opLowByte + cpu.V0; u16 addr = (((0x0F & opHighByte) << 8) | opLowByte) + cpu.V0;
cpu.programCounter = addr; cpu.programCounter = addr;
} }
break; break;
@ -534,14 +565,15 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
// RND Vx, byte - Cxkk - Set Vx = random byte AND kk // RND Vx, byte - Cxkk - Set Vx = random byte AND kk
case 0xC0: case 0xC0:
{ {
u8 firstRegNum = (0x0F & opHighByte); u8 regNum = (0x0F & opHighByte);
DQNT_ASSERT(firstRegNum < DQNT_ARRAY_COUNT(cpu.registerArray)); DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
u8 *vx = &cpu.registerArray[regNum];
u8 andBits = opLowByte;
u8 *vx = &cpu.registerArray[firstRegNum];
u8 randNum = (u8)dqnt_rnd_pcg_range(&pcgState, 0, 255); u8 randNum = (u8)dqnt_rnd_pcg_range(&pcgState, 0, 255);
*vx = (randNum & opLowByte); u8 andBits = opLowByte;
DQNT_ASSERT(randNum >= 0 && randNum <= 255);
*vx = (randNum & andBits);
} }
break; break;
@ -595,7 +627,6 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
bool spriteBit = ((spriteBytes >> bitShift) & 1); bool spriteBit = ((spriteBytes >> bitShift) & 1);
bool pixelIsOn = (pixelWasOn ^ spriteBit); bool pixelIsOn = (pixelWasOn ^ spriteBit);
// TODO(doyle): wrap pixels around
// NOTE: If caused a pixel to XOR into off, then this is // NOTE: If caused a pixel to XOR into off, then this is
// known as a "collision" in chip8 // known as a "collision" in chip8
if (pixelWasOn && !pixelIsOn) if (pixelWasOn && !pixelIsOn)
@ -622,20 +653,30 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
case 0xE0: case 0xE0:
{ {
// TODO(doyle): Implement key checks u8 regNum = (0x0F & opHighByte);
u8 checkKey = (0x0F & opHighByte); DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray));
u8 vx = cpu.registerArray[regNum];
DQNT_ASSERT(vx >= 0 && vx <= 0x0F);
const u32 KEY_OFFSET_TO_START_CONTROLS = key_7;
DQNT_ASSERT((KEY_OFFSET_TO_START_CONTROLS + vx) <
DQNT_ARRAY_COUNT(input.key));
KeyState checkKey =
input.key[KEY_OFFSET_TO_START_CONTROLS + vx];
bool skipNextInstruction = false;
// SKP Vx - Ex9E - Skip next instruction if key with the value // SKP Vx - Ex9E - Skip next instruction if key with the value
// of Vx is pressed // of Vx is pressed
bool skipNextInstruction = false;
if (opLowByte == 0x9E) if (opLowByte == 0x9E)
{ {
skipNextInstruction = checkKey.isDown;
} }
// SKNP Vx - ExA1 - Skip next instruction if key with the value // SKNP Vx - ExA1 - Skip next instruction if key with the value
// of Vx is not pressed // of Vx is not pressed
else else
{ {
DQNT_ASSERT(opLowByte == 0xA1); DQNT_ASSERT(opLowByte == 0xA1);
skipNextInstruction = !checkKey.isDown;
} }
if (skipNextInstruction) cpu.programCounter += 2; if (skipNextInstruction) cpu.programCounter += 2;
@ -657,6 +698,8 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
// the key in Vx // the key in Vx
else if (opLowByte == 0x0A) else if (opLowByte == 0x0A)
{ {
cpu.state = chip8state_await_input;
cpu.keyToStoreToRegisterIndex = regNum;
} }
// LD DT, Vx - Fx15 - Set delay timer = Vx // LD DT, Vx - Fx15 - Set delay timer = Vx
else if (opLowByte == 0x15) else if (opLowByte == 0x15)
@ -676,15 +719,16 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input,
// LD F, Vx - Fx29 - Set I = location of sprite for digit Vx // LD F, Vx - Fx29 - Set I = location of sprite for digit Vx
else if (opLowByte == 0x29) else if (opLowByte == 0x29)
{ {
u8 hexCharFromFontSet = (0x0F & opHighByte); u8 hexCharFromFontSet = *vx;
DQNT_ASSERT(hexCharFromFontSet >= 0x00 && DQNT_ASSERT(hexCharFromFontSet >= 0x00 &&
hexCharFromFontSet <= 0x0F); hexCharFromFontSet <= 0x0F);
const u8 BITS_IN_BYTE = 8; const u8 BITS_IN_BYTE = 8;
u8 fontSizeInMem = BITS_IN_BYTE * 5; u8 fontSizeInMem = BITS_IN_BYTE * 5;
u16 startMemAddrOfFontSet = 0; u16 startMemAddrOfFontSet = 0;
cpu.I = (hexCharFromFontSet * fontSizeInMem) *
startMemAddrOfFontSet; cpu.I = startMemAddrOfFontSet +
(hexCharFromFontSet * fontSizeInMem);
} }
// LD B, Vx - Fx33 - Store BCD representations of Vx in memory // LD B, Vx - Fx33 - Store BCD representations of Vx in memory
// locations I, I+1 and I+2 // locations I, I+1 and I+2

View File

@ -20,6 +20,27 @@ enum Key
key_left, key_left,
key_right, key_right,
key_escape, key_escape,
key_7,
key_8,
key_9,
key_0,
key_U,
key_I,
key_O,
key_P,
key_J,
key_K,
key_L,
key_colon,
key_M,
key_comma,
key_dot,
key_forward_slash,
key_count, key_count,
}; };
@ -42,6 +63,26 @@ typedef struct PlatformInput
KeyState left; KeyState left;
KeyState right; KeyState right;
KeyState escape; KeyState escape;
KeyState key_7;
KeyState key_8;
KeyState key_9;
KeyState key_0;
KeyState key_U;
KeyState key_I;
KeyState key_O;
KeyState key_P;
KeyState key_J;
KeyState key_K;
KeyState key_L;
KeyState key_colon;
KeyState key_M;
KeyState key_comma;
KeyState key_dot;
KeyState key_forward_slash;
}; };
}; };
} PlatformInput; } PlatformInput;

View File

@ -53,7 +53,7 @@ i32 dqnt_strcmp (const char *a, const char *b);
i32 dqnt_strlen (const char *a); i32 dqnt_strlen (const char *a);
char *dqnt_strncpy(char *dest, const char *src, i32 numChars); char *dqnt_strncpy(char *dest, const char *src, i32 numChars);
bool dqnt_str_reverse(char *const buf, const i32 bufSize); bool dqnt_str_reverse(char *buf, const i32 bufSize);
i32 dqnt_str_to_i32 (char *const buf, const i32 bufSize); i32 dqnt_str_to_i32 (char *const buf, const i32 bufSize);
void dqnt_i32_to_str (i32 value, char *buf, i32 bufSize); void dqnt_i32_to_str (i32 value, char *buf, i32 bufSize);
@ -124,6 +124,10 @@ bool dqnt_char_is_alphanum(char c)
i32 dqnt_strcmp(const char *a, const char *b) i32 dqnt_strcmp(const char *a, const char *b)
{ {
if (!a && !b) return -1;
if (!a) return -1;
if (!b) return -1;
while ((*a) == (*b)) while ((*a) == (*b))
{ {
if (!(*a)) return 0; if (!(*a)) return 0;
@ -137,7 +141,7 @@ i32 dqnt_strcmp(const char *a, const char *b)
i32 dqnt_strlen(const char *a) i32 dqnt_strlen(const char *a)
{ {
i32 result = 0; i32 result = 0;
while (a[result]) result++; while (a && a[result]) result++;
return result; return result;
} }
@ -153,7 +157,7 @@ char *dqnt_strncpy(char *dest, const char *src, i32 numChars)
return dest; return dest;
} }
bool dqnt_str_reverse(char *const buf, const i32 bufSize) bool dqnt_str_reverse(char *buf, const i32 bufSize)
{ {
if (!buf) return false; if (!buf) return false;
i32 mid = bufSize / 2; i32 mid = bufSize / 2;
@ -253,6 +257,10 @@ wchar_t dqnt_wchar_ascii_to_lower(wchar_t character)
i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b) i32 dqnt_wstrcmp(const wchar_t *a, const wchar_t *b)
{ {
if (!a && !b) return -1;
if (!a) return -1;
if (!b) return -1;
while ((*a) == (*b)) while ((*a) == (*b))
{ {
if (!(*a)) return 0; if (!(*a)) return 0;

View File

@ -110,7 +110,6 @@ FILE_SCOPE void win32_process_messages(HWND window, PlatformInput *input)
MSG msg; MSG msg;
while (PeekMessage(&msg, window, 0, 0, PM_REMOVE)) while (PeekMessage(&msg, window, 0, 0, PM_REMOVE))
{ {
switch (msg.message) switch (msg.message)
{ {
case WM_SYSKEYDOWN: case WM_SYSKEYDOWN:
@ -125,6 +124,26 @@ FILE_SCOPE void win32_process_messages(HWND window, PlatformInput *input)
case VK_LEFT: win32_parse_key_msg(&input->left, msg); break; case VK_LEFT: win32_parse_key_msg(&input->left, msg); break;
case VK_RIGHT: win32_parse_key_msg(&input->right, msg); break; case VK_RIGHT: win32_parse_key_msg(&input->right, msg); break;
case '7': win32_parse_key_msg(&input->key_7, msg); break;
case '8': win32_parse_key_msg(&input->key_8, msg); break;
case '9': win32_parse_key_msg(&input->key_9, msg); break;
case '0': win32_parse_key_msg(&input->key_0, msg); break;
case 'U': win32_parse_key_msg(&input->key_U, msg); break;
case 'I': win32_parse_key_msg(&input->key_I, msg); break;
case 'O': win32_parse_key_msg(&input->key_O, msg); break;
case 'P': win32_parse_key_msg(&input->key_P, msg); break;
case 'J': win32_parse_key_msg(&input->key_J, msg); break;
case 'K': win32_parse_key_msg(&input->key_K, msg); break;
case 'L': win32_parse_key_msg(&input->key_L, msg); break;
case ';': win32_parse_key_msg(&input->key_colon, msg); break;
case 'M': win32_parse_key_msg(&input->key_M, msg); break;
case ',': win32_parse_key_msg(&input->key_comma, msg); break;
case '.': win32_parse_key_msg(&input->key_dot, msg); break;
case '/': win32_parse_key_msg(&input->key_forward_slash, msg); break;
case VK_ESCAPE: case VK_ESCAPE:
{ {
win32_parse_key_msg(&input->escape, msg); win32_parse_key_msg(&input->escape, msg);
@ -241,7 +260,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
platformMemory.permanentMemSize = DQNT_ARRAY_COUNT(stackMemory); platformMemory.permanentMemSize = DQNT_ARRAY_COUNT(stackMemory);
QueryPerformanceFrequency(&globalQueryPerformanceFrequency); QueryPerformanceFrequency(&globalQueryPerformanceFrequency);
const f32 TARGET_FRAMES_PER_S = 60.0f; const f32 TARGET_FRAMES_PER_S = 180.0f;
f32 targetSecondsPerFrame = 1 / TARGET_FRAMES_PER_S; f32 targetSecondsPerFrame = 1 / TARGET_FRAMES_PER_S;
f32 frameTimeInS = 0.0f; f32 frameTimeInS = 0.0f;
globalRunning = true; globalRunning = true;