Skip to content

Commit

Permalink
Gambatte: Fix halt behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
alyosha-tas committed May 12, 2018
1 parent 942454e commit efc35a5
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 29 deletions.
20 changes: 6 additions & 14 deletions libgambatte/src/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -633,15 +633,6 @@ void CPU::process(const unsigned long cycles) {
//Halt CPU and LCD display until button pressed:
case 0x10:
{
unsigned char followingByte;
PEEK(followingByte, PC);
PC = (PC + 1) & 0xFFFF;

//if (followingByte != 0x00) {
//memory.di();
//memory.blackScreen();
//}

cycleCounter = memory.stop(cycleCounter);

if (cycleCounter < memory.nextEventTime()) {
Expand Down Expand Up @@ -1164,13 +1155,14 @@ void CPU::process(const unsigned long cycles) {

//halt (4 cycles):
case 0x76:
if (!memory.ime() && (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F)) {
if (memory.isCgb())
cycleCounter += 4;
if (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F) {
if (memory.ime())
PC = (PC - 1) & 0xFFFF;
else
skip = true;
} else {
memory.halt();
}
else {
memory.halt(cycleCounter);

if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.nextEventTime() - cycleCounter;
Expand Down
26 changes: 14 additions & 12 deletions libgambatte/src/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ unsigned long Memory::event(unsigned long cycleCounter) {

switch (intreq.minEventId()) {
case UNHALT:
nontrivial_ff_write(0xFF04, 0, cycleCounter);
PC = (PC + 1) & 0xFFFF;
cycleCounter += 4;
intreq.unhalt();
intreq.setEventTime<UNHALT>(DISABLED_TIME);
break;
Expand Down Expand Up @@ -265,8 +268,12 @@ unsigned long Memory::event(unsigned long cycleCounter) {
display.update(cycleCounter);
break;
case INTERRUPTS:
if (stopped) {
intreq.setEventTime<INTERRUPTS>(DISABLED_TIME);
break;
}
if (halted()) {
if (gbIsCgb_)
if (gbIsCgb_ || (!gbIsCgb_ && cycleCounter <= halttime + 4))
cycleCounter += 4;

intreq.unhalt();
Expand Down Expand Up @@ -311,7 +318,7 @@ unsigned long Memory::event(unsigned long cycleCounter) {
}

unsigned long Memory::stop(unsigned long cycleCounter) {
cycleCounter += 4 << isDoubleSpeed();
cycleCounter += 4;

if (ioamhram[0x14D] & isCgb()) {
sound.generate_samples(cycleCounter, isDoubleSpeed());
Expand All @@ -329,17 +336,11 @@ unsigned long Memory::stop(unsigned long cycleCounter) {
// otherwise, the cpu should be allowed to stay halted as long as needed
// so only execute this line when switching speed
intreq.halt();
intreq.setEventTime<UNHALT>(cycleCounter + 0x20000 + isDoubleSpeed() * 8);
intreq.setEventTime<UNHALT>(cycleCounter + 0x20000);
}
else {
if ((ioamhram[0x100] & 0x30) == 0x30) {
di();
intreq.halt();
}
else {
intreq.halt();
intreq.setEventTime<UNHALT>(cycleCounter + 0x20000 + isDoubleSpeed() * 8);
}
stopped = true;
intreq.halt();
}

return cycleCounter;
Expand Down Expand Up @@ -651,6 +652,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
case 0x04:
ioamhram[0x104] = 0;
divLastUpdate = cycleCounter;
tima.resTac(cycleCounter, TimaInterruptRequester(intreq));
return;
case 0x05:
tima.setTima(data, cycleCounter, TimaInterruptRequester(intreq));
Expand All @@ -660,7 +662,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
break;
case 0x07:
data |= 0xF8;
tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq));
tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq), gbIsCgb_);
break;
case 0x0F:
updateIrqs(cycleCounter);
Expand Down
4 changes: 3 additions & 1 deletion libgambatte/src/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ class Memory {
bool cgbSwitching;
bool agbMode;
bool gbIsCgb_;
bool stopped;
unsigned short &SP;
unsigned short &PC;
unsigned long halttime;

void (*readCallback)(unsigned);
void (*writeCallback)(unsigned);
Expand Down Expand Up @@ -128,7 +130,7 @@ class Memory {
return cc < intreq.eventTime(BLIT) ? -1 : static_cast<long>((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed());
}

void halt() { intreq.halt(); }
void halt(unsigned long cycleCounter) { halttime = cycleCounter; intreq.halt(); }
void ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } }

void di() { intreq.di(); }
Expand Down
20 changes: 19 additions & 1 deletion libgambatte/src/tima.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ void Tima::setTma(const unsigned data, const unsigned long cycleCounter, const T
tma_ = data;
}

void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq) {
void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const TimaInterruptRequester timaIrq, bool gbIsCgb) {
if (tac_ ^ data) {
unsigned long nextIrqEventTime = timaIrq.nextIrqEventTime();

Expand All @@ -142,6 +142,15 @@ void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const T

if (data & 4) {
lastUpdate_ = (cycleCounter >> timaClock[data & 3]) << timaClock[data & 3];
unsigned long diff = cycleCounter - basetime_;

if (gbIsCgb) {
if (((diff >> (timaClock[tac_ & 3] - 1)) & 1) == 1 && ((diff >> (timaClock[data & 3] - 1)) & 1) == 0)
tima_++;

}

lastUpdate_ = basetime_ + ((diff >> timaClock[data & 3]) << timaClock[data & 3]);
nextIrqEventTime = lastUpdate_ + ((256u - tima_) << timaClock[data & 3]) + 3;
}

Expand All @@ -151,6 +160,15 @@ void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const T
tac_ = data;
}

void Tima::resTac(unsigned long const cycleCounter, TimaInterruptRequester timaIrq) {
basetime_ = cycleCounter;

if (tac_ & 0x04) {
setTac(tac_ & ~0x04, cycleCounter, timaIrq, false);
setTac(tac_ | 0x04, cycleCounter, timaIrq, false);
}
}

unsigned Tima::tima(unsigned long cycleCounter) {
if (tac_ & 0x04)
updateTima(cycleCounter);
Expand Down
4 changes: 3 additions & 1 deletion libgambatte/src/tima.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class TimaInterruptRequester {
};

class Tima {
unsigned long basetime_;
unsigned long lastUpdate_;
unsigned long tmatime_;

Expand All @@ -55,7 +56,8 @@ class Tima {

void setTima(unsigned tima, unsigned long cc, TimaInterruptRequester timaIrq);
void setTma(unsigned tma, unsigned long cc, TimaInterruptRequester timaIrq);
void setTac(unsigned tac, unsigned long cc, TimaInterruptRequester timaIrq);
void setTac(unsigned tac, unsigned long cc, TimaInterruptRequester timaIrq, bool gbIsCgb);
void resTac(unsigned long cc, TimaInterruptRequester timaIrq);
unsigned tima(unsigned long cc);

void doIrqEvent(TimaInterruptRequester timaIrq);
Expand Down
Binary file modified output/dll/libgambatte.dll
Binary file not shown.

0 comments on commit efc35a5

Please sign in to comment.