From 2aa5bffb79e34d8fc79a30c7c2bb8e5873051db9 Mon Sep 17 00:00:00 2001 From: Doyle Thai Date: Thu, 6 Apr 2017 02:18:41 +1000 Subject: [PATCH] Fix some register bugs --- src/dchip8.cpp | 106 ++++++++++++++++++++++++++++++------------ src/dchip8_platform.h | 41 ++++++++++++++++ src/dqnt.h | 14 ++++-- src/win32_dchip8.cpp | 23 ++++++++- 4 files changed, 148 insertions(+), 36 deletions(-) diff --git a/src/dchip8.cpp b/src/dchip8.cpp index 955be53..f6c8a89 100644 --- a/src/dchip8.cpp +++ b/src/dchip8.cpp @@ -10,6 +10,7 @@ enum Chip8State { chip8state_init, chip8state_load_file, + chip8state_await_input, chip8state_running, chip8state_off, }; @@ -65,6 +66,7 @@ typedef struct Chip8CPU u8 stackPointer; u16 stack[16]; + u8 keyToStoreToRegisterIndex; enum Chip8State state; } Chip8CPU; @@ -285,7 +287,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, if (cpu.state == chip8state_load_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) <= memory.permanentMemSize); @@ -305,6 +307,25 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, } #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) { u8 opHighByte = mainMem[cpu.programCounter++]; @@ -356,20 +377,20 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, { u8 regNum = (0x0F & opHighByte); DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray)); + u8 *vx = &cpu.registerArray[regNum]; + u8 valToCheck = opLowByte; // SE Vx, byte - 3xkk - Skip next instruction if Vx == kk if (opFirstNibble == 0x30) { - if (cpu.registerArray[regNum] == valToCheck) - cpu.programCounter += 2; + if (*vx == valToCheck) cpu.programCounter += 2; } // SNE Vx, byte - 4xkk - Skip next instruction if Vx == kk else { DQNT_ASSERT(opFirstNibble == 0x40); - if (cpu.registerArray[regNum] != valToCheck) - cpu.programCounter += 2; + if (*vx != valToCheck) cpu.programCounter += 2; } } break; @@ -383,11 +404,10 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, u8 secondRegNum = (0xF0 & opLowByte) >> 4; DQNT_ASSERT(secondRegNum < DQNT_ARRAY_COUNT(cpu.registerArray)); - if (cpu.registerArray[firstRegNum] == - cpu.registerArray[secondRegNum]) - { - cpu.programCounter++; - } + u8 *vx = &cpu.registerArray[firstRegNum]; + u8 *vy = &cpu.registerArray[secondRegNum]; + + if (*vx == *vy) cpu.programCounter += 2; } break; @@ -398,16 +418,17 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray)); u8 valToOperateOn = opLowByte; + u8 *vx = &cpu.registerArray[regNum]; // LD Vx, byte - 6xkk - Set Vx = kk if (opFirstNibble == 0x60) { - cpu.registerArray[regNum] = valToOperateOn; + *vx = valToOperateOn; } // ADD Vx, byte - 7xkk - Set Vx = Vx + kk else { DQNT_ASSERT(opFirstNibble == 0x70); - cpu.registerArray[regNum] += valToOperateOn; + *vx += valToOperateOn; } } break; @@ -444,26 +465,31 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, // XOR Vx, Vy - 8xy3 - Set Vx = Vx XOR Vy else if (opFourthNibble == 0x03) { - u8 result = (*vx & *vy); + u8 result = (*vx ^ *vy); *vx = result; } // ADD Vx, Vy - 8xy4 - Set Vx = Vx + Vy, set VF = carry else if (opFourthNibble == 0x04) { 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 else if (opFourthNibble == 0x05) { if (*vx > *vy) + { cpu.VF = 1; + *vx -= *vy; + } else + { cpu.VF = 0; + *vx = (u8)(256 + *vx - *vy); + } - *vx -= *vy; } // SHR Vx {, Vy} - 8xy6 - Set Vx = Vx SHR 1 else if (opFourthNibble == 0x06) @@ -479,11 +505,16 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, else if (opFourthNibble == 0x07) { if (*vy > *vx) + { cpu.VF = 1; + *vx = *vy - *vx; + } else + { cpu.VF = 0; + *vx = (u8)(256 + *vy - *vx); + } - *vx = *vy - *vx; } // SHL Vx {, Vy} - 8xyE - Set Vx = SHL 1 else @@ -526,7 +557,7 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, // JP V0, addr - Bnnn - Jump to location (nnn + V0) case 0xB0: { - u8 addr = opLowByte + cpu.V0; + u16 addr = (((0x0F & opHighByte) << 8) | opLowByte) + cpu.V0; cpu.programCounter = addr; } break; @@ -534,14 +565,15 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, // RND Vx, byte - Cxkk - Set Vx = random byte AND kk case 0xC0: { - u8 firstRegNum = (0x0F & opHighByte); - DQNT_ASSERT(firstRegNum < DQNT_ARRAY_COUNT(cpu.registerArray)); - - u8 andBits = opLowByte; - u8 *vx = &cpu.registerArray[firstRegNum]; + u8 regNum = (0x0F & opHighByte); + DQNT_ASSERT(regNum < DQNT_ARRAY_COUNT(cpu.registerArray)); + u8 *vx = &cpu.registerArray[regNum]; 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; @@ -595,7 +627,6 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, bool spriteBit = ((spriteBytes >> bitShift) & 1); bool pixelIsOn = (pixelWasOn ^ spriteBit); - // TODO(doyle): wrap pixels around // NOTE: If caused a pixel to XOR into off, then this is // known as a "collision" in chip8 if (pixelWasOn && !pixelIsOn) @@ -622,20 +653,30 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, case 0xE0: { - // TODO(doyle): Implement key checks - u8 checkKey = (0x0F & opHighByte); + u8 regNum = (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 // of Vx is pressed - bool skipNextInstruction = false; if (opLowByte == 0x9E) { + skipNextInstruction = checkKey.isDown; } // SKNP Vx - ExA1 - Skip next instruction if key with the value // of Vx is not pressed else { DQNT_ASSERT(opLowByte == 0xA1); + skipNextInstruction = !checkKey.isDown; } if (skipNextInstruction) cpu.programCounter += 2; @@ -657,6 +698,8 @@ void dchip8_update(PlatformRenderBuffer renderBuffer, PlatformInput input, // the key in Vx else if (opLowByte == 0x0A) { + cpu.state = chip8state_await_input; + cpu.keyToStoreToRegisterIndex = regNum; } // LD DT, Vx - Fx15 - Set delay timer = Vx 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 else if (opLowByte == 0x29) { - u8 hexCharFromFontSet = (0x0F & opHighByte); + u8 hexCharFromFontSet = *vx; DQNT_ASSERT(hexCharFromFontSet >= 0x00 && hexCharFromFontSet <= 0x0F); const u8 BITS_IN_BYTE = 8; u8 fontSizeInMem = BITS_IN_BYTE * 5; u16 startMemAddrOfFontSet = 0; - cpu.I = (hexCharFromFontSet * fontSizeInMem) * - startMemAddrOfFontSet; + + cpu.I = startMemAddrOfFontSet + + (hexCharFromFontSet * fontSizeInMem); } // LD B, Vx - Fx33 - Store BCD representations of Vx in memory // locations I, I+1 and I+2 diff --git a/src/dchip8_platform.h b/src/dchip8_platform.h index 2d47c6d..4b6df8d 100644 --- a/src/dchip8_platform.h +++ b/src/dchip8_platform.h @@ -20,6 +20,27 @@ enum Key key_left, key_right, 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, }; @@ -42,6 +63,26 @@ typedef struct PlatformInput KeyState left; KeyState right; 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; diff --git a/src/dqnt.h b/src/dqnt.h index 31f8acd..51de3bd 100644 --- a/src/dqnt.h +++ b/src/dqnt.h @@ -53,7 +53,7 @@ i32 dqnt_strcmp (const char *a, const char *b); i32 dqnt_strlen (const char *a); 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); 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) { + if (!a && !b) return -1; + if (!a) return -1; + if (!b) return -1; + while ((*a) == (*b)) { if (!(*a)) return 0; @@ -137,7 +141,7 @@ i32 dqnt_strcmp(const char *a, const char *b) i32 dqnt_strlen(const char *a) { i32 result = 0; - while (a[result]) result++; + while (a && a[result]) result++; return result; } @@ -153,7 +157,7 @@ char *dqnt_strncpy(char *dest, const char *src, i32 numChars) 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; 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) { + if (!a && !b) return -1; + if (!a) return -1; + if (!b) return -1; + while ((*a) == (*b)) { if (!(*a)) return 0; diff --git a/src/win32_dchip8.cpp b/src/win32_dchip8.cpp index e47da40..da75e19 100644 --- a/src/win32_dchip8.cpp +++ b/src/win32_dchip8.cpp @@ -110,7 +110,6 @@ FILE_SCOPE void win32_process_messages(HWND window, PlatformInput *input) MSG msg; while (PeekMessage(&msg, window, 0, 0, PM_REMOVE)) { - switch (msg.message) { 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_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: { win32_parse_key_msg(&input->escape, msg); @@ -241,7 +260,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, platformMemory.permanentMemSize = DQNT_ARRAY_COUNT(stackMemory); 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 frameTimeInS = 0.0f; globalRunning = true;