Gambatte: Recommit Halt changes (now with Gifvex's improvements too)
This commit is contained in:
parent
98ed9e7c42
commit
38b84fce09
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
Loading…
Reference in New Issue