mirror of
https://github.com/MoleskiCoder/EightBit.git
synced 2024-11-12 17:04:46 +00:00
LR35902: Fix lots of timing issues by attaching to the "tick" event.
Signed-off-by: Adrian Conlon <adrian.conlon@gmail.com>
This commit is contained in:
parent
efed7dae23
commit
fa7e1480d3
@ -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);
|
||||
|
@ -26,10 +26,6 @@ namespace EightBit {
|
||||
Signal<LR35902> ExecutingInstruction;
|
||||
Signal<LR35902> 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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user