diff --git a/src/libs/libchip8/BitmappedGraphics.cpp b/src/libs/libchip8/BitmappedGraphics.cpp index 8eb085f..813109e 100644 --- a/src/libs/libchip8/BitmappedGraphics.cpp +++ b/src/libs/libchip8/BitmappedGraphics.cpp @@ -11,8 +11,8 @@ void BitmappedGraphics::initialise() { setHighResolution(false); } -int BitmappedGraphics::draw(const Memory& memory, int address, int drawX, int drawY, int width, int height) { - auto bytesPerRow = width / 8; +int BitmappedGraphics::draw(const Memory& memory, int address, const int drawX, const int drawY, const int width, const int height) { + const auto bytesPerRow = width / 8; size_t hits = 0; for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { if (isPlaneSelected(plane)) { @@ -20,79 +20,68 @@ int BitmappedGraphics::draw(const Memory& memory, int address, int drawX, int dr address += height * bytesPerRow; } } - setDirty(true); + setDirty(); if (!m_countRowHits) hits = hits > 0 ? 1 : 0; return (int)hits; } -void BitmappedGraphics::scrollDown(int count) { - for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { +void BitmappedGraphics::scrollDown(const int count) { + for (int plane = 0; plane < getNumberOfPlanes(); ++plane) maybeScrollDown(plane, count); - } - setDirty(true); + setDirty(); } void BitmappedGraphics::scrollUp(int count) { - for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { + for (int plane = 0; plane < getNumberOfPlanes(); ++plane) maybeScrollUp(plane, count); - } - setDirty(true); + setDirty(); } void BitmappedGraphics::scrollLeft() { - for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { + for (int plane = 0; plane < getNumberOfPlanes(); ++plane) maybeScrollLeft(plane); - } - setDirty(true); + setDirty(); } void BitmappedGraphics::scrollRight() { - for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { + for (int plane = 0; plane < getNumberOfPlanes(); ++plane) maybeScrollRight(plane); - } - setDirty(true); + setDirty(); } void BitmappedGraphics::clear() { - for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { + for (int plane = 0; plane < getNumberOfPlanes(); ++plane) maybeClear(plane); - } - setDirty(true); + setDirty(); } -bool BitmappedGraphics::isPlaneSelected(int plane) const { - auto mask = 1 << plane; - auto selected = (getPlaneMask() & mask) != 0; - return selected; +bool BitmappedGraphics::isPlaneSelected(const int plane) const { + const auto mask = 1 << plane; + return (getPlaneMask() & mask) != 0; } -void BitmappedGraphics::maybeScrollDown(int plane, int count) { - if (isPlaneSelected(plane)) { +void BitmappedGraphics::maybeScrollDown(const int plane, const int count) { + if (isPlaneSelected(plane)) m_planes[plane].scrollDown(count); - } } -void BitmappedGraphics::maybeScrollUp(int plane, int count) { - if (isPlaneSelected(plane)) { +void BitmappedGraphics::maybeScrollUp(const int plane, const int count) { + if (isPlaneSelected(plane)) m_planes[plane].scrollUp(count); - } } -void BitmappedGraphics::maybeScrollLeft(int plane) { - if (isPlaneSelected(plane)) { +void BitmappedGraphics::maybeScrollLeft(const int plane) { + if (isPlaneSelected(plane)) m_planes[plane].scrollLeft(); - } } -void BitmappedGraphics::maybeScrollRight(int plane) { - if (isPlaneSelected(plane)) { +void BitmappedGraphics::maybeScrollRight(const int plane) { + if (isPlaneSelected(plane)) m_planes[plane].scrollRight(); - } } -void BitmappedGraphics::maybeClear(int plane) { - if (isPlaneSelected(plane)) { +void BitmappedGraphics::maybeClear(const int plane) { + if (isPlaneSelected(plane)) m_planes[plane].clear(); - } } diff --git a/src/libs/libchip8/BitmappedGraphics.h b/src/libs/libchip8/BitmappedGraphics.h index 715d206..74a66f2 100644 --- a/src/libs/libchip8/BitmappedGraphics.h +++ b/src/libs/libchip8/BitmappedGraphics.h @@ -27,11 +27,11 @@ class BitmappedGraphics final { return 1 << getNumberOfPlanes(); } - const std::vector& getPlanes() const { + const std::vector& planes() const { return m_planes; } - std::vector& getPlanesMutable() { + std::vector& planes() { return m_planes; } @@ -39,11 +39,10 @@ class BitmappedGraphics final { return m_highResolution; } - void setHighResolution(bool value) { + void setHighResolution(const bool value) { m_highResolution = value; - for (int plane = 0; plane < getNumberOfPlanes(); ++plane) { - m_planes[plane].setHighResolution(value); - } + for (auto& plane : m_planes) + plane.setHighResolution(value); } bool getLowResolution() const { @@ -62,7 +61,7 @@ class BitmappedGraphics final { return m_planeMask; } - void setPlaneMask(int value) { + void setPlaneMask(const int value) { m_planeMask = value; } @@ -70,7 +69,7 @@ class BitmappedGraphics final { return m_dirty; } - void setDirty(bool value) { + void setDirty(const bool value = true) { m_dirty = value; } diff --git a/src/libs/libchip8/Chip8.cpp b/src/libs/libchip8/Chip8.cpp index c3e8c6f..683bc7b 100644 --- a/src/libs/libchip8/Chip8.cpp +++ b/src/libs/libchip8/Chip8.cpp @@ -18,45 +18,44 @@ Chip8::Chip8(const Memory& memory, const KeyboardDevice& keyboard, const Bitmapp } void Chip8::initialise() { - m_finished = false; + setFinished(false); - m_pc = m_configuration.getStartAddress(); - m_i = 0; // Reset index register - m_sp = 0; // Reset stack pointer + PC() = configuration().getStartAddress(); + indirector() = 0; + SP() = 0; - m_display.initialise(); + display().initialise(); // Clear stack - std::fill(m_stack.begin(), m_stack.end(), (uint16_t)0U); + std::fill(stack().begin(), stack().end(), (uint16_t)0U); // Clear registers V0-VF - std::fill(m_v.begin(), m_v.end(), (uint8_t)0U); + std::fill(registers().begin(), registers().end(), (uint8_t)0U); // Clear memory - m_memory.clear(); + memory().clear(); // Load fonts - std::copy_n(m_standardFont.cbegin(), m_standardFont.size(), m_memory.getBusMutable().begin() + StandardFontOffset); + std::copy_n(m_standardFont.cbegin(), m_standardFont.size(), memory().bus().begin() + StandardFontOffset); // Reset timers - m_delayTimer = m_soundTimer = 0; + delayTimer() = soundTimer() = 0; m_soundPlaying = false; - m_waitingForKeyPress = false; + setWaitingForKeyPress(false); m_randomNumberGenerator.seed(std::random_device()()); } void Chip8::loadGame(const std::string& game) { - m_memory.loadRom(game, m_configuration.getLoadAddress()); + memory().loadRom(game, m_configuration.getLoadAddress()); } void Chip8::step() { - if (m_waitingForKeyPress) { + if (m_waitingForKeyPress) waitForKeyPress(); - } else { + else emulateCycle(); - } } void Chip8::updateTimers() { @@ -75,7 +74,7 @@ void Chip8::onBeepStopped() { } void Chip8::onEmulatingCycle(uint16_t programCounter, uint16_t instruction, int address, int operand, int n, int x, int y) { - m_mnemomicFormat.clear(); + mnemomicFormat().clear(); EmulatingCycle.fire(InstructionEventArgs(programCounter, instruction, address, operand, n, x, y)); } @@ -91,33 +90,29 @@ void Chip8::emulateCycle() { // <- n -> // <- x -> // <- y -> - m_opcode = m_memory.getWord(m_pc); + m_opcode = memory().getWord(PC()); auto nnn = m_opcode & 0xfff; auto nn = m_opcode & 0xff; auto n = nn & 0xf; auto x = (m_opcode & 0xf00) >> 8; auto y = (nn & 0xf0) >> 4; - if ((m_pc % 2) == 1) { - if (!m_configuration.getAllowMisalignedOpcodes()) { - throw std::runtime_error("Instruction is not on an aligned address."); - } - } + if (((PC() % 2) == 1) && !configuration().getAllowMisalignedOpcodes()) + throw std::runtime_error("Instruction is not on an aligned address."); - auto programCounter = m_pc; - m_pc += 2; + auto programCounter = PC(); + PC() += 2; onEmulatingCycle(programCounter, m_opcode, nnn, nn, n, x, y); - if (!emulateInstruction(nnn, nn, n, x, y)) { + if (!emulateInstruction(nnn, nn, n, x, y)) throw std::runtime_error("Illegal instruction (is the processor type set correctly?)"); - } onEmulatedCycle(programCounter, m_opcode, nnn, nn, n, x, y); } void Chip8::draw(int x, int y, int width, int height) { - auto hits = m_display.draw(m_memory, m_i, m_v[x], m_v[y], width, height); - m_v[0xf] = (uint8_t)hits; + const auto hits = display().draw(memory(), indirector(), registers()[x], registers()[y], width, height); + registers()[0xf] = (uint8_t)hits; } bool Chip8::emulateInstruction(int nnn, int nn, int n, int x, int y) { @@ -371,123 +366,119 @@ bool Chip8::emulateInstructions_0(int, int nn, int, int, int) { //// void Chip8::CLS() { - m_mnemomicFormat = "CLS"; - m_display.clear(); + mnemomicFormat() = "CLS"; + display().clear(); } void Chip8::RET() { - m_mnemomicFormat = "RET"; - m_pc = m_stack[--m_sp & 0xF]; + mnemomicFormat() = "RET"; + PC() = stack()[--SP() & 0xF]; } void Chip8::JP(int nnn) { - m_mnemomicFormat = "JP %1$03X"; - m_pc = (uint16_t)nnn; + mnemomicFormat() = "JP %1$03X"; + PC() = (uint16_t)nnn; } void Chip8::CALL(int nnn) { - m_mnemomicFormat = "CALL %1$03X"; - m_stack[m_sp++] = m_pc; - m_pc = (uint16_t)nnn; + mnemomicFormat() = "CALL %1$03X"; + stack()[SP()++] = PC(); + PC() = (uint16_t)nnn; } void Chip8::SE_REG_IMM(int x, int nn) { - m_mnemomicFormat = "SE V%4$01X,%2$02X"; - if (m_v[x] == nn) { - m_pc += 2; - } + mnemomicFormat() = "SE V%4$01X,%2$02X"; + if (registers()[x] == nn) + PC() += 2; } void Chip8::SNE_REG_IMM(int x, int nn) { - m_mnemomicFormat = "SNE V%4$01X,%2$02X"; - if (m_v[x] != nn) { - m_pc += 2; - } + mnemomicFormat() = "SNE V%4$01X,%2$02X"; + if (registers()[x] != nn) + PC() += 2; } void Chip8::SE(int x, int y) { - m_mnemomicFormat = "SE V%4$01X,V%5$01X"; - if (m_v[x] == m_v[y]) { - m_pc += 2; - } + mnemomicFormat() = "SE V%4$01X,V%5$01X"; + if (registers()[x] == registers()[y]) + PC() += 2; } void Chip8::LD_REG_IMM(int x, int nn) { - m_mnemomicFormat = "LD V%4$01X,%2$02X"; - m_v[x] = (uint8_t)nn; + mnemomicFormat() = "LD V%4$01X,%2$02X"; + registers()[x] = (uint8_t)nn; } void Chip8::ADD_REG_IMM(int x, int nn) { m_mnemomicFormat = "ADD V%4$01X,%2$02X"; - m_v[x] += (uint8_t)nn; + registers()[x] += (uint8_t)nn; } void Chip8::LD(int x, int y) { - m_mnemomicFormat = "LD V%4$01X,V%5$01X"; - m_v[x] = m_v[y]; + mnemomicFormat() = "LD V%4$01X,V%5$01X"; + registers()[x] = registers()[y]; } void Chip8::OR(int x, int y) { - m_mnemomicFormat = "OR V%4$01X,V%5$01X"; - m_v[x] |= m_v[y]; + mnemomicFormat() = "OR V%4$01X,V%5$01X"; + registers()[x] |= registers()[y]; } void Chip8::AND(int x, int y) { - m_mnemomicFormat = "AND V%4$01X,V%5$01X"; - m_v[x] &= m_v[y]; + mnemomicFormat() = "AND V%4$01X,V%5$01X"; + registers()[x] &= registers()[y]; } void Chip8::XOR(int x, int y) { - m_mnemomicFormat = "XOR V%4$01X,V%5$01X"; - m_v[x] ^= m_v[y]; + mnemomicFormat() = "XOR V%4$01X,V%5$01X"; + registers()[x] ^= registers()[y]; } void Chip8::ADD(int x, int y) { - m_mnemomicFormat = "ADD V%4$01X,V%5$01X"; - m_v[0xf] = (uint8_t)(m_v[y] > (0xff - m_v[x]) ? 1 : 0); - m_v[x] += m_v[y]; + mnemomicFormat() = "ADD V%4$01X,V%5$01X"; + registers()[0xf] = (uint8_t)(registers()[y] > (0xff - registers()[x]) ? 1 : 0); + registers()[x] += registers()[y]; } void Chip8::SUB(int x, int y) { - m_mnemomicFormat = "SUB V%4$01X,V%5$01X"; - m_v[0xf] = (uint8_t)(m_v[x] >= m_v[y] ? 1 : 0); - m_v[x] -= m_v[y]; + mnemomicFormat() = "SUB V%4$01X,V%5$01X"; + registers()[0xf] = (uint8_t)(registers()[x] >= registers()[y] ? 1 : 0); + registers()[x] -= registers()[y]; } void Chip8::SHR(int x, int y) { // https://github.com/Chromatophore/HP48-Superchip#8xy6--8xye // Bit shifts X register by 1, VIP: shifts Y by one and places in X, HP48-SC: ignores Y field, shifts X - m_mnemomicFormat = "SHR V%4$01X,V%5$01X"; - m_v[0xf] = (uint8_t)(m_v[y] & 0x1); - m_v[y] >>= 1; - m_v[x] = m_v[y]; + mnemomicFormat() = "SHR V%4$01X,V%5$01X"; + registers()[0xf] = (uint8_t)(registers()[y] & 0x1); + registers()[y] >>= 1; + registers()[x] = registers()[y]; } void Chip8::SUBN(int x, int y) { - m_mnemomicFormat = "SUBN V%4$01X,V%5$01X"; - m_v[0xf] = (uint8_t)(m_v[x] > m_v[y] ? 0 : 1); - m_v[x] = (uint8_t)(m_v[y] - m_v[x]); + mnemomicFormat() = "SUBN V%4$01X,V%5$01X"; + registers()[0xf] = (uint8_t)(registers()[x] > registers()[y] ? 0 : 1); + registers()[x] = (uint8_t)(registers()[y] - registers()[x]); } void Chip8::SHL(int x, int y) { // https://github.com/Chromatophore/HP48-Superchip#8xy6--8xye // Bit shifts X register by 1, VIP: shifts Y by one and places in X, HP48-SC: ignores Y field, shifts X - m_mnemomicFormat = "SHL V%4$01X,V%5$01X"; - m_v[0xf] = (uint8_t)((m_v[y] & 0x80) == 0 ? 0 : 1); - m_v[y] <<= 1; - m_v[x] = m_v[y]; + mnemomicFormat() = "SHL V%4$01X,V%5$01X"; + registers()[0xf] = (uint8_t)((registers()[y] & 0x80) == 0 ? 0 : 1); + registers()[y] <<= 1; + registers()[x] = registers()[y]; } void Chip8::SNE(int x, int y) { - m_mnemomicFormat = "SNE V%4$01X,V%5$01X"; - if (m_v[x] != m_v[y]) { - m_pc += 2; - } + mnemomicFormat() = "SNE V%4$01X,V%5$01X"; + if (registers()[x] != registers()[y]) + PC() += 2; } void Chip8::LD_I(int nnn) { - m_mnemomicFormat = "LD I,%1$03X"; - m_i = (uint16_t)nnn; + mnemomicFormat() = "LD I,%1$03X"; + indirector() = (uint16_t)nnn; } void Chip8::JP_V0(int, int nnn) { @@ -496,121 +487,116 @@ void Chip8::JP_V0(int, int nnn) { // VIP: correctly jumps based on v0 // HP48 -SC: reads highest nibble of address to select // register to apply to address (high nibble pulls double duty) - m_mnemomicFormat = "JP V0,%1$03X"; - m_pc = (uint16_t)(m_v[0] + nnn); + mnemomicFormat() = "JP V0,%1$03X"; + PC() = (uint16_t)(registers()[0] + nnn); } void Chip8::RND(int x, int nn) { - m_mnemomicFormat = "RND V%4$01X,%2$02X"; + mnemomicFormat() = "RND V%4$01X,%2$02X"; auto random = m_eightBitDistribution(m_randomNumberGenerator); - m_v[x] = (uint8_t)(random & nn); + registers()[x] = (uint8_t)(random & nn); } void Chip8::DRW(int x, int y, int n) { - m_mnemomicFormat = "DRW V%4$01X,V%5$01X,%3$01X"; + mnemomicFormat() = "DRW V%4$01X,V%5$01X,%3$01X"; draw(x, y, 8, n); } void Chip8::SKP(int x) { - m_mnemomicFormat = "SKP V%4$01X"; - if (m_keyboard.isKeyPressed(m_v[x])) { - m_pc += 2; - } + mnemomicFormat() = "SKP V%4$01X"; + if (keyboard().isKeyPressed(registers()[x])) + PC() += 2; } void Chip8::SKNP(int x) { - m_mnemomicFormat = "SKNP V%4$01X"; - if (!m_keyboard.isKeyPressed(m_v[x])) { - m_pc += 2; - } + mnemomicFormat() = "SKNP V%4$01X"; + if (!keyboard().isKeyPressed(registers()[x])) + PC() += 2; } void Chip8::LD_Vx_II(int x) { // https://github.com/Chromatophore/HP48-Superchip#fx55--fx65 // Saves/Loads registers up to X at I pointer - VIP: increases I, HP48-SC: I remains static - m_mnemomicFormat = "LD V%4$01X,[I]"; - std::copy_n(m_memory.getBus().cbegin() + m_i, x + 1, m_v.begin()); - m_i += x + 1; + mnemomicFormat() = "LD V%4$01X,[I]"; + std::copy_n(memory().bus().cbegin() + indirector(), x + 1, registers().begin()); + indirector() += x + 1; } void Chip8::LD_II_Vx(int x) { // https://github.com/Chromatophore/HP48-Superchip#fx55--fx65 // Saves/Loads registers up to X at I pointer - VIP: increases I, HP48-SC: I remains static - m_mnemomicFormat = "LD [I],V%4$01X"; - std::copy_n(m_v.cbegin(), x + 1, m_memory.getBusMutable().begin() + m_i); - m_i += x + 1; + mnemomicFormat() = "LD [I],V%4$01X"; + std::copy_n(registers().cbegin(), x + 1, memory().bus().begin() + indirector()); + indirector() += x + 1; } void Chip8::LD_B_Vx(int x) { - m_mnemomicFormat = "LD B,V%4$01X"; - auto content = m_v[x]; - m_memory.set(m_i, (uint8_t)(content / 100)); - m_memory.set(m_i + 1, (uint8_t)((content / 10) % 10)); - m_memory.set(m_i + 2, (uint8_t)((content % 100) % 10)); + mnemomicFormat() = "LD B,V%4$01X"; + auto content = registers()[x]; + memory().set(indirector(), (uint8_t)(content / 100)); + memory().set(indirector() + 1, (uint8_t)((content / 10) % 10)); + memory().set(indirector() + 2, (uint8_t)((content % 100) % 10)); } void Chip8::LD_F_Vx(int x) { - m_mnemomicFormat = "LD F,V%4$01X"; - m_i = (uint16_t)(StandardFontOffset + (StandardFontSize * m_v[x])); + mnemomicFormat() = "LD F,V%4$01X"; + indirector() = (uint16_t)(StandardFontOffset + (StandardFontSize * registers()[x])); } void Chip8::ADD_I_Vx(int x) { // From wikipedia entry on CHIP-8: // VF is set to 1 when there is a range overflow (I+VX>0xFFF), and to 0 // when there isn't. This is an undocumented feature of the CHIP-8 and used by the Spacefight 2091! game - m_mnemomicFormat = "ADD I,V%4$01X"; - auto sum = m_i + m_v[x]; + mnemomicFormat() = "ADD I,V%4$01X"; + auto sum = indirector() + registers()[x]; auto masked = sum & 0xFFF; - m_v[0xf] = sum == masked ? 0 : 1; - m_i = masked; + registers()[0xf] = sum == masked ? 0 : 1; + indirector() = masked; } void Chip8::LD_ST_Vx(int x) { - m_mnemomicFormat = "LD ST,V%4$01X"; - m_soundTimer = m_v[x]; + mnemomicFormat() = "LD ST,V%4$01X"; + soundTimer() = registers()[x]; } void Chip8::LD_DT_Vx(int x) { - m_mnemomicFormat = "LD DT,V%4$01X"; - m_delayTimer = m_v[x]; + mnemomicFormat() = "LD DT,V%4$01X"; + delayTimer() = registers()[x]; } void Chip8::LD_Vx_K(int x) { - m_mnemomicFormat = "LD V%4$01X,K"; - m_waitingForKeyPress = true; - m_waitingForKeyPressRegister = x; + mnemomicFormat() = "LD V%4$01X,K"; + setWaitingForKeyPress(); + setWaitingForKeyPressRegister(x); } void Chip8::LD_Vx_DT(int x) { - m_mnemomicFormat = "LD V%4$01X,DT"; - m_v[x] = m_delayTimer; + mnemomicFormat() = "LD V%4$01X,DT"; + registers()[x] = delayTimer(); } //// void Chip8::waitForKeyPress() { int key; - if (m_keyboard.checkKeyPress(key)) { - m_waitingForKeyPress = false; - m_v[m_waitingForKeyPressRegister] = (uint8_t)key; + if (keyboard().checkKeyPress(key)) { + setWaitingForKeyPress(); + registers()[getWaitingForKeyPressRegister()] = (uint8_t)key; } } void Chip8::updateDelayTimer() { - if (m_delayTimer > 0) { - --m_delayTimer; - } + if (delayTimer() > 0) + --delayTimer(); } void Chip8::updateSoundTimer() { - if (m_soundTimer > 0) { - if (!m_soundPlaying) { + if (soundTimer() > 0) { + if (!m_soundPlaying) onBeepStarting(); - } - --m_soundTimer; + --soundTimer(); } else { - if (m_soundPlaying) { + if (m_soundPlaying) onBeepStopped(); - } } } diff --git a/src/libs/libchip8/Chip8.h b/src/libs/libchip8/Chip8.h index 1f71551..8ba27c2 100644 --- a/src/libs/libchip8/Chip8.h +++ b/src/libs/libchip8/Chip8.h @@ -38,131 +38,54 @@ class Chip8 { void updateTimers(); - uint16_t getProgramCounter() const { - return m_pc; - } + uint16_t PC() const { return m_pc; } + uint16_t& PC() { return m_pc; } - void setProgramCounter(uint16_t value) { - m_pc = value; - } - - const std::array& getRegisters() const { - return m_v; - } - - std::array& getRegistersMutable() { - return m_v; - } - - uint16_t getIndirector() const { - return m_i; - } - - void setIndirector(uint16_t value) { - m_i = value; - } - - const Memory& getMemory() const { - return m_memory; - } - - Memory& getMemoryMutable() { - return m_memory; - } - - const std::array& getStack() const { - return m_stack; - } + const std::array& registers() const { return m_v; } + std::array& registers() { return m_v; } - uint16_t getStackPointer() const { - return m_sp; - } - - uint8_t getDelayTimer() const { - return m_delayTimer; - } - - void setDelayTimer(uint8_t value) { - m_delayTimer = value; - } - - uint8_t getSoundTimer() const { - return m_soundTimer; - } - - void setSoundTimer(uint8_t value) { - m_soundTimer = value; - } - - bool isWaitingForKeyPress() const { - return m_waitingForKeyPress; - } + uint16_t indirector() const { return m_i; } + uint16_t& indirector() { return m_i; } - void setWaitingForKeyPress(bool value) { - m_waitingForKeyPress = value; - } + const Memory& memory() const { return m_memory; } + Memory& memory() {return m_memory; } - int getWaitingForKeyPressRegister() const { - return m_waitingForKeyPressRegister; - } + const std::array& stack() const { return m_stack; } + std::array& stack() { return m_stack; } - void setWaitingForKeyPressRegister(int value) { - m_waitingForKeyPressRegister = value; - } + uint16_t SP() const { return m_sp; } + uint16_t& SP() { return m_sp; } - const Configuration& getConfiguration() const { - return m_configuration; - } + uint8_t delayTimer() const { return m_delayTimer; } + uint8_t& delayTimer() { return m_delayTimer; } - const BitmappedGraphics& getDisplay() const { - return m_display; - } + uint8_t soundTimer() const { return m_soundTimer; } + uint8_t& soundTimer() { return m_soundTimer; } - BitmappedGraphics& getDisplayMutable() { - return m_display; - } + bool isWaitingForKeyPress() const { return m_waitingForKeyPress; } + void setWaitingForKeyPress(bool value = true) { m_waitingForKeyPress = value; } - const KeyboardDevice& getKeyboard() const { - return m_keyboard; - } + int getWaitingForKeyPressRegister() const { return m_waitingForKeyPressRegister; } + void setWaitingForKeyPressRegister(int value) { m_waitingForKeyPressRegister = value; } - KeyboardDevice& getKeyboardMutable() { - return m_keyboard; - } + const Configuration& configuration() const { return m_configuration; } - bool getDrawNeeded() const { - return m_display.getDirty(); - } + const BitmappedGraphics& display() const { return m_display; } + BitmappedGraphics& display() { return m_display; } - void setDrawNeeded(bool value) { - m_display.setDirty(value); - } + const KeyboardDevice& keyboard() const { return m_keyboard; } + KeyboardDevice& keyboard() { return m_keyboard; } - bool getFinished() const { - return m_finished; - } + bool getDrawNeeded() const { return display().getDirty(); } + void setDrawNeeded(bool value = true) { display().setDirty(value); } - void setFinished(bool value) { - m_finished = value; - } + bool getFinished() const { return m_finished; } + void setFinished(bool value = true) { m_finished = value; } - const std::string& getMnemomicFormat() const { - return m_mnemomicFormat; - } + const std::string& mnemomicFormat() const { return m_mnemomicFormat; } + std::string& mnemomicFormat() { return m_mnemomicFormat; } protected: - BitmappedGraphics m_display; - Memory m_memory; - - std::array m_v; - - uint16_t m_i = 0; - uint16_t m_pc = 0; - - bool m_finished = false; - - std::string m_mnemomicFormat; - void onBeepStarting(); void onBeepStopped(); @@ -250,6 +173,18 @@ class Chip8 { m_waitingForKeyPressRegister); } + BitmappedGraphics m_display; + Memory m_memory; + + std::array m_v; + + uint16_t m_i = 0; + uint16_t m_pc = 0; + + bool m_finished = false; + + std::string m_mnemomicFormat; + std::array m_standardFont = { { 0xF0, 0x90, 0x90, 0x90, 0xF0, // 0 0x20, 0x60, 0x20, 0x20, 0x70, // 1 diff --git a/src/libs/libchip8/Controller.cpp b/src/libs/libchip8/Controller.cpp index 3da4318..3565498 100644 --- a/src/libs/libchip8/Controller.cpp +++ b/src/libs/libchip8/Controller.cpp @@ -22,9 +22,9 @@ Controller::Controller(std::shared_ptr processor, const std::string& game) : m_processor(processor), m_game(game), - m_colours(m_processor->getDisplay().getNumberOfColours()), - m_gameController(m_processor->getKeyboardMutable()), - m_fps(m_processor->getConfiguration().getFramesPerSecond()) { + m_colours(m_processor->display().getNumberOfColours()), + m_gameController(m_processor->keyboard()), + m_fps(m_processor->configuration().getFramesPerSecond()) { } Controller::~Controller() { @@ -73,7 +73,7 @@ void Controller::runGameLoop() { while (::SDL_PollEvent(&e)) { switch (e.type) { case SDL_QUIT: - m_processor->setFinished(true); + m_processor->setFinished(); break; case SDL_KEYDOWN: handleKeyDown(e.key.keysym.sym); @@ -98,9 +98,8 @@ void Controller::runGameLoop() { const auto elapsedTicks = ::SDL_GetTicks() - m_startTicks; const auto neededTicks = (++m_frames / (float)m_fps) * 1000.0; auto sleepNeeded = (int)(neededTicks - elapsedTicks); - if (sleepNeeded > 0) { + if (sleepNeeded > 0) ::SDL_Delay(sleepNeeded); - } } } } @@ -119,7 +118,7 @@ void Controller::handleKeyDown(SDL_Keycode key) { // Don't let it get poked. break; default: - m_processor->getKeyboardMutable().pokeKey(key); + m_processor->keyboard().pokeKey(key); break; } } @@ -136,7 +135,7 @@ void Controller::handleKeyUp(SDL_Keycode key) { toggleFullscreen(); break; default: - m_processor->getKeyboardMutable().pullKey(key); + m_processor->keyboard().pullKey(key); break; } } @@ -155,15 +154,15 @@ void Controller::runFrame() { } bool Controller::finishedCycling(int cycles) const { - auto limit = m_processor->getConfiguration().getCyclesPerFrame(); + auto limit = m_processor->configuration().getCyclesPerFrame(); auto exhausted = cycles > limit; auto finished = m_processor->getFinished(); - auto draw = m_processor->getDisplay().getLowResolution() && m_processor->getDrawNeeded(); + auto draw = m_processor->display().getLowResolution() && m_processor->getDrawNeeded(); return exhausted || finished || draw; } void Controller::stop() { - m_processor->setFinished(true); + m_processor->setFinished(); } void Controller::loadContent() { @@ -180,7 +179,7 @@ void Controller::loadContent() { ::SDL_DisplayMode mode; verifySDLCall(::SDL_GetWindowDisplayMode(m_window, &mode), "Unable to obtain window information"); - const auto& configuration = m_processor->getConfiguration(); + const auto& configuration = m_processor->configuration(); m_vsync = configuration.getVsyncLocked(); Uint32 rendererFlags = 0; @@ -228,7 +227,7 @@ void Controller::loadContent() { schip->LowResolutionConfigured.connect(std::bind(&Controller::recreateBitmapTexture, this)); } - if (m_processor->getConfiguration().isDebugMode()) { + if (m_processor->configuration().isDebugMode()) { m_processor->EmulatingCycle.connect(std::bind(&Controller::Processor_EmulatingCycle, this, std::placeholders::_1)); m_processor->EmulatedCycle.connect(std::bind(&Controller::Processor_EmulatedCycle, this, std::placeholders::_1)); } @@ -303,8 +302,8 @@ void Controller::drawFrame() { auto displayWidth = getDisplayWidth(); auto displayHeight = getDisplayHeight(); - auto source = m_processor->getDisplay().getPlanes(); - auto numberOfPlanes = m_processor->getDisplay().getNumberOfPlanes(); + auto source = m_processor->display().planes(); + auto numberOfPlanes = m_processor->display().getNumberOfPlanes(); for (int y = 0; y < displayHeight; y++) { auto rowOffset = y * displayWidth; @@ -312,7 +311,7 @@ void Controller::drawFrame() { auto pixelIndex = x + rowOffset; int colourIndex = 0; for (int plane = 0; plane < numberOfPlanes; ++plane) { - auto bit = source[plane].getGraphics()[pixelIndex]; + auto bit = source[plane].graphics()[pixelIndex]; colourIndex |= bit << plane; } m_pixels[pixelIndex] = m_colours.getColour(colourIndex); @@ -383,7 +382,7 @@ void Controller::Processor_EmulatingCycle(const InstructionEventArgs& cycleEvent void Controller::Processor_EmulatedCycle(const InstructionEventArgs& cycleEvent) { auto state = m_processorState; auto raw = cycleEvent.getInstruction(); - auto disassembly = m_disassembler.disassemble(m_processor->getMnemomicFormat(), cycleEvent, m_processor->getMemory()); + auto disassembly = m_disassembler.disassemble(m_processor->mnemomicFormat(), cycleEvent, m_processor->memory()); std::ostringstream output; boost::format formatter("%04X"); diff --git a/src/libs/libchip8/Controller.h b/src/libs/libchip8/Controller.h index 5a9279c..d34d05a 100644 --- a/src/libs/libchip8/Controller.h +++ b/src/libs/libchip8/Controller.h @@ -44,11 +44,11 @@ class Controller final { virtual void loadContent(); int getDisplayWidth() const { - return m_processor->getDisplay().getWidth(); + return m_processor->display().getWidth(); } int getDisplayHeight() const { - return m_processor->getDisplay().getHeight(); + return m_processor->display().getHeight(); } int getScreenWidth() const { diff --git a/src/libs/libchip8/Disassembler.cpp b/src/libs/libchip8/Disassembler.cpp index 1f0aa31..87dc9aa 100644 --- a/src/libs/libchip8/Disassembler.cpp +++ b/src/libs/libchip8/Disassembler.cpp @@ -15,13 +15,13 @@ Disassembler::Disassembler() { std::string Disassembler::generateState(const InstructionEventArgs& event, Chip8* processor) const { auto pc = event.getProgramCounter(); - auto sp = processor->getStackPointer(); - auto indirector = processor->getIndirector(); - auto dt = processor->getDelayTimer(); - auto st = processor->getSoundTimer(); + auto sp = processor->SP(); + auto indirector = processor->indirector(); + auto dt = processor->delayTimer(); + auto st = processor->soundTimer(); auto waiting = processor->isWaitingForKeyPress(); auto keypressRegister = processor->getWaitingForKeyPressRegister(); - const auto& V = processor->getRegisters(); + const auto& V = processor->registers(); std::ostringstream output; diff --git a/src/libs/libchip8/GraphicsPlane.h b/src/libs/libchip8/GraphicsPlane.h index 50de8b1..73038d0 100644 --- a/src/libs/libchip8/GraphicsPlane.h +++ b/src/libs/libchip8/GraphicsPlane.h @@ -21,11 +21,11 @@ class GraphicsPlane final { GraphicsPlane() = default; GraphicsPlane(bool clip, bool countExceededRows); - const std::vector& getGraphics() const { + const std::vector& graphics() const { return m_graphics; } - std::vector& getGraphicsMutable() { + std::vector& graphics() { return m_graphics; } diff --git a/src/libs/libchip8/Memory.cpp b/src/libs/libchip8/Memory.cpp index 30a65d2..a7ecb66 100644 --- a/src/libs/libchip8/Memory.cpp +++ b/src/libs/libchip8/Memory.cpp @@ -9,11 +9,11 @@ Memory::Memory(int size) : m_bus(size) { } -const std::vector& Memory::getBus() const { +const std::vector& Memory::bus() const { return m_bus; } -std::vector& Memory::getBusMutable() { +std::vector& Memory::bus() { return m_bus; } diff --git a/src/libs/libchip8/Memory.h b/src/libs/libchip8/Memory.h index 00b0edf..b8557d1 100644 --- a/src/libs/libchip8/Memory.h +++ b/src/libs/libchip8/Memory.h @@ -13,8 +13,8 @@ class Memory final { Memory() noexcept {} Memory(int size); - const std::vector& getBus() const; - std::vector& getBusMutable(); + const std::vector& bus() const; + std::vector& bus(); uint8_t get(int address) const; uint16_t getWord(int address) const; diff --git a/src/libs/libchip8/Schip.cpp b/src/libs/libchip8/Schip.cpp index 75dad51..a750268 100644 --- a/src/libs/libchip8/Schip.cpp +++ b/src/libs/libchip8/Schip.cpp @@ -7,18 +7,18 @@ Schip::Schip(const Memory& memory, const KeyboardDevice& keyboard, const Bitmapp void Schip::initialise() { Chip8::initialise(); - std::copy_n(m_highFont.cbegin(), m_highFont.size(), m_memory.getBusMutable().begin() + HighFontOffset); - if (getConfiguration().getChip8LoadAndSave()) + std::copy_n(m_highFont.cbegin(), m_highFont.size(), memory().bus().begin() + HighFontOffset); + if (configuration().getChip8LoadAndSave()) m_compatibility = true; } void Schip::onHighResolution() { - m_display.setHighResolution(true); + display().setHighResolution(true); HighResolutionConfigured.fire(EventArgs()); } void Schip::onLowResolution() { - m_display.setHighResolution(false); + display().setHighResolution(false); LowResolutionConfigured.fire(EventArgs()); } @@ -98,24 +98,24 @@ bool Schip::emulateInstructions_0(int nnn, int nn, int n, int x, int y) { // https://github.com/Chromatophore/HP48-Superchip#8xy6--8xye // Bit shifts X register by 1, VIP: shifts Y by one and places in X, HP48-SC: ignores Y field, shifts X void Schip::SHR(int x, int y) { - if (getConfiguration().getChip8Shifts()) { + if (configuration().getChip8Shifts()) { Chip8::SHR(x, y); } else { - m_mnemomicFormat = "(S) SHR V%4$01X"; - m_v[0xf] = m_v[x] & 0x1; - m_v[x] >>= 1; + mnemomicFormat() = "(S) SHR V%4$01X"; + registers()[0xf] = registers()[x] & 0x1; + registers()[x] >>= 1; } } // https://github.com/Chromatophore/HP48-Superchip#8xy6--8xye // Bit shifts X register by 1, VIP: shifts Y by one and places in X, HP48-SC: ignores Y field, shifts X void Schip::SHL(int x, int y) { - if (getConfiguration().getChip8Shifts()) { + if (configuration().getChip8Shifts()) { Chip8::SHL(x, y); } else { - m_mnemomicFormat = "(S) SHL V%4$01X"; - m_v[0xf] = (m_v[x] & 0x80) == 0 ? 0 : 1; - m_v[x] <<= 1; + mnemomicFormat() = "(S) SHL V%4$01X"; + registers()[0xf] = (registers()[x] & 0x80) == 0 ? 0 : 1; + registers()[x] <<= 1; } } @@ -125,11 +125,11 @@ void Schip::SHL(int x, int y) { // HP48 -SC: reads highest nibble of address to select // register to apply to address (high nibble pulls double duty) void Schip::JP_V0(int x, int nnn) { - if (getConfiguration().getChip8IndexedJumps()) { + if (configuration().getChip8IndexedJumps()) { Chip8::JP_V0(x, nnn); } else { - m_mnemomicFormat = "(S) JP V%4$01X,%1$03X"; - m_pc = (uint16_t)(m_v[x] + nnn); + mnemomicFormat() = "(S) JP V%4$01X,%1$03X"; + PC() = (uint16_t)(registers()[x] + nnn); } } @@ -139,8 +139,8 @@ void Schip::LD_Vx_II(int x) { if (m_compatibility) { Chip8::LD_Vx_II(x); } else { - m_mnemomicFormat = "(S) LD V%4$01X,[I]"; - std::copy_n(m_memory.getBus().cbegin() + m_i, x + 1, m_v.begin()); + mnemomicFormat() = "(S) LD V%4$01X,[I]"; + std::copy_n(memory().bus().cbegin() + indirector(), x + 1, registers().begin()); } } @@ -150,18 +150,18 @@ void Schip::LD_II_Vx(int x) { if (m_compatibility) { Chip8::LD_II_Vx(x); } else { - m_mnemomicFormat = "(S) LD [I],V%4$01X"; - std::copy_n(m_v.cbegin(), x + 1, m_memory.getBusMutable().begin() + m_i); + mnemomicFormat() = "(S) LD [I],V%4$01X"; + std::copy_n(registers().cbegin(), x + 1, memory().bus().begin() + indirector()); } } void Schip::LD_HF_Vx(int x) { - m_mnemomicFormat = "(S) LD HF,V%4$01X"; - m_i = HighFontOffset + (HighFontSize * m_v[x]); + mnemomicFormat() = "(S) LD HF,V%4$01X"; + indirector() = HighFontOffset + (HighFontSize * registers()[x]); } void Schip::XDRW(int x, int y) { - m_mnemomicFormat = "(S) XDRW V%4$01X,V%5$01X"; + mnemomicFormat() = "(S) XDRW V%4$01X,V%5$01X"; draw(x, y, 16, 16); } @@ -170,8 +170,8 @@ void Schip::XDRW(int x, int y) { // with a successful exit status. [Super-Chip] // Code generated: 0x00FD. void Schip::EXIT() { - m_mnemomicFormat = "(S) EXIT"; - m_finished = true; + mnemomicFormat() = "(S) EXIT"; + setFinished(); } // scdown n @@ -180,8 +180,8 @@ void Schip::EXIT() { // (Use the delay timer to pace your games in high resolution mode.) // Code generated: 0x00Cn void Schip::SCDOWN(int n) { - m_mnemomicFormat = "(S) SCDOWN %3$01X"; - m_display.scrollDown(n); + mnemomicFormat() = "(S) SCDOWN %3$01X"; + display().scrollDown(n); } // compatibility @@ -190,7 +190,7 @@ void Schip::SCDOWN(int n) { // porting of Chip 8 games which rely on this behaviour. // Code generated: 0x00FA void Schip::COMPATIBILITY() { - m_mnemomicFormat = "(S) COMPATIBILITY"; + mnemomicFormat() = "(S) COMPATIBILITY"; m_compatibility = true; } @@ -200,8 +200,8 @@ void Schip::COMPATIBILITY() { // (Use the delay timer to pace your games in high resolution mode.) // Code generated: 0x00FB void Schip::SCRIGHT() { - m_mnemomicFormat = "(S) SCRIGHT"; - m_display.scrollRight(); + mnemomicFormat() = "(S) SCRIGHT"; + display().scrollRight(); } // scleft @@ -210,15 +210,15 @@ void Schip::SCRIGHT() { // (Use the delay timer to pace your games in high resolution mode.) // Code generated: 0x00FC void Schip::SCLEFT() { - m_mnemomicFormat = "(S) SCLEFT"; - m_display.scrollLeft(); + mnemomicFormat() = "(S) SCLEFT"; + display().scrollLeft(); } // low // Low resolution (64×32) graphics mode (this is the default). [Super-Chip] // Code generated: 0x00FE void Schip::LOW() { - m_mnemomicFormat = "(S) LOW"; + mnemomicFormat() = "(S) LOW"; onLowResolution(); } @@ -226,7 +226,7 @@ void Schip::LOW() { // High resolution (128×64) graphics mode. [Super-Chip] // Code generated: 0x00FF void Schip::HIGH() { - m_mnemomicFormat = "(S) HIGH"; + mnemomicFormat() = "(S) HIGH"; onHighResolution(); } @@ -235,8 +235,8 @@ void Schip::HIGH() { // HP48 implementation). (X < 8) [Super-Chip] // Code generated: 0xFX75 void Schip::LD_R_Vx(int x) { - m_mnemomicFormat = "(S) LD R,V%4$01X"; - std::copy_n(m_v.cbegin(), (x & 7) + 1, m_r.begin()); + mnemomicFormat() = "(S) LD R,V%4$01X"; + std::copy_n(registers().cbegin(), (x & 7) + 1, calculatorRegisters().begin()); } // flags.restore vX @@ -244,6 +244,6 @@ void Schip::LD_R_Vx(int x) { // HP48 implementation). (X < 8) [Super-Chip] // Code generated: 0xFX85 void Schip::LD_Vx_R(int x) { - m_mnemomicFormat = "(S) LD V%4$01X,R"; - std::copy_n(m_r.cbegin(), (x & 7) + 1, m_v.begin()); + mnemomicFormat() = "(S) LD V%4$01X,R"; + std::copy_n(calculatorRegisters().cbegin(), (x & 7) + 1, registers().begin()); } diff --git a/src/libs/libchip8/Schip.h b/src/libs/libchip8/Schip.h index e702e5a..5436068 100644 --- a/src/libs/libchip8/Schip.h +++ b/src/libs/libchip8/Schip.h @@ -30,13 +30,8 @@ class Schip : public Chip8 { virtual void initialise(); - const std::array& getCalculatorRegisters() const { - return m_r; - } - - std::array& getCalculatorRegistersMutable() { - return m_r; - } + const std::array& calculatorRegisters() const { return m_r; } + std::array& calculatorRegisters() { return m_r; } protected: void onHighResolution(); diff --git a/src/libs/libchip8/Signal.h b/src/libs/libchip8/Signal.h index 101deb3..30245d9 100644 --- a/src/libs/libchip8/Signal.h +++ b/src/libs/libchip8/Signal.h @@ -16,8 +16,7 @@ template class Signal final { } void fire(const T& e) const { - if (!delegates.empty()) - for (auto& delegate : delegates) - delegate(e); + for (auto& delegate : delegates) + delegate(e); } }; diff --git a/src/libs/libchip8/XoChip.cpp b/src/libs/libchip8/XoChip.cpp index 27a8ea8..c941fc1 100644 --- a/src/libs/libchip8/XoChip.cpp +++ b/src/libs/libchip8/XoChip.cpp @@ -62,20 +62,20 @@ bool XoChip::emulateInstructions_F(int nnn, int nn, int n, int x, int y) { //// scroll-up n (0x00DN) scroll the contents of the display up by 0-15 pixels. void XoChip::SCUP(int n) { - m_mnemomicFormat = "(X) SCUP %3$01X"; - m_display.scrollUp(n); + mnemomicFormat() = "(X) SCUP %3$01X"; + display().scrollUp(n); } // save vx - vy (0x5XY2) save an inclusive range of registers to memory starting at i. // https://github.com/JohnEarnest/Octo/blob/gh-pages/docs/XO-ChipSpecification.md#memory-access void XoChip::save_vx_to_vy(int x, int y) { - m_mnemomicFormat = "(X) SAVE V%4$01X-V%5$01X"; + mnemomicFormat() = "(X) SAVE V%4$01X-V%5$01X"; auto step = x > y ? -1 : +1; - auto address = m_i; + auto address = indirector(); auto ongoing = true; do { - m_memory.set(address++, m_v[x]); + memory().set(address++, registers()[x]); ongoing = x != y; x += step; } while (ongoing); @@ -84,12 +84,12 @@ void XoChip::save_vx_to_vy(int x, int y) { // load vx - vy (0x5XY3) load an inclusive range of registers from memory starting at i. // https://github.com/JohnEarnest/Octo/blob/gh-pages/docs/XO-ChipSpecification.md#memory-access void XoChip::load_vx_to_vy(int x, int y) { - m_mnemomicFormat = "(X) LOAD V%4$01X-V%5$01X"; + mnemomicFormat() = "(X) LOAD V%4$01X-V%5$01X"; auto step = x > y ? -1 : +1; - auto address = m_i; + auto address = indirector(); auto ongoing = true; do { - m_v[x] = m_memory.get(address++); + registers()[x] = memory().get(address++); ongoing = x != y; x += step; } while (ongoing); @@ -98,19 +98,19 @@ void XoChip::load_vx_to_vy(int x, int y) { // i := long NNNN (0xF000, 0xNNNN) load i with a 16-bit address. // https://github.com/JohnEarnest/Octo/blob/gh-pages/docs/XO-ChipSpecification.md#extended-memory void XoChip::load_i_long() { - m_mnemomicFormat = "(X) LD I,%6$04X"; - m_i = (uint16_t)m_memory.getWord(m_pc); - m_pc += 2; + mnemomicFormat() = "(X) LD I,%6$04X"; + indirector() = (uint16_t)memory().getWord(PC()); + PC() += 2; } ////plane n (0xFN01) select zero or more drawing planes by bitmask (0 <= n <= 3). void XoChip::plane(int n) { - m_mnemomicFormat = "(X) PLANE %3$01X"; - m_display.setPlaneMask(n); + mnemomicFormat() = "(X) PLANE %3$01X"; + display().setPlaneMask(n); } ////audio (0xF002) store 16 bytes starting at i in the audio pattern buffer. void XoChip::audio() { - m_mnemomicFormat = "(X) AUDIO"; - std::copy_n(m_memory.getBus().cbegin() + m_i, m_audoPatternBuffer.size(), m_audoPatternBuffer.begin()); + mnemomicFormat() = "(X) AUDIO"; + std::copy_n(memory().bus().cbegin() + indirector(), m_audoPatternBuffer.size(), m_audoPatternBuffer.begin()); } diff --git a/src/testchip8/chip8_tests.cpp b/src/testchip8/chip8_tests.cpp index 84f7136..5c4d28d 100644 --- a/src/testchip8/chip8_tests.cpp +++ b/src/testchip8/chip8_tests.cpp @@ -18,15 +18,15 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("the screen is cleared (CLS: 0x00E0)") { - auto& display = processor->getDisplayMutable(); - auto& planes = display.getPlanesMutable(); + auto& display = processor->display(); + auto& planes = display.planes(); auto& plane = planes[0]; - auto& bitmap = plane.getGraphicsMutable(); + auto& bitmap = plane.graphics(); // The equivalent of a fully filled screen std::fill(bitmap.begin(), bitmap.end(), 1); - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x00E0); // CLS processor->step(); @@ -37,150 +37,150 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a subroutine returns (RET: 0x00EE)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x2400); // CALL subroutine memory.setWord(0x400, 0x00EE); // RET processor->step(); processor->step(); THEN("the program counter should be set to execute the next statement past the original call") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("a jump is made (JP NNN: 0x1NNN)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x1400); // JP 400 processor->step(); THEN("the program counter should be set to the jump destination") { - REQUIRE(processor->getProgramCounter() == 0x400); + REQUIRE(processor->PC() == 0x400); } } WHEN("a subroutine is called (CALL NNN: 0x2NNN)") { - const auto sp = processor->getStackPointer(); + const auto sp = processor->SP(); - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x2400); // CALL subroutine processor->step(); THEN("the program counter should be set to execute the subroutine") { - REQUIRE(processor->getProgramCounter() == 0x400); + REQUIRE(processor->PC() == 0x400); } AND_THEN("the stack should contain an extra word") { - REQUIRE(processor->getStackPointer() == sp + 1); + REQUIRE(processor->SP() == sp + 1); } AND_THEN("the new value on the stack should be the return address") { - const auto& stack = processor->getStack(); - REQUIRE(stack[processor->getStackPointer() - 1] == 0x202); + const auto& stack = processor->stack(); + REQUIRE(stack[processor->SP() - 1] == 0x202); } } WHEN("a positive SE instruction is executed (SE VX,NN: 0x3XNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x30FF); // SE V0,FF processor->step(); THEN("the program counter should skip the following instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 4)); + REQUIRE(processor->PC() == (startAddress + 4)); } } WHEN("a negative SE instruction is executed (SE VX,NN: 0x3XNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x30FE); // SE V0,FE processor->step(); THEN("the program counter should move forward normally") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("a positive SNE instruction is executed (SNE VX,NN: 0x4XNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x40FE); // SNE V0,FE processor->step(); THEN("the program counter should skip the following instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 4)); + REQUIRE(processor->PC() == (startAddress + 4)); } } WHEN("a negative SNE instruction is executed (SNE VX,NN: 0x4XNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x40FF); // SNE V0,FF processor->step(); THEN("the program counter should move forward normally") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("a positive SE instruction is executed (SE VX,VY: 0x5XY0)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; registers[1] = 0xFF; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x5010); // SE V0,V1 processor->step(); THEN("the program counter should skip the following instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 4)); + REQUIRE(processor->PC() == (startAddress + 4)); } } WHEN("a negative SE instruction is executed (SE VX,VY: 0x5XY0)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; registers[1] = 0xFE; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x5010); // SE V0,V1 processor->step(); THEN("the program counter should move forward normally") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("a register is loaded with an immediate value (LD VX,NN: 0x6XNN)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x60FF); // LD V0,FF processor->step(); THEN("the register takes the new value") { - const auto& registers = processor->getRegisters(); + const auto& registers = processor->registers(); REQUIRE(registers[0] == 0xFF); } } WHEN("a register has an immediate value added (ADD VX,NN: 0x7XNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x7001); // ADD V0,1 processor->step(); @@ -191,10 +191,10 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is loaded with another (LD VX,VY: 0x8XY0)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[1] = 1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8010); // LD V0,V1 processor->step(); @@ -207,11 +207,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is logically ORed with another (OR VX,VY: 0x8XY1)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x10; registers[1] = 0x1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8011); // OR V0,V1 processor->step(); @@ -222,11 +222,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is logically ANDed another (AND VX,VY: 0x8XY2)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xfe; registers[1] = 0xf; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8012); // AND V0,V1 processor->step(); @@ -237,11 +237,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is logically XORed with another (XOR VX,VY: 0x8XY3)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0b01010101; registers[1] = 0b01110111; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8013); // XOR V0,V1 processor->step(); @@ -252,11 +252,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is added to another with no carry (ADD VX,VY: 0x8XY4)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 2; registers[1] = 3; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8014); // ADD V0,V1 processor->step(); @@ -269,11 +269,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is added to another with carry (ADD VX,VY: 0x8XY4)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xff; registers[1] = 1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8014); // ADD V0,V1 processor->step(); @@ -286,11 +286,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is subtracted from another with no borrow (SUB VX,VY: 0x8XY5)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 3; registers[1] = 2; // x > y - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8015); // SUB V0,V1 processor->step(); @@ -303,11 +303,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is subtracted from another with borrow (SUB VX,VY: 0x8XY5)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 2; registers[1] = 3; // x < y - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8015); // SUB V0,V1 processor->step(); @@ -320,11 +320,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a register is shifted right by one bit generating carry (SHR VX,VY: 0x8XY6)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xff; registers[1] = 3; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8016); // SHR VX,VY processor->step(); @@ -339,11 +339,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a register is shifted right by one bit without generating carry (SHR VX,VY: 0x8XY6)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xff; registers[1] = 2; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8016); // SHR VX,VY processor->step(); @@ -358,11 +358,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is subtracted from another with no borrow (SUBN VX,VY: 0x8XY7") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; registers[1] = 4; // x < y - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8017); // SUBN V0,V1 processor->step(); @@ -375,11 +375,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("one register is subtracted from another with borrow (SUBN VX,VY: 0x8XY7)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 4; registers[1] = 1; // x > y - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8017); // SUBN V0,V1 processor->step(); @@ -392,11 +392,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a register is shifted left by one bit generating carry (SHL VX,VY: 0x8XYE)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xff; registers[1] = 0x81; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x801E); // SHL VX,VY processor->step(); @@ -411,11 +411,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a register is shifted left by one bit without generating carry (SHL VX,VY: 0x8XYE)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xff; registers[1] = 1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x801E); // SHL VX,VY processor->step(); @@ -430,65 +430,65 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a positive SNE instruction is executed (SNE VX,VY: 0x9XY0)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; registers[1] = 2; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x9010); // SNE VX,VY processor->step(); THEN("the program counter should skip the following instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 4)); + REQUIRE(processor->PC() == (startAddress + 4)); } } WHEN("a negative SNE instruction is executed (SNE VX,VY: 0x9XY0)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; registers[1] = 1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x9010); // SNE VX,VY processor->step(); THEN("the program counter should move forward normally") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("the indirection register is loaded with an immediate value (LD I,NNN: 0xANNN)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xA111); // LD I,NNN processor->step(); THEN("the I register is loaded with the new value") { - REQUIRE(processor->getIndirector() == 0x111); + REQUIRE(processor->indirector() == 0x111); } } WHEN("an indexed jump is executed (JP V0,NNN: 0xBNNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x10; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xB100); // JP V0,100 processor->step(); THEN("the program counter is set to the address plus V0") { - REQUIRE(processor->getProgramCounter() == 0x110); + REQUIRE(processor->PC() == 0x110); } } WHEN("a masked random number is generated (RND X,NN: 0xCXNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x10; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xC00F); // RND 0,0F processor->step(); @@ -499,11 +499,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a draw command is executed with no hits (DRW X,Y,N: 0xDXYN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0; registers[1] = 0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); const uint16_t sprite = 0x400U; memory.set(sprite, 0b10101010); @@ -511,16 +511,16 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C memory.set(sprite + 2, 0b10101010); memory.set(sprite + 3, 0b01010101); - processor->setIndirector(sprite); + processor->indirector() = sprite; memory.setWord(startAddress, 0xD014); // DRW 0,1,4 processor->step(); THEN("the display will have the sprite pattern placed at 0,0") { - auto& display = processor->getDisplay(); - auto& planes = display.getPlanes(); + auto& display = processor->display(); + auto& planes = display.planes(); auto& plane = planes[0]; - auto& bitmap = plane.getGraphics(); + auto& bitmap = plane.graphics(); for (int y = 0; y < 4; ++y) { std::bitset<8> displayRow; for (int x = 0; x < 8; ++x) { @@ -537,11 +537,11 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a draw command is executed with complete hits (DRW VX,VY,N: 0xDXYN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0; registers[1] = 0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); const uint16_t sprite = 0x400U; memory.set(sprite, 0b10101010); @@ -549,7 +549,7 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C memory.set(sprite + 2, 0b10101010); memory.set(sprite + 3, 0b01010101); - processor->setIndirector(sprite); + processor->indirector() = sprite; memory.setWord(startAddress, 0xD014); // DRW V0,V1,4 memory.setWord(0x202, 0xD014); // DRW V0,V1,4 Executing the same sprite drawing twice will generate only hits @@ -557,10 +557,10 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C processor->step(); THEN("all bits in the display are set to zero") { - auto& display = processor->getDisplay(); - auto& planes = display.getPlanes(); + auto& display = processor->display(); + auto& planes = display.planes(); auto& plane = planes[0]; - auto& bitmap = plane.getGraphics(); + auto& bitmap = plane.graphics(); REQUIRE(std::all_of(bitmap.cbegin(), bitmap.cend(), [](int bit) { return bit == 0; })); } AND_THEN("there have been hits") { REQUIRE(registers[0xf] == 1); @@ -569,146 +569,146 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("a positive skip on key pressed instruction is executed (SKP VX: 0xEX9E)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xA; - auto& keyboard = processor->getKeyboardMutable(); + auto& keyboard = processor->keyboard(); keyboard.pokeKey(SDLK_z); // Mapped Z -> A on Chip-8 - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xE09E); // SKP V0 processor->step(); THEN("the program counter should skip the following instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 4)); + REQUIRE(processor->PC() == (startAddress + 4)); } } WHEN("a negative skip on key pressed instruction is executed (SKP VX: 0xEX9E)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xB; - auto& keyboard = processor->getKeyboardMutable(); + auto& keyboard = processor->keyboard(); keyboard.pokeKey(SDLK_z); // Mapped Z -> A on Chip-8 - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xE09E); // SKP V0 processor->step(); THEN("the program counter should move forward normally") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("a positive skip on key not pressed instruction is executed (SKNP VX: 0xEXA1)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xB; - auto& keyboard = processor->getKeyboardMutable(); + auto& keyboard = processor->keyboard(); keyboard.pokeKey(SDLK_z); // Mapped Z -> A on Chip-8 - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xE0A1); // SKNP V0 processor->step(); THEN("the program counter should skip the following instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 4)); + REQUIRE(processor->PC() == (startAddress + 4)); } } WHEN("a negative skip on key not pressed instruction is executed (SKNP VX: 0xEXA1)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xA; - auto& keyboard = processor->getKeyboardMutable(); + auto& keyboard = processor->keyboard(); keyboard.pokeKey(SDLK_z); // Mapped Z -> A on Chip-8 - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xE0A1); // SKNP V0 processor->step(); THEN("the program counter should move forward normally") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("the V0 register is loaded with the contents of the delay timer (LD VX,DT: 0xFX07)") { - processor->setDelayTimer(0x10); + processor->delayTimer() = 0x10; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF007); // LD V0,DT processor->step(); THEN("V0 should be set to the contents of the delay timer") { - const auto& registers = processor->getRegisters(); + const auto& registers = processor->registers(); REQUIRE(registers[0] == 0x10); } } WHEN("an instruction to wait for the next key pressed and place it in the secified register (LD VX,K: 0xFX0A)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF00A); // LD V0,K processor->step(); - auto& keyboard = processor->getKeyboardMutable(); + auto& keyboard = processor->keyboard(); keyboard.pokeKey(SDLK_z); processor->step(); THEN("V0 should be set to the mapped key") { - const auto& registers = processor->getRegisters(); + const auto& registers = processor->registers(); REQUIRE(registers[0] == 0xA); } AND_THEN("the program counter should have moved forward by just one instruction") { - REQUIRE(processor->getProgramCounter() == (startAddress + 2)); + REQUIRE(processor->PC() == (startAddress + 2)); } } WHEN("the delay timer is loaded with the contents of a register (LD DT,VX: 0xFX15)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x10; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF015); // LD DT,V0 processor->step(); THEN("the delay timer should be set to the contents of the specified register") { - REQUIRE(processor->getDelayTimer() == 0x10); + REQUIRE(processor->delayTimer() == 0x10); } } WHEN("the sound timer is loaded with the contents of a register (LD ST,VX: 0xFX18)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x10; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF018); // LD ST,V0 processor->step(); THEN("the sound timer should be set to the contents of the specified register") { - REQUIRE(processor->getSoundTimer() == 0x10); + REQUIRE(processor->soundTimer() == 0x10); } } WHEN("the instruction to add a register to the indirector, with no range overflow, is executed (ADD I,VX: 0xFX1E)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; - processor->setIndirector(0x100); + processor->indirector() = 0x100; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF01E); // ADD I,V0 processor->step(); THEN("the indirector should be set to the sum of the indirector plus V0, masked to 0xFFF") { - REQUIRE(processor->getIndirector() == 0x101); + REQUIRE(processor->indirector() == 0x101); } AND_THEN("the carry flag should not be set") { REQUIRE(registers[0xf] == 0); } @@ -716,17 +716,17 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("the instruction to add a register to the indirector, with range overflow, is executed (ADD I,VX: 0xFX1E)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; - processor->setIndirector(0xFFF); + processor->indirector() = 0xFFF; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF01E); // ADD I,V0 processor->step(); THEN("the indirector should be set to the sum of the indirector plus V0, masked to 0xFFF") { - REQUIRE(processor->getIndirector() == 0); + REQUIRE(processor->indirector() == 0); } AND_THEN("the carry flag should be set") { REQUIRE(registers[0xf] == 1); } @@ -734,26 +734,26 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("the instruction to load the indirector register with the location of a number in the font table (LD F,VX: 0xFX29)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xA; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF029); // LD F,V0 processor->step(); THEN("the indirector should be set to location of the A character in the font table") { - REQUIRE(processor->getIndirector() == (Chip8::StandardFontOffset + 0xA * Chip8::StandardFontSize)); + REQUIRE(processor->indirector() == (Chip8::StandardFontOffset + 0xA * Chip8::StandardFontSize)); } } WHEN("the instruction to convert the contents of a register to decimal in executed (LD B,VX: 0xFX33)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xFF; - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF033); // LD B,V0 processor->step(); @@ -768,15 +768,15 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C WHEN("the instruction to save X registers is executed (LD [I],VX: 0xFX55)") { - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x1; registers[1] = 0x2; registers[2] = 0x3; registers[3] = 0x4; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.set(0x400, 0); memory.set(0x401, 0); @@ -795,21 +795,21 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C } AND_THEN("the contents of the fourth location should be 0 (i.e. unchanged)") { REQUIRE(memory.get(0x403) == 0); } AND_THEN("the value of the indirector should be the base location plus the number of registers saved") { - REQUIRE(processor->getIndirector() == 0x403); + REQUIRE(processor->indirector() == 0x403); } } WHEN("the instruction to load X registers is executed (LD VX,[I]: 0xFX65)") { - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x0; registers[1] = 0x0; registers[2] = 0x0; registers[3] = 0x0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.set(0x400, 1); memory.set(0x401, 2); @@ -828,7 +828,7 @@ SCENARIO("The Chip-8 interpreter can execute all valid Chip-8 instructions", "[C } AND_THEN("the contents of V3 should be 0 (i.e. unchanged)") { REQUIRE(registers[3] == 0); } AND_THEN("the value of the indirector should be the base location plus the number of registers saved") { - REQUIRE(processor->getIndirector() == 0x403); + REQUIRE(processor->indirector() == 0x403); } } } @@ -845,7 +845,7 @@ SCENARIO("The Chip-8 interpreter rejects invalid instructions", "[Chip8][!throws WHEN("an unknown instruction from 0 is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x0000); // ??? Unknown instruction bool runtimeErrorThrown = false; @@ -862,7 +862,7 @@ SCENARIO("The Chip-8 interpreter rejects invalid instructions", "[Chip8][!throws WHEN("an unknown instruction from 8 is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8008); // ??? Unknown instruction bool runtimeErrorThrown = false; @@ -879,7 +879,7 @@ SCENARIO("The Chip-8 interpreter rejects invalid instructions", "[Chip8][!throws WHEN("an unknown instruction from 9 is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x9009); // ??? Unknown instruction bool runtimeErrorThrown = false; @@ -896,7 +896,7 @@ SCENARIO("The Chip-8 interpreter rejects invalid instructions", "[Chip8][!throws WHEN("an unknown instruction from E is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xE000); // ??? Unknown instruction bool runtimeErrorThrown = false; @@ -913,7 +913,7 @@ SCENARIO("The Chip-8 interpreter rejects invalid instructions", "[Chip8][!throws WHEN("an unknown instruction from F is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF000); // ??? Unknown instruction bool runtimeErrorThrown = false; @@ -943,7 +943,7 @@ SCENARIO("The Chip-8 interpreter handles instructions on even or odd boundaries" WHEN("an aligned instruction is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x00E0); // CLS bool runtimeErrorThrown = false; @@ -960,7 +960,7 @@ SCENARIO("The Chip-8 interpreter handles instructions on even or odd boundaries" WHEN("a misaligned instruction is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x1401); // JP 401 memory.setWord(0x401, 0x00E0); // CLS @@ -991,7 +991,7 @@ SCENARIO("The Chip-8 interpreter handles instructions on even or odd boundaries" WHEN("an aligned instruction is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x00E0); // CLS bool runtimeErrorThrown = false; @@ -1008,7 +1008,7 @@ SCENARIO("The Chip-8 interpreter handles instructions on even or odd boundaries" WHEN("a misaligned instruction is interpreted") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x1401); // JP 401 memory.setWord(0x401, 0x00E0); // CLS diff --git a/src/testchip8/schip_tests.cpp b/src/testchip8/schip_tests.cpp index 375838a..b5383ff 100644 --- a/src/testchip8/schip_tests.cpp +++ b/src/testchip8/schip_tests.cpp @@ -19,7 +19,7 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to save X (where X < 8) registers to the calculator is executed (LD_R_Vx: 0xFX75)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x1; registers[1] = 0x2; registers[2] = 0x3; @@ -27,13 +27,13 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre auto schip = dynamic_cast(processor.get()); - auto& calculatorRegisters = schip->getCalculatorRegistersMutable(); + auto& calculatorRegisters = schip->calculatorRegisters(); calculatorRegisters[0] = 0; calculatorRegisters[1] = 0; calculatorRegisters[2] = 0; calculatorRegisters[3] = 0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF275); // LD R,V2 processor->step(); @@ -51,17 +51,17 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to save X (where X > 7) registers to the calculator is executed (LD_R_Vx: 0xFX75)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x1; registers[1] = 0x2; auto schip = dynamic_cast(processor.get()); - auto& calculatorRegisters = schip->getCalculatorRegistersMutable(); + auto& calculatorRegisters = schip->calculatorRegisters(); calculatorRegisters[0] = 0; calculatorRegisters[1] = 0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF875); // LD R,V8 processor->step(); @@ -75,7 +75,7 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to load X (where X < 8) registers from the calculator is executed (LD_Vx_R: 0xFX85)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x0; registers[1] = 0x0; registers[2] = 0x0; @@ -83,13 +83,13 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre auto schip = dynamic_cast(processor.get()); - auto& calculatorRegisters = schip->getCalculatorRegistersMutable(); + auto& calculatorRegisters = schip->calculatorRegisters(); calculatorRegisters[0] = 1; calculatorRegisters[1] = 2; calculatorRegisters[2] = 3; calculatorRegisters[3] = 4; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF285); // LD V2,R processor->step(); @@ -107,17 +107,17 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to load X (where X > 7) registers from the calculator is executed (LD_Vx_R: 0xFX85)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x0; registers[1] = 0x0; auto schip = dynamic_cast(processor.get()); - auto& calculatorRegisters = schip->getCalculatorRegistersMutable(); + auto& calculatorRegisters = schip->calculatorRegisters(); calculatorRegisters[0] = 1; calculatorRegisters[1] = 2; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF885); // LD V8,R processor->step(); @@ -131,15 +131,15 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to enter low resolution is executed, the display dimensions should be 64x32 (LOW: 0x00FE)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x00FE); // LOW processor->step(); THEN("the display mode should be low resolution ") { - REQUIRE(processor->getDisplay().getLowResolution()); - REQUIRE(!processor->getDisplay().getHighResolution()); - REQUIRE(processor->getDisplay().getWidth() == GraphicsPlane::ScreenWidthLow); - REQUIRE(processor->getDisplay().getHeight() == GraphicsPlane::ScreenHeightLow); + REQUIRE(processor->display().getLowResolution()); + REQUIRE(!processor->display().getHighResolution()); + REQUIRE(processor->display().getWidth() == GraphicsPlane::ScreenWidthLow); + REQUIRE(processor->display().getHeight() == GraphicsPlane::ScreenHeightLow); REQUIRE(GraphicsPlane::ScreenWidthLow == 64); REQUIRE(GraphicsPlane::ScreenHeightLow == 32); } @@ -147,15 +147,15 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to enter high resolution is executed, the display dimensions should be 128x64 (HIGH: 0x00FF)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x00FF); // HIGH processor->step(); THEN("the display mode should be low resolution ") { - REQUIRE(processor->getDisplay().getHighResolution()); - REQUIRE(!processor->getDisplay().getLowResolution()); - REQUIRE(processor->getDisplay().getWidth() == GraphicsPlane::ScreenWidthHigh); - REQUIRE(processor->getDisplay().getHeight() == GraphicsPlane::ScreenHeightHigh); + REQUIRE(processor->display().getHighResolution()); + REQUIRE(!processor->display().getLowResolution()); + REQUIRE(processor->display().getWidth() == GraphicsPlane::ScreenWidthHigh); + REQUIRE(processor->display().getHeight() == GraphicsPlane::ScreenHeightHigh); REQUIRE(GraphicsPlane::ScreenWidthHigh == 128); REQUIRE(GraphicsPlane::ScreenHeightHigh == 64); } @@ -171,7 +171,7 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to exit is executed, the processor indicates it is finished (EXIT: 0x00FD)") { - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x00FD); // EXIT processor->step(); @@ -182,15 +182,15 @@ SCENARIO("The SuperChip interpreter interprets SuperChip only instructions corre WHEN("the instruction to load the indirector register with the location of a number in the hi-resolution font table (LD HF,VX: 0xFX30)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0xA; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xF030); // LD HF,V0 processor->step(); THEN("the indirector should be set to location of the A character in the font table") { - REQUIRE(processor->getIndirector() == (Schip::HighFontOffset + 0xA * Schip::HighFontSize)); + REQUIRE(processor->indirector() == (Schip::HighFontOffset + 0xA * Schip::HighFontSize)); } } } @@ -207,10 +207,10 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently WHEN("a register is shifted right by one bit generating carry (SHR VX: 0x8X06)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 3; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8006); // SHR V0 processor->step(); @@ -223,10 +223,10 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently WHEN("a register is shifted right by one bit without generating carry (SHR VX: 0x8X06)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 2; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x8016); // SHR V0 processor->step(); @@ -239,10 +239,10 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently WHEN("a register is shifted left by one bit generating carry (SHL VX: 0x8X0E)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x81; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x800E); // SHL V0 processor->step(); @@ -255,10 +255,10 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently WHEN("a register is shifted left by one bit without generating carry (SHL VX: 0x8X0E)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 1; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0x800E); // SHL V0 processor->step(); @@ -271,15 +271,15 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently WHEN("an indexed jump is executed (JP VX,NNN: 0xBNNN)") { - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[1] = 0x10; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.setWord(startAddress, 0xB100); // JP V1,100 processor->step(); THEN("the program counter is set to the address plus VX") { - REQUIRE(processor->getProgramCounter() == 0x110); + REQUIRE(processor->PC() == 0x110); } } } @@ -296,15 +296,15 @@ SCENARIO("The SuperChip interpreter can execute some Chip8 instructions in compa WHEN("the instruction to save X registers is executed (LD [I],VX: 0xFX55)") { - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x1; registers[1] = 0x2; registers[2] = 0x3; registers[3] = 0x4; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.set(0x400, 0); memory.set(0x401, 0); @@ -325,21 +325,21 @@ SCENARIO("The SuperChip interpreter can execute some Chip8 instructions in compa } AND_THEN("the contents of the fourth location should be 0 (i.e. unchanged)") { REQUIRE(memory.get(0x403) == 0); } AND_THEN("the value of the indirector should be the base location plus the number of registers saved") { - REQUIRE(processor->getIndirector() == 0x403); + REQUIRE(processor->indirector() == 0x403); } } WHEN("the instruction to load X registers is executed (LD VX,[I]: 0xFX65)") { - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x0; registers[1] = 0x0; registers[2] = 0x0; registers[3] = 0x0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.set(0x400, 1); memory.set(0x401, 2); @@ -360,7 +360,7 @@ SCENARIO("The SuperChip interpreter can execute some Chip8 instructions in compa } AND_THEN("the contents of V3 should be 0 (i.e. unchanged)") { REQUIRE(registers[3] == 0); } AND_THEN("the value of the indirector should be the base location plus the number of registers saved") { - REQUIRE(processor->getIndirector() == 0x403); + REQUIRE(processor->indirector() == 0x403); } } } @@ -377,15 +377,15 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently WHEN("the instruction to save X registers is executed (LD [I],VX: 0xFX55)") { - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x1; registers[1] = 0x2; registers[2] = 0x3; registers[3] = 0x4; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.set(0x400, 0); memory.set(0x401, 0); @@ -404,21 +404,21 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently } AND_THEN("the contents of the fourth location should be 0 (i.e. unchanged)") { REQUIRE(memory.get(0x403) == 0); } AND_THEN("the value of the indirector should be unchanged") { - REQUIRE(processor->getIndirector() == 0x400); + REQUIRE(processor->indirector() == 0x400); } } WHEN("the instruction to load X registers is executed (LD VX,[I]: 0xFX65)") { - processor->setIndirector(0x400); + processor->indirector() = 0x400; - auto& registers = processor->getRegistersMutable(); + auto& registers = processor->registers(); registers[0] = 0x0; registers[1] = 0x0; registers[2] = 0x0; registers[3] = 0x0; - auto& memory = processor->getMemoryMutable(); + auto& memory = processor->memory(); memory.set(0x400, 1); memory.set(0x401, 2); @@ -437,7 +437,7 @@ SCENARIO("The SuperChip interpreter executes some Chip8 instructions differently } AND_THEN("the contents of V3 should be 0 (i.e. unchanged)") { REQUIRE(registers[3] == 0); } AND_THEN("the value of the indirector should be unchanged") { - REQUIRE(processor->getIndirector() == 0x400); + REQUIRE(processor->indirector() == 0x400); } } }