From fa7e1480d38dde61943f227ae7332572e0ae9729 Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Fri, 13 Nov 2020 10:14:06 +0000 Subject: [PATCH] LR35902: Fix lots of timing issues by attaching to the "tick" event. Signed-off-by: Adrian Conlon --- LR35902/inc/IoRegisters.h | 6 +++--- LR35902/inc/LR35902.h | 20 ++++++++------------ LR35902/src/IoRegisters.cpp | 23 +++++++++++------------ LR35902/src/LR35902.cpp | 27 +++++++++++++++------------ 4 files changed, 37 insertions(+), 39 deletions(-) diff --git a/LR35902/inc/IoRegisters.h b/LR35902/inc/IoRegisters.h index a4e9784..dfd1020 100644 --- a/LR35902/inc/IoRegisters.h +++ b/LR35902/inc/IoRegisters.h @@ -117,7 +117,7 @@ namespace EightBit { poke(IF, peek(IF) | cause); } - void checkTimers(int cycles); + void incrementTimers(); int timerClockTicks(); @@ -125,7 +125,7 @@ namespace EightBit { bool timerEnabled(); bool timerDisabled(); - void incrementDIV(int cycles); + void incrementDIV(); void incrementTIMA(); void incrementLY(); @@ -185,7 +185,7 @@ namespace EightBit { bool m_p11 = true; // left/b bool m_p10 = true; // right/a - void checkTimer(int cycles); + void incrementTimer(); void mask(const uint16_t address, const uint8_t masking) { poke(address, peek(address) | ~masking); diff --git a/LR35902/inc/LR35902.h b/LR35902/inc/LR35902.h index caa2c89..93d8353 100644 --- a/LR35902/inc/LR35902.h +++ b/LR35902/inc/LR35902.h @@ -26,10 +26,6 @@ namespace EightBit { Signal ExecutingInstruction; Signal ExecutedInstruction; - [[nodiscard]] auto clockCycles() const noexcept { - return cycles() * 4; - } - [[nodiscard]] register16_t& AF() final; [[nodiscard]] register16_t& BC() final; [[nodiscard]] register16_t& DE() final; @@ -49,46 +45,46 @@ namespace EightBit { void handleINT() final; void memoryWrite() final { - tick(); + tick(4); IntelProcessor::memoryWrite(); } uint8_t memoryRead() final { - tick(); + tick(4); return IntelProcessor::memoryRead(); } void pushWord(register16_t value) final { - tick(); + tick(4); IntelProcessor::pushWord(value); } void jr(int8_t offset) final { IntelProcessor::jr(offset); - tick(); + tick(4); } int jumpConditional(const int condition) final { if (IntelProcessor::jumpConditional(condition)) - tick(); + tick(4); return condition; } int returnConditional(const int condition) final { IntelProcessor::returnConditional(condition); - tick(); + tick(4); return condition; } int jrConditional(const int condition) final { if (!IntelProcessor::jrConditional(condition)) - tick(); + tick(4); return condition; } void ret() final { IntelProcessor::ret(); - tick(); + tick(4); } private: diff --git a/LR35902/src/IoRegisters.cpp b/LR35902/src/IoRegisters.cpp index 2ac5eb6..47bded6 100644 --- a/LR35902/src/IoRegisters.cpp +++ b/LR35902/src/IoRegisters.cpp @@ -146,15 +146,14 @@ void EightBit::GameBoy::IoRegisters::Bus_WrittenByte(EightBit::EventArgs) { } } -void EightBit::GameBoy::IoRegisters::checkTimers(int cycles) { - incrementDIV(cycles); - checkTimer(cycles); +void EightBit::GameBoy::IoRegisters::incrementTimers() { + incrementDIV(); + incrementTimer(); } -void EightBit::GameBoy::IoRegisters::checkTimer(int cycles) { +void EightBit::GameBoy::IoRegisters::incrementTimer() { if (timerEnabled()) { - m_timerCounter -= cycles; - if (m_timerCounter <= 0) { + if (--m_timerCounter == 0) { m_timerCounter += m_timerRate; incrementTIMA(); } @@ -164,13 +163,13 @@ void EightBit::GameBoy::IoRegisters::checkTimer(int cycles) { int EightBit::GameBoy::IoRegisters::timerClockTicks() { switch (timerClock()) { case 0b00: - return 1024; // 4.096 Khz + return 256; // 4.096 Khz case 0b01: - return 16; // 262.144 Khz + return 4; // 262.144 Khz case 0b10: - return 64; // 65.536 Khz + return 16; // 65.536 Khz case 0b11: - return 256; // 16.384 Khz + return 64; // 16.384 Khz default: UNREACHABLE; } @@ -189,8 +188,8 @@ bool EightBit::GameBoy::IoRegisters::timerDisabled() { return (peek(TAC) & Chip::Bit2) == 0; } -void EightBit::GameBoy::IoRegisters::incrementDIV(int cycles) { - m_divCounter += cycles; +void EightBit::GameBoy::IoRegisters::incrementDIV() { + ++m_divCounter; poke(DIV, m_divCounter.high); } diff --git a/LR35902/src/LR35902.cpp b/LR35902/src/LR35902.cpp index 69206bf..81ee835 100644 --- a/LR35902/src/LR35902.cpp +++ b/LR35902/src/LR35902.cpp @@ -7,6 +7,12 @@ EightBit::GameBoy::LR35902::LR35902(Bus& memory) : IntelProcessor(memory), m_bus(memory) { + Ticked.connect([this](EventArgs) { + if ((cycles() % 4) == 0) { + m_bus.IO().incrementTimers(); + m_bus.IO().transferDma(); + } + }); } EightBit::register16_t& EightBit::GameBoy::LR35902::AF() { @@ -30,7 +36,7 @@ void EightBit::GameBoy::LR35902::handleRESET() { IntelProcessor::handleRESET(); di(); SP() = Mask16 - 1; - tick(4); + tick(4 * 4); } void EightBit::GameBoy::LR35902::handleINT() { @@ -104,7 +110,7 @@ void EightBit::GameBoy::LR35902::reti() { EightBit::register16_t EightBit::GameBoy::LR35902::add(uint8_t& f, const register16_t operand, const register16_t value) { - tick(); + tick(4); const int addition = operand.word + value.word; const register16_t result = addition; @@ -332,12 +338,9 @@ int EightBit::GameBoy::LR35902::step() { } else { Processor::execute(fetchByte()); } - - m_bus.IO().checkTimers(clockCycles()); - m_bus.IO().transferDma(); } ExecutedInstruction.fire(*this); - return clockCycles(); + return cycles(); } int EightBit::GameBoy::LR35902::execute() { @@ -359,7 +362,7 @@ int EightBit::GameBoy::LR35902::execute() { if (UNLIKELY(cycles() == 0)) throw std::logic_error("Unhandled opcode"); - return clockCycles(); + return cycles(); } void EightBit::GameBoy::LR35902::executeCB(const int x, const int y, const int z, int, int) { @@ -504,7 +507,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in default: UNREACHABLE; } - tick(); + tick(4); break; case 4: { // 8-bit INC auto operand = R(y); @@ -604,7 +607,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in case 5: { // GB: ADD SP,dd const auto before = SP().word; const int8_t value = fetchByte(); - tick(2); + tick(2 * 4); const auto result = before + value; SP() = result; const auto carried = before ^ value ^ (result & Mask16); @@ -619,7 +622,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in case 7: { // GB: LD HL,SP + dd const auto before = SP().word; const int8_t value = fetchByte(); - tick(); + tick(4); const auto result = before + value; HL() = result; const auto carried = before ^ value ^ (result & Mask16); @@ -650,7 +653,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in break; case 3: // LD SP,HL SP() = HL(); - tick(); + tick(4); break; default: UNREACHABLE; @@ -690,7 +693,7 @@ void EightBit::GameBoy::LR35902::executeOther(const int x, const int y, const in switch (y) { case 0: // JP nn jump(MEMPTR() = fetchWord()); - tick(); + tick(4); break; case 1: // CB prefix m_prefixCB = true;