Gambatte: Recommit Halt changes (now with Gifvex's improvements too)

This commit is contained in:
alyosha-tas 2018-05-12 12:21:15 -04:00
parent 98ed9e7c42
commit 38b84fce09
6 changed files with 40 additions and 28 deletions

View File

@ -634,15 +634,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()) {
@ -1165,13 +1156,13 @@ 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();
memory.halt(cycleCounter);
if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.nextEventTime() - cycleCounter;

View File

@ -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;
@ -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();
@ -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());
@ -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;
@ -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));
@ -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);

View File

@ -42,9 +42,11 @@ class Memory {
bool cgbSwitching;
bool agbMode;
bool gbIsCgb_;
bool stopped;
unsigned short &SP;
unsigned short &PC;
unsigned long basetime;
unsigned long halttime;
MemoryCallback readCallback;
MemoryCallback writeCallback;
@ -129,7 +131,7 @@ public:
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(); }

View File

@ -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();
@ -142,6 +142,13 @@ 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;
}
@ -151,6 +158,14 @@ 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);

View File

@ -34,6 +34,7 @@ public:
};
class Tima {
unsigned long basetime_;
unsigned long lastUpdate_;
unsigned long tmatime_;
@ -55,7 +56,8 @@ public:
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);

Binary file not shown.