Boot into overblank.

This commit is contained in:
Christian Speckner 2024-06-30 17:16:32 +02:00
parent 41c8bff0c6
commit fe6e67de32
14 changed files with 317 additions and 143 deletions

View File

@ -55,5 +55,5 @@ bool RamCheat::disable()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamCheat::evaluate() void RamCheat::evaluate()
{ {
myOSystem.console().system().poke(address, value); myOSystem.console().system().pokeOob(address, value);
} }

View File

@ -77,7 +77,7 @@ Int16 HighScoresManager::peek(uInt16 addr) const
if (myOSystem.hasConsole()) if (myOSystem.hasConsole())
{ {
if(addr < 0x100U || myOSystem.console().cartridge().internalRamSize() == 0) if(addr < 0x100U || myOSystem.console().cartridge().internalRamSize() == 0)
return myOSystem.console().system().peek(addr); return myOSystem.console().system().peekOob(addr);
else else
return myOSystem.console().cartridge().internalRamGetValue(addr); return myOSystem.console().cartridge().internalRamGetValue(addr);
} }

View File

@ -98,7 +98,7 @@ void Debugger::initialize()
delete myDialog; myDialog = nullptr; delete myDialog; myDialog = nullptr;
myDialog = new DebuggerDialog(myOSystem, *this, 0, 0, mySize.w, mySize.h); myDialog = new DebuggerDialog(myOSystem, *this, 0, 0, mySize.w, mySize.h);
myCartDebug->setDebugWidget(&(myDialog->cartDebug())); myCartDebug->setDebugWidget(myDialog->cartDebug());
saveOldState(); saveOldState();
} }
@ -249,7 +249,7 @@ string Debugger::setRAM(IntArray& args)
const size_t count = args.size(); const size_t count = args.size();
int address = args[0]; int address = args[0];
for(size_t i = 1; i < count; ++i) for(size_t i = 1; i < count; ++i)
mySystem.poke(address++, args[i]); mySystem.pokeOob(address++, args[i]);
buf << "changed " << (count-1) << " location"; buf << "changed " << (count-1) << " location";
if(count != 2) if(count != 2)
@ -327,7 +327,7 @@ int Debugger::step(bool save)
int Debugger::trace() int Debugger::trace()
{ {
// 32 is the 6502 JSR instruction: // 32 is the 6502 JSR instruction:
if(mySystem.peek(myCpuDebug->pc()) == 32) if(mySystem.peekOob(myCpuDebug->pc()) == 32)
{ {
saveOldState(); saveOldState();
@ -521,20 +521,20 @@ void Debugger::log(string_view triggerMsg)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Debugger::peek(uInt16 addr, Device::AccessFlags flags) uInt8 Debugger::peek(uInt16 addr, Device::AccessFlags flags)
{ {
return mySystem.peek(addr, flags); return mySystem.peekOob(addr, flags);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Debugger::dpeek(uInt16 addr, Device::AccessFlags flags) uInt16 Debugger::dpeek(uInt16 addr, Device::AccessFlags flags)
{ {
return static_cast<uInt16>(mySystem.peek(addr, flags) | return static_cast<uInt16>(mySystem.peekOob(addr, flags) |
(mySystem.peek(addr+1, flags) << 8)); (mySystem.peekOob(addr+1, flags) << 8));
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags) void Debugger::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags)
{ {
mySystem.poke(addr, value, flags); mySystem.pokeOob(addr, value, flags);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -546,14 +546,14 @@ M6502& Debugger::m6502() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::peekAsInt(int addr, Device::AccessFlags flags) int Debugger::peekAsInt(int addr, Device::AccessFlags flags)
{ {
return mySystem.peek(static_cast<uInt16>(addr), flags); return mySystem.peekOob(static_cast<uInt16>(addr), flags);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::dpeekAsInt(int addr, Device::AccessFlags flags) int Debugger::dpeekAsInt(int addr, Device::AccessFlags flags)
{ {
return mySystem.peek(static_cast<uInt16>(addr), flags) | return mySystem.peekOob(static_cast<uInt16>(addr), flags) |
(mySystem.peek(static_cast<uInt16>(addr+1), flags) << 8); (mySystem.peekOob(static_cast<uInt16>(addr+1), flags) << 8);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -121,25 +121,25 @@ void RiotDebug::saveOldState()
uInt8 RiotDebug::swcha(int newVal) uInt8 RiotDebug::swcha(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x280, newVal); mySystem.pokeOob(0x280, newVal);
return mySystem.peek(0x280); return mySystem.peekOob(0x280);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 RiotDebug::swchb(int newVal) uInt8 RiotDebug::swchb(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x282, newVal); mySystem.pokeOob(0x282, newVal);
return mySystem.peek(0x282); return mySystem.peekOob(0x282);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 RiotDebug::swacnt(int newVal) uInt8 RiotDebug::swacnt(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x281, newVal); mySystem.pokeOob(0x281, newVal);
return mySystem.m6532().myDDRA; return mySystem.m6532().myDDRA;
} }
@ -148,7 +148,7 @@ uInt8 RiotDebug::swacnt(int newVal)
uInt8 RiotDebug::swbcnt(int newVal) uInt8 RiotDebug::swbcnt(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x283, newVal); mySystem.pokeOob(0x283, newVal);
return mySystem.m6532().myDDRB; return mySystem.m6532().myDDRB;
} }
@ -159,7 +159,7 @@ uInt8 RiotDebug::inpt(int x)
static constexpr std::array<TIARegister, 6> _inpt = { static constexpr std::array<TIARegister, 6> _inpt = {
INPT0, INPT1, INPT2, INPT3, INPT4, INPT5 INPT0, INPT1, INPT2, INPT3, INPT4, INPT5
}; };
return mySystem.peek(_inpt[x]); return mySystem.peekOob(_inpt[x]);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -177,7 +177,7 @@ bool RiotDebug::vblank(int bit)
uInt8 RiotDebug::tim1T(int newVal) uInt8 RiotDebug::tim1T(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x294, newVal); mySystem.pokeOob(0x294, newVal);
return mySystem.m6532().myOutTimer[0]; return mySystem.m6532().myOutTimer[0];
} }
@ -186,7 +186,7 @@ uInt8 RiotDebug::tim1T(int newVal)
uInt8 RiotDebug::tim8T(int newVal) uInt8 RiotDebug::tim8T(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x295, newVal); mySystem.pokeOob(0x295, newVal);
return mySystem.m6532().myOutTimer[1]; return mySystem.m6532().myOutTimer[1];
} }
@ -195,7 +195,7 @@ uInt8 RiotDebug::tim8T(int newVal)
uInt8 RiotDebug::tim64T(int newVal) uInt8 RiotDebug::tim64T(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x296, newVal); mySystem.pokeOob(0x296, newVal);
return mySystem.m6532().myOutTimer[2]; return mySystem.m6532().myOutTimer[2];
} }
@ -204,7 +204,7 @@ uInt8 RiotDebug::tim64T(int newVal)
uInt8 RiotDebug::tim1024T(int newVal) uInt8 RiotDebug::tim1024T(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(0x297, newVal); mySystem.pokeOob(0x297, newVal);
return mySystem.m6532().myOutTimer[3]; return mySystem.m6532().myOutTimer[3];
} }
@ -410,10 +410,10 @@ string RiotDebug::toString()
// Yes, the fire buttons are in the TIA, but we might as well // Yes, the fire buttons are in the TIA, but we might as well
// show them here for convenience. // show them here for convenience.
<< "Left/P0 stick: " << dirP0String() << "Left/P0 stick: " << dirP0String()
<< ((mySystem.peek(0x03c) & 0x80) ? "" : "(button) ") << ((mySystem.peekOob(0x03c) & 0x80) ? "" : "(button) ")
<< '\n' << '\n'
<< "Right/P1 stick: " << dirP1String() << "Right/P1 stick: " << dirP1String()
<< ((mySystem.peek(0x03d) & 0x80) ? "" : "(button) "); << ((mySystem.peekOob(0x03d) & 0x80) ? "" : "(button) ");
return buf.str(); return buf.str();
} }

View File

@ -267,7 +267,7 @@ void TIADebug::saveOldState()
myOldState.info.push_back(frameWsyncCycles()); myOldState.info.push_back(frameWsyncCycles());
} }
/* the set methods now use mySystem.poke(). This will save us the /* the set methods now use mySystem.pokeOob(). This will save us the
trouble of masking the values here, since TIA::poke() will do it trouble of masking the values here, since TIA::poke() will do it
for us. for us.
@ -293,7 +293,7 @@ void TIADebug::saveOldState()
bool TIADebug::vdelP0(int newVal) bool TIADebug::vdelP0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(VDELP0, static_cast<bool>(newVal)); mySystem.pokeOob(VDELP0, static_cast<bool>(newVal));
return myTIA.registerValue(VDELP0) & 0x01; return myTIA.registerValue(VDELP0) & 0x01;
} }
@ -302,7 +302,7 @@ bool TIADebug::vdelP0(int newVal)
bool TIADebug::vdelP1(int newVal) bool TIADebug::vdelP1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(VDELP1, static_cast<bool>(newVal)); mySystem.pokeOob(VDELP1, static_cast<bool>(newVal));
return myTIA.registerValue(VDELP1) & 0x01; return myTIA.registerValue(VDELP1) & 0x01;
} }
@ -311,7 +311,7 @@ bool TIADebug::vdelP1(int newVal)
bool TIADebug::vdelBL(int newVal) bool TIADebug::vdelBL(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(VDELBL, static_cast<bool>(newVal)); mySystem.pokeOob(VDELBL, static_cast<bool>(newVal));
return myTIA.registerValue(VDELBL) & 0x01; return myTIA.registerValue(VDELBL) & 0x01;
} }
@ -320,7 +320,7 @@ bool TIADebug::vdelBL(int newVal)
bool TIADebug::enaM0(int newVal) bool TIADebug::enaM0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(ENAM0, static_cast<bool>(newVal) << 1); mySystem.pokeOob(ENAM0, static_cast<bool>(newVal) << 1);
return myTIA.registerValue(ENAM0) & 0x02; return myTIA.registerValue(ENAM0) & 0x02;
} }
@ -329,7 +329,7 @@ bool TIADebug::enaM0(int newVal)
bool TIADebug::enaM1(int newVal) bool TIADebug::enaM1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(ENAM1, static_cast<bool>(newVal) << 1); mySystem.pokeOob(ENAM1, static_cast<bool>(newVal) << 1);
return myTIA.registerValue(ENAM1) & 0x02; return myTIA.registerValue(ENAM1) & 0x02;
} }
@ -338,7 +338,7 @@ bool TIADebug::enaM1(int newVal)
bool TIADebug::enaBL(int newVal) bool TIADebug::enaBL(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(ENABL, static_cast<bool>(newVal) << 1); mySystem.pokeOob(ENABL, static_cast<bool>(newVal) << 1);
return myTIA.registerValue(ENABL) & 0x02; return myTIA.registerValue(ENABL) & 0x02;
} }
@ -347,7 +347,7 @@ bool TIADebug::enaBL(int newVal)
bool TIADebug::resMP0(int newVal) bool TIADebug::resMP0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(RESMP0, static_cast<bool>(newVal) << 1); mySystem.pokeOob(RESMP0, static_cast<bool>(newVal) << 1);
return myTIA.registerValue(RESMP0) & 0x02; return myTIA.registerValue(RESMP0) & 0x02;
} }
@ -356,7 +356,7 @@ bool TIADebug::resMP0(int newVal)
bool TIADebug::resMP1(int newVal) bool TIADebug::resMP1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(RESMP1, static_cast<bool>(newVal) << 1); mySystem.pokeOob(RESMP1, static_cast<bool>(newVal) << 1);
return myTIA.registerValue(RESMP1) & 0x02; return myTIA.registerValue(RESMP1) & 0x02;
} }
@ -365,7 +365,7 @@ bool TIADebug::resMP1(int newVal)
bool TIADebug::refP0(int newVal) bool TIADebug::refP0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(REFP0, static_cast<bool>(newVal) << 3); mySystem.pokeOob(REFP0, static_cast<bool>(newVal) << 3);
return myTIA.registerValue(REFP0) & 0x08; return myTIA.registerValue(REFP0) & 0x08;
} }
@ -374,7 +374,7 @@ bool TIADebug::refP0(int newVal)
bool TIADebug::refP1(int newVal) bool TIADebug::refP1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(REFP1, static_cast<bool>(newVal) << 3); mySystem.pokeOob(REFP1, static_cast<bool>(newVal) << 3);
return myTIA.registerValue(REFP1) & 0x08; return myTIA.registerValue(REFP1) & 0x08;
} }
@ -389,7 +389,7 @@ bool TIADebug::refPF(int newVal)
tmp |= 0x01; tmp |= 0x01;
else else
tmp &= ~0x01; tmp &= ~0x01;
mySystem.poke(CTRLPF, tmp); mySystem.pokeOob(CTRLPF, tmp);
} }
return myTIA.registerValue(CTRLPF) & 0x01; return myTIA.registerValue(CTRLPF) & 0x01;
@ -405,7 +405,7 @@ bool TIADebug::scorePF(int newVal)
tmp |= 0x02; tmp |= 0x02;
else else
tmp &= ~0x02; tmp &= ~0x02;
mySystem.poke(CTRLPF, tmp); mySystem.pokeOob(CTRLPF, tmp);
} }
return myTIA.registerValue(CTRLPF) & 0x02; return myTIA.registerValue(CTRLPF) & 0x02;
@ -421,7 +421,7 @@ bool TIADebug::priorityPF(int newVal)
tmp |= 0x04; tmp |= 0x04;
else else
tmp &= ~0x04; tmp &= ~0x04;
mySystem.poke(CTRLPF, tmp); mySystem.pokeOob(CTRLPF, tmp);
} }
return myTIA.registerValue(CTRLPF) & 0x04; return myTIA.registerValue(CTRLPF) & 0x04;
@ -515,7 +515,7 @@ bool TIADebug::collision(CollisionBit id, bool toggle) const
uInt8 TIADebug::audC0(int newVal) uInt8 TIADebug::audC0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(AUDC0, newVal); mySystem.pokeOob(AUDC0, newVal);
return myTIA.registerValue(AUDC0) & 0x0f; return myTIA.registerValue(AUDC0) & 0x0f;
} }
@ -524,7 +524,7 @@ uInt8 TIADebug::audC0(int newVal)
uInt8 TIADebug::audC1(int newVal) uInt8 TIADebug::audC1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(AUDC1, newVal); mySystem.pokeOob(AUDC1, newVal);
return myTIA.registerValue(AUDC1) & 0x0f; return myTIA.registerValue(AUDC1) & 0x0f;
} }
@ -533,7 +533,7 @@ uInt8 TIADebug::audC1(int newVal)
uInt8 TIADebug::audV0(int newVal) uInt8 TIADebug::audV0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(AUDV0, newVal); mySystem.pokeOob(AUDV0, newVal);
return myTIA.registerValue(AUDV0) & 0x0f; return myTIA.registerValue(AUDV0) & 0x0f;
} }
@ -542,7 +542,7 @@ uInt8 TIADebug::audV0(int newVal)
uInt8 TIADebug::audV1(int newVal) uInt8 TIADebug::audV1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(AUDV1, newVal); mySystem.pokeOob(AUDV1, newVal);
return myTIA.registerValue(AUDV1) & 0x0f; return myTIA.registerValue(AUDV1) & 0x0f;
} }
@ -551,7 +551,7 @@ uInt8 TIADebug::audV1(int newVal)
uInt8 TIADebug::audF0(int newVal) uInt8 TIADebug::audF0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(AUDF0, newVal); mySystem.pokeOob(AUDF0, newVal);
return myTIA.registerValue(AUDF0) & 0x1f; return myTIA.registerValue(AUDF0) & 0x1f;
} }
@ -560,7 +560,7 @@ uInt8 TIADebug::audF0(int newVal)
uInt8 TIADebug::audF1(int newVal) uInt8 TIADebug::audF1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(AUDF1, newVal); mySystem.pokeOob(AUDF1, newVal);
return myTIA.registerValue(AUDF1) & 0x1f; return myTIA.registerValue(AUDF1) & 0x1f;
} }
@ -569,7 +569,7 @@ uInt8 TIADebug::audF1(int newVal)
uInt8 TIADebug::pf0(int newVal) uInt8 TIADebug::pf0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(PF0, newVal << 4); mySystem.pokeOob(PF0, newVal << 4);
return myTIA.registerValue(PF0) >> 4; return myTIA.registerValue(PF0) >> 4;
} }
@ -578,7 +578,7 @@ uInt8 TIADebug::pf0(int newVal)
uInt8 TIADebug::pf1(int newVal) uInt8 TIADebug::pf1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(PF1, newVal); mySystem.pokeOob(PF1, newVal);
return myTIA.registerValue(PF1); return myTIA.registerValue(PF1);
} }
@ -587,7 +587,7 @@ uInt8 TIADebug::pf1(int newVal)
uInt8 TIADebug::pf2(int newVal) uInt8 TIADebug::pf2(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(PF2, newVal); mySystem.pokeOob(PF2, newVal);
return myTIA.registerValue(PF2); return myTIA.registerValue(PF2);
} }
@ -596,7 +596,7 @@ uInt8 TIADebug::pf2(int newVal)
uInt8 TIADebug::coluP0(int newVal) uInt8 TIADebug::coluP0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(COLUP0, newVal); mySystem.pokeOob(COLUP0, newVal);
return myTIA.registerValue(COLUP0); return myTIA.registerValue(COLUP0);
} }
@ -605,7 +605,7 @@ uInt8 TIADebug::coluP0(int newVal)
uInt8 TIADebug::coluP1(int newVal) uInt8 TIADebug::coluP1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(COLUP1, newVal); mySystem.pokeOob(COLUP1, newVal);
return myTIA.registerValue(COLUP1); return myTIA.registerValue(COLUP1);
} }
@ -614,7 +614,7 @@ uInt8 TIADebug::coluP1(int newVal)
uInt8 TIADebug::coluPF(int newVal) uInt8 TIADebug::coluPF(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(COLUPF, newVal); mySystem.pokeOob(COLUPF, newVal);
return myTIA.registerValue(COLUPF); return myTIA.registerValue(COLUPF);
} }
@ -623,7 +623,7 @@ uInt8 TIADebug::coluPF(int newVal)
uInt8 TIADebug::coluBK(int newVal) uInt8 TIADebug::coluBK(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(COLUBK, newVal); mySystem.pokeOob(COLUBK, newVal);
return myTIA.registerValue(COLUBK); return myTIA.registerValue(COLUBK);
} }
@ -632,7 +632,7 @@ uInt8 TIADebug::coluBK(int newVal)
uInt8 TIADebug::nusiz0(int newVal) uInt8 TIADebug::nusiz0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(NUSIZ0, newVal); mySystem.pokeOob(NUSIZ0, newVal);
return myTIA.registerValue(NUSIZ0); return myTIA.registerValue(NUSIZ0);
} }
@ -641,7 +641,7 @@ uInt8 TIADebug::nusiz0(int newVal)
uInt8 TIADebug::nusiz1(int newVal) uInt8 TIADebug::nusiz1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(NUSIZ1, newVal); mySystem.pokeOob(NUSIZ1, newVal);
return myTIA.registerValue(NUSIZ1); return myTIA.registerValue(NUSIZ1);
} }
@ -653,7 +653,7 @@ uInt8 TIADebug::nusizP0(int newVal)
{ {
uInt8 tmp = myTIA.registerValue(NUSIZ0) & ~0x07; uInt8 tmp = myTIA.registerValue(NUSIZ0) & ~0x07;
tmp |= (newVal & 0x07); tmp |= (newVal & 0x07);
mySystem.poke(NUSIZ0, tmp); mySystem.pokeOob(NUSIZ0, tmp);
} }
return myTIA.registerValue(NUSIZ0) & 0x07; return myTIA.registerValue(NUSIZ0) & 0x07;
@ -666,7 +666,7 @@ uInt8 TIADebug::nusizP1(int newVal)
{ {
uInt8 tmp = myTIA.registerValue(NUSIZ1) & ~0x07; uInt8 tmp = myTIA.registerValue(NUSIZ1) & ~0x07;
tmp |= newVal & 0x07; tmp |= newVal & 0x07;
mySystem.poke(NUSIZ1, tmp); mySystem.pokeOob(NUSIZ1, tmp);
} }
return myTIA.registerValue(NUSIZ1) & 0x07; return myTIA.registerValue(NUSIZ1) & 0x07;
@ -679,7 +679,7 @@ uInt8 TIADebug::nusizM0(int newVal)
{ {
uInt8 tmp = myTIA.registerValue(NUSIZ0) & ~0x30; uInt8 tmp = myTIA.registerValue(NUSIZ0) & ~0x30;
tmp |= (newVal & 0x04) << 4; tmp |= (newVal & 0x04) << 4;
mySystem.poke(NUSIZ0, tmp); mySystem.pokeOob(NUSIZ0, tmp);
} }
return (myTIA.registerValue(NUSIZ0) & 0x30) >> 4; return (myTIA.registerValue(NUSIZ0) & 0x30) >> 4;
@ -692,7 +692,7 @@ uInt8 TIADebug::nusizM1(int newVal)
{ {
uInt8 tmp = myTIA.registerValue(NUSIZ1) & ~0x30; uInt8 tmp = myTIA.registerValue(NUSIZ1) & ~0x30;
tmp |= (newVal & 0x04) << 4; tmp |= (newVal & 0x04) << 4;
mySystem.poke(NUSIZ1, tmp); mySystem.pokeOob(NUSIZ1, tmp);
} }
return (myTIA.registerValue(NUSIZ1) & 0x30) >> 4; return (myTIA.registerValue(NUSIZ1) & 0x30) >> 4;
@ -702,7 +702,7 @@ uInt8 TIADebug::nusizM1(int newVal)
uInt8 TIADebug::grP0(int newVal) uInt8 TIADebug::grP0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(GRP0, newVal); mySystem.pokeOob(GRP0, newVal);
return myTIA.registerValue(GRP0); return myTIA.registerValue(GRP0);
} }
@ -711,7 +711,7 @@ uInt8 TIADebug::grP0(int newVal)
uInt8 TIADebug::grP1(int newVal) uInt8 TIADebug::grP1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(GRP1, newVal); mySystem.pokeOob(GRP1, newVal);
return myTIA.registerValue(GRP1); return myTIA.registerValue(GRP1);
} }
@ -765,7 +765,7 @@ uInt8 TIADebug::posBL(int newVal)
uInt8 TIADebug::ctrlPF(int newVal) uInt8 TIADebug::ctrlPF(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(CTRLPF, newVal); mySystem.pokeOob(CTRLPF, newVal);
return myTIA.registerValue(CTRLPF); return myTIA.registerValue(CTRLPF);
} }
@ -777,7 +777,7 @@ uInt8 TIADebug::sizeBL(int newVal)
{ {
uInt8 tmp = myTIA.registerValue(CTRLPF) & ~0x30; uInt8 tmp = myTIA.registerValue(CTRLPF) & ~0x30;
tmp |= (newVal & 0x04) << 4; tmp |= (newVal & 0x04) << 4;
mySystem.poke(CTRLPF, tmp); mySystem.pokeOob(CTRLPF, tmp);
} }
return (myTIA.registerValue(CTRLPF) & 0x30) >> 4; return (myTIA.registerValue(CTRLPF) & 0x30) >> 4;
@ -787,7 +787,7 @@ uInt8 TIADebug::sizeBL(int newVal)
uInt8 TIADebug::hmP0(int newVal) uInt8 TIADebug::hmP0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(HMP0, newVal << 4); mySystem.pokeOob(HMP0, newVal << 4);
return myTIA.registerValue(HMP0) >> 4; return myTIA.registerValue(HMP0) >> 4;
} }
@ -796,7 +796,7 @@ uInt8 TIADebug::hmP0(int newVal)
uInt8 TIADebug::hmP1(int newVal) uInt8 TIADebug::hmP1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(HMP1, newVal << 4); mySystem.pokeOob(HMP1, newVal << 4);
return myTIA.registerValue(HMP1) >> 4; return myTIA.registerValue(HMP1) >> 4;
} }
@ -805,7 +805,7 @@ uInt8 TIADebug::hmP1(int newVal)
uInt8 TIADebug::hmM0(int newVal) uInt8 TIADebug::hmM0(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(HMM0, newVal << 4); mySystem.pokeOob(HMM0, newVal << 4);
return myTIA.registerValue(HMM0) >> 4; return myTIA.registerValue(HMM0) >> 4;
} }
@ -814,7 +814,7 @@ uInt8 TIADebug::hmM0(int newVal)
uInt8 TIADebug::hmM1(int newVal) uInt8 TIADebug::hmM1(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(HMM1, newVal << 4); mySystem.pokeOob(HMM1, newVal << 4);
return myTIA.registerValue(HMM1) >> 4; return myTIA.registerValue(HMM1) >> 4;
} }
@ -823,7 +823,7 @@ uInt8 TIADebug::hmM1(int newVal)
uInt8 TIADebug::hmBL(int newVal) uInt8 TIADebug::hmBL(int newVal)
{ {
if(newVal > -1) if(newVal > -1)
mySystem.poke(HMBL, newVal << 4); mySystem.pokeOob(HMBL, newVal << 4);
return myTIA.registerValue(HMBL) >> 4; return myTIA.registerValue(HMBL) >> 4;
} }
@ -849,61 +849,61 @@ void TIADebug::setENABLOld(bool b)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeWsync() void TIADebug::strobeWsync()
{ {
mySystem.poke(WSYNC, 0); mySystem.pokeOob(WSYNC, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeRsync() void TIADebug::strobeRsync()
{ {
mySystem.poke(RSYNC, 0); mySystem.pokeOob(RSYNC, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeResP0() void TIADebug::strobeResP0()
{ {
mySystem.poke(RESP0, 0); mySystem.pokeOob(RESP0, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeResP1() void TIADebug::strobeResP1()
{ {
mySystem.poke(RESP1, 0); mySystem.pokeOob(RESP1, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeResM0() void TIADebug::strobeResM0()
{ {
mySystem.poke(RESM0, 0); mySystem.pokeOob(RESM0, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeResM1() void TIADebug::strobeResM1()
{ {
mySystem.poke(RESM1, 0); mySystem.pokeOob(RESM1, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeResBL() void TIADebug::strobeResBL()
{ {
mySystem.poke(RESBL, 0); mySystem.pokeOob(RESBL, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeHmove() void TIADebug::strobeHmove()
{ {
mySystem.poke(HMOVE, 0); mySystem.pokeOob(HMOVE, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeHmclr() void TIADebug::strobeHmclr()
{ {
mySystem.poke(HMCLR, 0); mySystem.pokeOob(HMCLR, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIADebug::strobeCxclr() void TIADebug::strobeCxclr()
{ {
mySystem.poke(CXCLR, 0); mySystem.pokeOob(CXCLR, 0);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -964,7 +964,7 @@ int TIADebug::cyclesThisLine() const
bool TIADebug::vsync(int newVal) bool TIADebug::vsync(int newVal)
{ {
if (newVal > -1) if (newVal > -1)
mySystem.poke(VSYNC, newVal); mySystem.pokeOob(VSYNC, newVal);
return myTIA.registerValue(VSYNC) & 0x02; return myTIA.registerValue(VSYNC) & 0x02;
} }
@ -979,7 +979,7 @@ bool TIADebug::vsync() const
bool TIADebug::vblank(int newVal) bool TIADebug::vblank(int newVal)
{ {
if (newVal > -1) if (newVal > -1)
mySystem.poke(VBLANK, newVal); mySystem.pokeOob(VBLANK, newVal);
return myTIA.registerValue(VBLANK) & 0x02; return myTIA.registerValue(VBLANK) & 0x02;
} }

View File

@ -67,7 +67,7 @@ class DebuggerDialog : public Dialog
TiaOutputWidget& tiaOutput() const { return *myTiaOutput; } TiaOutputWidget& tiaOutput() const { return *myTiaOutput; }
TiaZoomWidget& tiaZoom() const { return *myTiaZoom; } TiaZoomWidget& tiaZoom() const { return *myTiaZoom; }
RomWidget& rom() const { return *myRom; } RomWidget& rom() const { return *myRom; }
CartDebugWidget& cartDebug() const { return *myCartDebug; } CartDebugWidget* cartDebug() const { return myCartDebug; }
CartRamWidget& cartRam() const { return *myCartRam; } CartRamWidget& cartRam() const { return *myCartRam; }
EditTextWidget& message() const { return *myMessageBox; } EditTextWidget& message() const { return *myMessageBox; }
ButtonWidget& rewindButton() const { return *myRewindButton; } ButtonWidget& rewindButton() const { return *myRewindButton; }

View File

@ -337,9 +337,9 @@ void CartridgeAR::loadIntoRAM(uInt8 load)
// Copy the bank switching byte and starting address into the 2600's // Copy the bank switching byte and starting address into the 2600's
// RAM for the "dummy" SC BIOS to access it // RAM for the "dummy" SC BIOS to access it
mySystem->poke(0xfe, myHeader[0]); mySystem->pokeOob(0xfe, myHeader[0]);
mySystem->poke(0xff, myHeader[1]); mySystem->pokeOob(0xff, myHeader[1]);
mySystem->poke(0x80, myHeader[2]); mySystem->pokeOob(0x80, myHeader[2]);
myBankChanged = true; myBankChanged = true;
if(success) if(success)

View File

@ -23,7 +23,41 @@
#include "CartELF.hxx" #include "CartELF.hxx"
namespace { namespace {
constexpr size_t READ_STREAM_CAPACITY = 512; constexpr size_t READ_STREAM_CAPACITY = 1024;
constexpr uInt8 OVERBLANK_PROGRAM[] = {
0xa0,0x00, // ldy #0
0xa5,0xe0, // lda $e0
// OverblankLoop:
0x85,0x02, // sta WSYNC
0x85,0x2d, // sta AUDV0 (currently using $2d instead to disable audio until fully implemented
0x98, // tya
0x18, // clc
0x6a, // ror
0xaa, // tax
0xb5,0xe0, // lda $e0,x
0x90,0x04, // bcc
0x4a, // lsr
0x4a, // lsr
0x4a, // lsr
0x4a, // lsr
0xc8, // iny
0xc0, 0x1d, // cpy #$1d
0xd0, 0x04, // bne
0xa2, 0x02, // ldx #2
0x86, 0x00, // stx VSYNC
0xc0, 0x20, // cpy #$20
0xd0, 0x04, // bne SkipClearVSync
0xa2, 0x00, // ldx #0
0x86, 0x00, // stx VSYNC
// SkipClearVSync:
0xc0, 0x3f, // cpy #$3f
0xd0, 0xdb, // bne OverblankLoop
// WaitForCart:
0xae, 0xff, 0xff, // ldx $ffff
0xd0, 0xfb, // bne WaitForCart
0x4c, 0x00, 0x10 // jmp $1000
};
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -34,6 +68,9 @@ CartridgeELF::CartridgeELF(const ByteBuffer& image, size_t size, string_view md5
myImage = make_unique<uInt8[]>(size); myImage = make_unique<uInt8[]>(size);
std::memcpy(myImage.get(), image.get(), size); std::memcpy(myImage.get(), image.get(), size);
myLastPeekResult = make_unique<uInt8[]>(0x1000);
std::fill_n(myLastPeekResult.get(), 0x1000, 0);
createRomAccessArrays(0x1000); createRomAccessArrays(0x1000);
} }
@ -44,7 +81,15 @@ CartridgeELF::~CartridgeELF() {}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::reset() void CartridgeELF::reset()
{ {
myReadStream.Reset(); std::fill_n(myLastPeekResult.get(), 0x1000, 0);
myReadStream.reset();
myReadStream.push(0x00, 0x0ffc);
myReadStream.push(0x10);
myReadStream.setNextPushAddress(0);
vcsCopyOverblankToRiotRam();
vcsStartOverblank();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -76,7 +121,16 @@ bool CartridgeELF::load(Serializer& in)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeELF::peek(uInt16 address) uInt8 CartridgeELF::peek(uInt16 address)
{ {
return myReadStream.Pop(address); if (myReadStream.isYield()) return mySystem->getDataBusState();
myLastPeekResult[address & 0xfff] = myReadStream.pop(address);
return myLastPeekResult[address & 0xfff];
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeELF::peekOob(uInt16 address)
{
return myLastPeekResult[address & 0xfff];
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -92,30 +146,62 @@ const ByteBuffer& CartridgeELF::getImage(size_t& size) const
return myImage; return myImage;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::vcsWrite5(uInt8 zpAddress, uInt8 value)
{
myReadStream.push(0xa9);
myReadStream.push(value);
myReadStream.push(0x85);
myReadStream.push(zpAddress);
myReadStream.yield();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::vcsCopyOverblankToRiotRam()
{
for (size_t i = 0; i < sizeof(OVERBLANK_PROGRAM); i++)
vcsWrite5(0x80 + i, OVERBLANK_PROGRAM[i]);
}
void CartridgeELF::vcsStartOverblank()
{
myReadStream.push(0x4c);
myReadStream.push(0x80);
myReadStream.push(0x00);
myReadStream.yield();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeELF::ReadStream::ReadStream() CartridgeELF::ReadStream::ReadStream()
{ {
myStream = make_unique<ScheduledRead[]>(READ_STREAM_CAPACITY); myStream = make_unique<ScheduledRead[]>(READ_STREAM_CAPACITY);
Reset(); reset();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::ReadStream::Reset() void CartridgeELF::ReadStream::reset()
{ {
myStreamNext = myStreamSize = 0; myStreamNext = myStreamSize = myNextPushAddress = 0;
myIsYield = true;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::ReadStream::Push(uInt8 value) void CartridgeELF::ReadStream::setNextPushAddress(uInt16 address)
{ {
if (myNextReadAddress == 0xfff) myNextPushAddress = address;
throw FatalEmulationError("read stream has reached the end of address space");
Push(value, myNextReadAddress + 1);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::ReadStream::Push(uInt8 value, uInt8 address) void CartridgeELF::ReadStream::push(uInt8 value)
{
if (myNextPushAddress > 0xfff)
throw FatalEmulationError("read stream pointer overflow");
push(value, myNextPushAddress);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeELF::ReadStream::push(uInt8 value, uInt16 address)
{ {
if (myStreamSize == READ_STREAM_CAPACITY) if (myStreamSize == READ_STREAM_CAPACITY)
throw FatalEmulationError("read stream overflow"); throw FatalEmulationError("read stream overflow");
@ -123,37 +209,57 @@ void CartridgeELF::ReadStream::Push(uInt8 value, uInt8 address)
address &= 0xfff; address &= 0xfff;
myStream[(myStreamNext + myStreamSize++) % READ_STREAM_CAPACITY] = myStream[(myStreamNext + myStreamSize++) % READ_STREAM_CAPACITY] =
{.address = address, .value = value}; {.address = address, .value = value, .yield = false};
myNextPushAddress = address + 1;
myIsYield = false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeELF::ReadStream::HasPendingRead() const void CartridgeELF::ReadStream::yield()
{
if (myStreamSize == 0)
throw new FatalEmulationError("yield called on empty stream");
myStream[(myStreamNext + myStreamSize - 1) % READ_STREAM_CAPACITY].yield = true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeELF::ReadStream::isYield() const
{
return myIsYield;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeELF::ReadStream::hasPendingRead() const
{ {
return myStreamSize > 0; return myStreamSize > 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 CartridgeELF::ReadStream::GetNextReadAddress() const uInt8 CartridgeELF::ReadStream::pop(uInt16 readAddress)
{ {
return myNextReadAddress; if (myStreamSize == 0) {
} ostringstream s;
s << "read stream underflow at 0x" << std::hex << std::setw(4) << readAddress;
throw FatalEmulationError(s.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if ((readAddress & 0xfff) != myStream[myStreamNext].address)
uInt8 CartridgeELF::ReadStream::Pop(uInt16 readAddress)
{
if (myStreamSize == 0)
throw FatalEmulationError("read stream underflow");
if ((readAddress & 0xfff) != myNextReadAddress)
{ {
ostringstream s; ostringstream s;
s << "unexcpected cartridge read from 0x" << std::hex << std::setw(4) << readAddress; s <<
"unexcpected cartridge read from 0x" << std::hex << std::setw(4) <<
std::setfill('0') << (readAddress & 0xfff) << " expected 0x" << myStream[myStreamNext].address;
throw FatalEmulationError(s.str()); throw FatalEmulationError(s.str());
} }
myIsYield = myStream[myStreamNext].yield && myStreamSize == 1;
const uInt8 value = myStream[myStreamNext++].value; const uInt8 value = myStream[myStreamNext++].value;
myStreamNext %= READ_STREAM_CAPACITY; myStreamNext %= READ_STREAM_CAPACITY;
myStreamSize--;
return value; return value;
} }

View File

@ -38,6 +38,7 @@ class CartridgeELF: public Cartridge {
bool load(Serializer& in) override; bool load(Serializer& in) override;
uInt8 peek(uInt16 address) override; uInt8 peek(uInt16 address) override;
uInt8 peekOob(uInt16 address) override;
bool poke(uInt16 address, uInt8 value) override; bool poke(uInt16 address, uInt8 value) override;
@ -51,31 +52,42 @@ class CartridgeELF: public Cartridge {
string name() const override { return "CartridgeELF"; }; string name() const override { return "CartridgeELF"; };
private:
void vcsWrite5(uInt8 zpAddress, uInt8 value);
void vcsCopyOverblankToRiotRam();
void vcsStartOverblank();
private: private:
struct ScheduledRead { struct ScheduledRead {
uInt16 address; uInt16 address;
uInt8 value; uInt8 value;
bool yield;
}; };
class ReadStream { class ReadStream {
public: public:
ReadStream(); ReadStream();
void Reset(); void reset();
void Push(uInt8 value); void setNextPushAddress(uInt16 address);
void Push(uInt8 value, uInt8 address); void push(uInt8 value);
void push(uInt8 value, uInt16 address);
bool HasPendingRead() const; void yield();
uInt16 GetNextReadAddress() const; bool isYield() const;
uInt8 Pop(uInt16 readAddress);
bool hasPendingRead() const;
uInt8 pop(uInt16 readAddress);
private: private:
unique_ptr<ScheduledRead[]> myStream; unique_ptr<ScheduledRead[]> myStream;
size_t myStreamNext{0}; size_t myStreamNext{0};
size_t myStreamSize{0}; size_t myStreamSize{0};
uInt16 myNextReadAddress{0}; uInt16 myNextPushAddress{0};
bool myIsYield{true};
}; };
private: private:
@ -84,6 +96,7 @@ class CartridgeELF: public Cartridge {
System* mySystem{nullptr}; System* mySystem{nullptr};
unique_ptr<uint8_t[]> myLastPeekResult;
ReadStream myReadStream; ReadStream myReadStream;
}; };

View File

@ -374,7 +374,7 @@ bool CartridgeEnhanced::patch(uInt16 address, uInt8 value)
// However, the patch command is special in that ignores such // However, the patch command is special in that ignores such
// cart restrictions // cart restrictions
myRAM[address & myRamMask] = value; myRAM[address & myRamMask] = value;
mySystem->poke(address, value); // keep RIOT RAM in sync mySystem->pokeOob(address, value); // keep RIOT RAM in sync
} }
else else
myImage[romAddressSegmentOffset(address) + (address & myBankMask)] = value; myImage[romAddressSegmentOffset(address) + (address & myBankMask)] = value;

View File

@ -789,7 +789,7 @@ void Console::initializeAudio()
void Console::fry() const void Console::fry() const
{ {
for(int i = 0; i < 0x100; i += mySystem->randGenerator().next() % 4) for(int i = 0; i < 0x100; i += mySystem->randGenerator().next() % 4)
mySystem->poke(i, mySystem->peek(i) & mySystem->randGenerator().next()); mySystem->pokeOob(i, mySystem->peekOob(i) & mySystem->randGenerator().next());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -119,6 +119,7 @@ class Device : public Serializable
@return The byte at the specified address @return The byte at the specified address
*/ */
virtual uInt8 peek(uInt16 address) = 0; virtual uInt8 peek(uInt16 address) = 0;
virtual uInt8 peekOob(uInt16 address) { return peek(address); };
/** /**
Change the byte at the specified address to the given value Change the byte at the specified address to the given value
@ -129,6 +130,7 @@ class Device : public Serializable
@return True if the poke changed the device address space, else false @return True if the poke changed the device address space, else false
*/ */
virtual bool poke(uInt16 address, uInt8 value) { return false; } virtual bool poke(uInt16 address, uInt8 value) { return false; }
virtual bool pokeOob(uInt16 address, uInt8 value) { return poke(address, value); }
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
/** /**

View File

@ -97,7 +97,8 @@ void System::clearDirtyPages()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 System::peek(uInt16 addr, Device::AccessFlags flags) template<bool oob>
uInt8 System::peekImpl(uInt16 addr, Device::AccessFlags flags)
{ {
const PageAccess& access = getPageAccess(addr); const PageAccess& access = getPageAccess(addr);
@ -120,7 +121,7 @@ uInt8 System::peek(uInt16 addr, Device::AccessFlags flags)
// See if this page uses direct accessing or not // See if this page uses direct accessing or not
const uInt8 result = access.directPeekBase const uInt8 result = access.directPeekBase
? *(access.directPeekBase + (addr & PAGE_MASK)) ? *(access.directPeekBase + (addr & PAGE_MASK))
: access.device->peek(addr); : (oob ? access.device->peekOob(addr) : access.device->peek(addr));
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
if(!myDataBusLocked) if(!myDataBusLocked)
@ -130,8 +131,15 @@ uInt8 System::peek(uInt16 addr, Device::AccessFlags flags)
return result; return result;
} }
template
uInt8 System::peekImpl<true>(uInt16 addr, Device::AccessFlags flags);
template
uInt8 System::peekImpl<false>(uInt16 addr, Device::AccessFlags flags);
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void System::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags) template<bool oob>
void System::pokeImpl(uInt16 addr, uInt8 value, Device::AccessFlags flags)
{ {
const uInt16 page = (addr & ADDRESS_MASK) >> PAGE_SHIFT; const uInt16 page = (addr & ADDRESS_MASK) >> PAGE_SHIFT;
const PageAccess& access = myPageAccessTable[page]; const PageAccess& access = myPageAccessTable[page];
@ -162,7 +170,7 @@ void System::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags)
else else
{ {
// The specific device informs us if the poke succeeded // The specific device informs us if the poke succeeded
myPageIsDirtyTable[page] = access.device->poke(addr, value); myPageIsDirtyTable[page] = oob ? access.device->pokeOob(addr, value) : access.device->poke(addr, value);
} }
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
@ -171,6 +179,12 @@ void System::poke(uInt16 addr, uInt8 value, Device::AccessFlags flags)
myDataBusState = value; myDataBusState = value;
} }
template
void System::pokeImpl<true>(uInt16 addr, uInt8 value, Device::AccessFlags flags);
template
void System::pokeImpl<false>(uInt16 addr, uInt8 value, Device::AccessFlags flags);
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Device::AccessFlags System::getAccessFlags(uInt16 addr) const Device::AccessFlags System::getAccessFlags(uInt16 addr) const

View File

@ -169,32 +169,36 @@ class System : public Serializable
uInt8 getDataBusState() const { return myDataBusState; } uInt8 getDataBusState() const { return myDataBusState; }
/** /**
Get the byte at the specified address. No masking of the * See peekImpl below.
address occurs before it's sent to the device mapped at */
the address. inline uInt8 peek(uInt16 address, Device::AccessFlags flags = Device::NONE)
{
@param address The address from which the value should be loaded return peekImpl<false>(address, flags);
@param flags Indicates that this address has the given flags }
for type of access (CODE, DATA, GFX, etc)
@return The byte at the specified address
*/
uInt8 peek(uInt16 address, Device::AccessFlags flags = Device::NONE);
/** /**
Change the byte at the specified address to the given value. * See peekImpl below.
No masking of the address occurs before it's sent to the device */
mapped at the address. inline uInt8 peekOob(uInt16 address, Device::AccessFlags flags = Device::NONE)
{
return peekImpl<true>(address, flags);
}
This method sets the 'page dirty' if the write succeeds. In the /**
case of direct-access pokes, the write always succeeds. Otherwise, * See pokeImpl below.
if the device is handling the poke, we depend on its return value */
for this information. inline void poke(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE)
{
pokeImpl<false>(address, value, flags);
}
@param address The address where the value should be stored /**
@param value The value to be stored at the address * See pokeImpl below.
*/ */
void poke(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE); inline void pokeOob(uInt16 address, uInt8 value, Device::AccessFlags flags = Device::NONE)
{
pokeImpl<true>(address, value, flags);
}
/** /**
Lock/unlock the data bus. When the bus is locked, peek() and Lock/unlock the data bus. When the bus is locked, peek() and
@ -365,6 +369,41 @@ class System : public Serializable
*/ */
bool load(Serializer& in) override; bool load(Serializer& in) override;
private:
/**
Get the byte at the specified address. No masking of the
address occurs before it's sent to the device mapped at
the address.
@param oob Out-of-band peeks are not part of the activity of the
emulated system
@param address The address from which the value should be loaded
@param flags Indicates that this address has the given flags
for type of access (CODE, DATA, GFX, etc)
@return The byte at the specified address
*/
template<bool oob = false>
uInt8 peekImpl(uInt16 address, Device::AccessFlags flags);
/**
Change the byte at the specified address to the given value.
No masking of the address occurs before it's sent to the device
mapped at the address.
This method sets the 'page dirty' if the write succeeds. In the
case of direct-access pokes, the write always succeeds. Otherwise,
if the device is handling the poke, we depend on its return value
for this information.
@param oob Out-of-band peeks are not part of the activity of the
emulated system
@param address The address where the value should be stored
@param value The value to be stored at the address
*/
template<bool oob = false>
void pokeImpl(uInt16 address, uInt8 value, Device::AccessFlags flags);
private: private:
// The system RNG // The system RNG
Random& myRandom; Random& myRandom;