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: //Halt CPU and LCD display until button pressed:
case 0x10: case 0x10:
{ {
unsigned char followingByte;
PEEK(followingByte, PC);
PC = (PC + 1) & 0xFFFF;
//if (followingByte != 0x00) {
//memory.di();
//memory.blackScreen();
//}
cycleCounter = memory.stop(cycleCounter); cycleCounter = memory.stop(cycleCounter);
if (cycleCounter < memory.nextEventTime()) { if (cycleCounter < memory.nextEventTime()) {
@ -1165,13 +1156,13 @@ void CPU::process(const unsigned long cycles) {
//halt (4 cycles): //halt (4 cycles):
case 0x76: case 0x76:
if (!memory.ime() && (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F)) { if (memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter) & 0x1F) {
if (memory.isCgb()) if (memory.ime())
cycleCounter += 4; PC = (PC - 1) & 0xFFFF;
else else
skip = true; skip = true;
} else { } else {
memory.halt(); memory.halt(cycleCounter);
if (cycleCounter < memory.nextEventTime()) { if (cycleCounter < memory.nextEventTime()) {
const unsigned long cycles = memory.nextEventTime() - cycleCounter; const unsigned long cycles = memory.nextEventTime() - cycleCounter;

View File

@ -154,6 +154,9 @@ unsigned long Memory::event(unsigned long cycleCounter) {
switch (intreq.minEventId()) { switch (intreq.minEventId()) {
case UNHALT: case UNHALT:
nontrivial_ff_write(0xFF04, 0, cycleCounter);
PC = (PC + 1) & 0xFFFF;
cycleCounter += 4;
intreq.unhalt(); intreq.unhalt();
intreq.setEventTime<UNHALT>(DISABLED_TIME); intreq.setEventTime<UNHALT>(DISABLED_TIME);
break; break;
@ -265,8 +268,12 @@ unsigned long Memory::event(unsigned long cycleCounter) {
display.update(cycleCounter); display.update(cycleCounter);
break; break;
case INTERRUPTS: case INTERRUPTS:
if (stopped) {
intreq.setEventTime<INTERRUPTS>(DISABLED_TIME);
break;
}
if (halted()) { if (halted()) {
if (gbIsCgb_) if (gbIsCgb_ || (!gbIsCgb_ && cycleCounter <= halttime + 4))
cycleCounter += 4; cycleCounter += 4;
intreq.unhalt(); intreq.unhalt();
@ -311,7 +318,7 @@ unsigned long Memory::event(unsigned long cycleCounter) {
} }
unsigned long Memory::stop(unsigned long cycleCounter) { unsigned long Memory::stop(unsigned long cycleCounter) {
cycleCounter += 4 << isDoubleSpeed(); cycleCounter += 4;
if (ioamhram[0x14D] & isCgb()) { if (ioamhram[0x14D] & isCgb()) {
sound.generate_samples(cycleCounter, isDoubleSpeed()); 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 // otherwise, the cpu should be allowed to stay halted as long as needed
// so only execute this line when switching speed // so only execute this line when switching speed
intreq.halt(); intreq.halt();
intreq.setEventTime<UNHALT>(cycleCounter + 0x20000 + isDoubleSpeed() * 8); intreq.setEventTime<UNHALT>(cycleCounter + 0x20000);
} }
else { else {
if ((ioamhram[0x100] & 0x30) == 0x30) { stopped = true;
di(); intreq.halt();
intreq.halt();
}
else {
intreq.halt();
intreq.setEventTime<UNHALT>(cycleCounter + 0x20000 + isDoubleSpeed() * 8);
}
} }
return cycleCounter; return cycleCounter;
@ -651,6 +652,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
case 0x04: case 0x04:
ioamhram[0x104] = 0; ioamhram[0x104] = 0;
divLastUpdate = cycleCounter; divLastUpdate = cycleCounter;
tima.resTac(cycleCounter, TimaInterruptRequester(intreq));
return; return;
case 0x05: case 0x05:
tima.setTima(data, cycleCounter, TimaInterruptRequester(intreq)); tima.setTima(data, cycleCounter, TimaInterruptRequester(intreq));
@ -660,7 +662,7 @@ void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned
break; break;
case 0x07: case 0x07:
data |= 0xF8; data |= 0xF8;
tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq)); tima.setTac(data, cycleCounter, TimaInterruptRequester(intreq), gbIsCgb_);
break; break;
case 0x0F: case 0x0F:
updateIrqs(cycleCounter); updateIrqs(cycleCounter);

View File

@ -42,9 +42,11 @@ class Memory {
bool cgbSwitching; bool cgbSwitching;
bool agbMode; bool agbMode;
bool gbIsCgb_; bool gbIsCgb_;
bool stopped;
unsigned short &SP; unsigned short &SP;
unsigned short &PC; unsigned short &PC;
unsigned long basetime; unsigned long basetime;
unsigned long halttime;
MemoryCallback readCallback; MemoryCallback readCallback;
MemoryCallback writeCallback; MemoryCallback writeCallback;
@ -129,7 +131,7 @@ public:
return cc < intreq.eventTime(BLIT) ? -1 : static_cast<long>((cc - intreq.eventTime(BLIT)) >> isDoubleSpeed()); 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 ei(unsigned long cycleCounter) { if (!ime()) { intreq.ei(cycleCounter); } }
void di() { intreq.di(); } void di() { intreq.di(); }

View File

@ -119,7 +119,7 @@ void Tima::setTma(const unsigned data, const unsigned long cycleCounter, const T
tma_ = data; 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) { if (tac_ ^ data) {
unsigned long nextIrqEventTime = timaIrq.nextIrqEventTime(); unsigned long nextIrqEventTime = timaIrq.nextIrqEventTime();
@ -142,6 +142,13 @@ void Tima::setTac(const unsigned data, const unsigned long cycleCounter, const T
if (data & 4) { if (data & 4) {
lastUpdate_ = (cycleCounter >> timaClock[data & 3]) << timaClock[data & 3]; 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; 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; 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) { unsigned Tima::tima(unsigned long cycleCounter) {
if (tac_ & 0x04) if (tac_ & 0x04)
updateTima(cycleCounter); updateTima(cycleCounter);

View File

@ -34,6 +34,7 @@ public:
}; };
class Tima { class Tima {
unsigned long basetime_;
unsigned long lastUpdate_; unsigned long lastUpdate_;
unsigned long tmatime_; unsigned long tmatime_;
@ -55,7 +56,8 @@ public:
void setTima(unsigned tima, unsigned long cc, TimaInterruptRequester timaIrq); void setTima(unsigned tima, unsigned long cc, TimaInterruptRequester timaIrq);
void setTma(unsigned tma, 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); unsigned tima(unsigned long cc);
void doIrqEvent(TimaInterruptRequester timaIrq); void doIrqEvent(TimaInterruptRequester timaIrq);

Binary file not shown.