Commit ecb6c7a5 authored by thrust26's avatar thrust26
Browse files

Implemented solution for #396

parent a7f8d672
......@@ -163,6 +163,9 @@ void CartDebug::triggerReadFromWritePort(uInt16 addr)
{
myRWPortAddress = addr;
mySystem.setDirtyPage(addr);
#ifdef DEBUGGER_SUPPORT
mySystem.m6502().setReadFromWritePort(addr);
#endif // DEBUGGER_SUPPORT
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
......
......@@ -73,7 +73,9 @@ M6502::M6502(const Settings& settings)
myOnHaltCallback(nullptr),
myHaltRequested(false),
myGhostReadsTrap(true),
myStepStateByInstruction(false)
myStepStateByInstruction(false),
myReadFromWritePortBreak(false),
myReadFromWritePortAddr(0)
{
#ifdef DEBUGGER_SUPPORT
myDebugger = nullptr;
......@@ -120,6 +122,7 @@ void M6502::reset()
myHaltRequested = false;
myGhostReadsTrap = mySettings.getBool("dbg.ghostreadstrap");
myReadFromWritePortBreak = mySettings.getBool(devSettings ? "dev.rwportbreak" : "plr.rwportbreak");
myLastBreakCycle = ULLONG_MAX;
}
......@@ -289,6 +292,18 @@ inline void M6502::_execute(uInt64 cycles, DispatchResult& result)
result.setDebugger(currentCycles, msg.str());
return;
}
int rwAddr = readFromWritePort();
if(rwAddr)
{
stringstream msg;
msg << "RWP[@ $" << Common::Base::HEX4 << rwAddr << "]: ";
myLastBreakCycle = mySystem->cycles();
result.setDebugger(currentCycles, msg.str(), PC);
return;
}
}
int cond = evalCondSaveStates();
......@@ -437,6 +452,8 @@ bool M6502::save(Serializer& out) const
out.putBool(myHaltRequested);
out.putBool(myStepStateByInstruction);
out.putBool(myGhostReadsTrap);
out.putBool(myReadFromWritePortBreak);
out.putInt(myReadFromWritePortAddr);
out.putLong(myLastBreakCycle);
}
catch(...)
......@@ -485,7 +502,8 @@ bool M6502::load(Serializer& in)
myHaltRequested = in.getBool();
myStepStateByInstruction = in.getBool();
myGhostReadsTrap = in.getBool();
myReadFromWritePortBreak = in.getBool();
myReadFromWritePortAddr = in.getInt();
myLastBreakCycle = in.getLong();
}
catch(...)
......@@ -635,4 +653,21 @@ void M6502::updateStepStateByInstruction()
myTrapConds.size();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int M6502::readFromWritePort()
{
uInt16 addr = myReadFromWritePortAddr;
myReadFromWritePortAddr = 0;
// A read from the write port occurs when the read is actually in the write
// port address space AND the last access was actually a read (the latter
// differentiates between reads that are normally part of a write cycle vs.
// ones that are illegal)
if(myReadFromWritePortBreak && lastReadAddress() &&
(mySystem->getPageAccessType(addr) & System::PA_WRITE) == System::PA_WRITE)
return addr;
else
return 0;
}
#endif // DEBUGGER_SUPPORT
......@@ -242,6 +242,9 @@ class M6502 : public Serializable
const StringList& getCondTrapNames() const;
void setGhostReadsTrap(bool enable) { myGhostReadsTrap = enable; }
void setReadFromWritePortBreak(bool enable) { myReadFromWritePortBreak = enable; }
void setReadFromWritePort(uInt16 addr) { myReadFromWritePortAddr = addr; };
int readFromWritePort();
#endif // DEBUGGER_SUPPORT
private:
......@@ -461,6 +464,8 @@ class M6502 : public Serializable
// in save states, they cannot be conditionally compiled
bool myGhostReadsTrap; // trap on ghost reads
bool myStepStateByInstruction;
bool myReadFromWritePortBreak;
uInt16 myReadFromWritePortAddr;
private:
// Following constructors and assignment operators not supported
......
......@@ -149,6 +149,8 @@ Settings::Settings(OSystem& osystem)
setInternal("dis.gfxformat", "2");
setInternal("dis.showaddr", "true");
setInternal("dis.relocate", "false");
setInternal("plr.rwportbreak", "false");
setInternal("dev.rwportbreak", "true");
#endif
// player settings
......@@ -620,6 +622,9 @@ void Settings::usage() const
<< " -plr.tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -plr.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
<< " read/peek\n"
#ifdef DEBUGGER_SUPPORT
<< " -plr.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
#endif
<< " -plr.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
<< " throw an exception\n"
<< " -plr.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
......@@ -639,6 +644,9 @@ void Settings::usage() const
<< " -dev.tv.jitter_recovery <1-20> Set recovery time for TV jitter effect\n"
<< " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
<< " read/peek\n"
#ifdef DEBUGGER_SUPPORT
<< " -dev.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
#endif
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
<< " throw an exception\n"
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
......
......@@ -151,6 +151,11 @@ void DeveloperDialog::addEmulationTab(const GUI::Font& font)
wid.push_back(myUndrivenPinsWidget);
ypos += lineHeight + VGAP;
myRWPortBreakWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
"Break on reads from write ports");
wid.push_back(myRWPortBreakWidget);
ypos += lineHeight + VGAP;
// Thumb ARM emulation exception
myThumbExceptionWidget = new CheckboxWidget(myTab, font, HBORDER + INDENT * 1, ypos + 1,
"Fatal ARM emulation error throws exception");
......@@ -445,7 +450,7 @@ void DeveloperDialog::addDebuggerTab(const GUI::Font& font)
ypos += lineHeight + VGAP * 4;
myGhostReadsTrapWidget = new CheckboxWidget(myTab, font, HBORDER, ypos + 1,
"Trap on 'ghost' reads", kGhostReads);
"Trap on 'ghost' reads");
wid.push_back(myGhostReadsTrapWidget);
// Add message concerning usage
......@@ -487,6 +492,8 @@ void DeveloperDialog::loadSettings(SettingsSet set)
myRandomizeCPU[set] = instance().settings().getString(prefix + "cpurandom");
// Undriven TIA pins
myUndrivenPins[set] = instance().settings().getBool(prefix + "tiadriven");
// Read from write ports break
myRWPortBreak[set] = instance().settings().getBool(prefix + "rwportbreak");
// Thumb ARM emulation exception
myThumbException[set] = instance().settings().getBool(prefix + "thumb.trapfatal");
// AtariVox/SaveKey EEPROM access
......@@ -521,6 +528,8 @@ void DeveloperDialog::saveSettings(SettingsSet set)
instance().settings().setValue(prefix + "cpurandom", myRandomizeCPU[set]);
// Undriven TIA pins
instance().settings().setValue(prefix + "tiadriven", myUndrivenPins[set]);
// Read from write ports break
instance().settings().setValue(prefix + "rwportbreak", myRWPortBreak[set]);
// Thumb ARM emulation exception
instance().settings().setValue(prefix + "thumb.trapfatal", myThumbException[set]);
// AtariVox/SaveKey EEPROM access
......@@ -558,6 +567,8 @@ void DeveloperDialog::getWidgetStates(SettingsSet set)
myRandomizeCPU[set] = cpurandom;
// Undriven TIA pins
myUndrivenPins[set] = myUndrivenPinsWidget->getState();
// Read from write ports break
myRWPortBreak[set] = myRWPortBreakWidget->getState();
// Thumb ARM emulation exception
myThumbException[set] = myThumbExceptionWidget->getState();
// AtariVox/SaveKey EEPROM access
......@@ -595,6 +606,8 @@ void DeveloperDialog::setWidgetStates(SettingsSet set)
myRandomizeCPUWidget[i]->setState(BSPF::containsIgnoreCase(cpurandom, cpuregs[i]));
// Undriven TIA pins
myUndrivenPinsWidget->setState(myUndrivenPins[set]);
// Read from write ports break
myRWPortBreakWidget->setState(myRWPortBreak[set]);
// Thumb ARM emulation exception
myThumbExceptionWidget->setState(myThumbException[set]);
// AtariVox/SaveKey EEPROM access
......@@ -682,6 +695,10 @@ void DeveloperDialog::saveConfig()
saveSettings(SettingsSet::player);
saveSettings(SettingsSet::developer);
// Read from write ports break
if(instance().hasConsole())
instance().console().system().m6502().setReadFromWritePortBreak(myRWPortBreakWidget->getState());
// activate the current settings
instance().frameBuffer().showFrameStats(myFrameStatsWidget->getState());
// jitter
......@@ -743,6 +760,8 @@ void DeveloperDialog::setDefaults()
myRandomizeCPU[set] = devSettings ? "SAXYP" : "AXYP";
// Undriven TIA pins
myUndrivenPins[set] = devSettings ? true : false;
// Reads from write ports
myRWPortBreak[set] = devSettings ? true : false;
// Thumb ARM emulation exception
myThumbException[set] = devSettings ? true : false;
// AtariVox/SaveKey EEPROM access
......
......@@ -75,7 +75,6 @@ class DeveloperDialog : public Dialog
kBLColourChangedCmd = 'GObl',
#ifdef DEBUGGER_SUPPORT
kDFontSizeChanged = 'UIfs',
kGhostReads = 'Dbgh'
#endif
};
enum SettingsSet
......@@ -101,6 +100,9 @@ class DeveloperDialog : public Dialog
StaticTextWidget* myRandomizeCPULabel;
CheckboxWidget* myRandomizeCPUWidget[5];
CheckboxWidget* myUndrivenPinsWidget;
#ifdef DEBUGGER_SUPPORT
CheckboxWidget* myRWPortBreakWidget;
#endif
CheckboxWidget* myThumbExceptionWidget;
CheckboxWidget* myEEPROMAccessWidget;
......@@ -143,6 +145,9 @@ class DeveloperDialog : public Dialog
int myTVJitterRec[2];
bool myDebugColors[2];
bool myUndrivenPins[2];
#ifdef DEBUGGER_SUPPORT
bool myRWPortBreak[2];
#endif
bool myThumbException[2];
bool myEEPROMAccess[2];
// States sets
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment