mirror of https://github.com/stella-emu/stella.git
further enhanced ARM cycle counts
This commit is contained in:
parent
22f9db40b9
commit
42f44b3bdb
|
@ -3543,14 +3543,23 @@
|
||||||
compared to real hardware.</td>
|
compared to real hardware.</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><pre>-dev.thumb.incycles <1|0></pre></td>
|
<td><pre>-dev.thumb.incycles <1|0></pre></td>
|
||||||
<td>When enabled, ARM emulation cycles are added to system cycles. This
|
<td>When enabled, ARM emulation cycles are added to 6507 system cycles. This
|
||||||
allows detecting timer overruns, but will also distort IRQ driven audio.</br>
|
allows detecting timer overruns, but will also distort audio.</br>
|
||||||
Note: The ARM emulation cycles are only a coarse approximation.
|
Note: The ARM emulation cycles are only a coarse approximation.
|
||||||
</td>
|
</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><pre>-dev.thumb.cyclefactor <float></pre></td>
|
<td><pre>-dev.thumb.cyclefactor <float></pre></td>
|
||||||
<td>Adjust ARM emulation cycles by a factor (1.25 = default).
|
<td>Defines the ARM cycle count correction factor (default = 0.95).</td>
|
||||||
</td>
|
</tr><tr>
|
||||||
|
<td><pre>-dev.thumb.chiptype <0|1></pre></td>
|
||||||
|
<td>Selects the emulated chip type (0 = LPC2103, 1 = LPC2104 family). This
|
||||||
|
setting affects the CPU clock, the Flash memory access clock cycles and
|
||||||
|
the number of Flash banks.</td>
|
||||||
|
</tr><tr>
|
||||||
|
<td><pre>-dev.thumb.mammode <0..3></pre></td>
|
||||||
|
<td>Selects the Memory Accelerator Module (MAM) mode.</br>
|
||||||
|
Note: Mode X (3) is for testing only. It reduces Flash memory access
|
||||||
|
clock cycles to always 1.</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td><pre>-<plr.|dev.>eepromaccess <1|0></pre></td>
|
<td><pre>-<plr.|dev.>eepromaccess <1|0></pre></td>
|
||||||
<td>When enabled, each read or write access to the AtariVox/SaveKey EEPROM is
|
<td>When enabled, each read or write access to the AtariVox/SaveKey EEPROM is
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include "OSystem.hxx"
|
#include "OSystem.hxx"
|
||||||
#include "EditTextWidget.hxx"
|
//#include "EditTextWidget.hxx"
|
||||||
|
#include "PopUpWidget.hxx"
|
||||||
|
#include "DataGridWidget.hxx"
|
||||||
#include "CartARMWidget.hxx"
|
#include "CartARMWidget.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -35,125 +37,147 @@ void CartridgeARMWidget::addCycleWidgets(int xpos, int ypos)
|
||||||
{
|
{
|
||||||
const int INDENT = 20;
|
const int INDENT = 20;
|
||||||
const int VGAP = 4;
|
const int VGAP = 4;
|
||||||
|
VariantList items;
|
||||||
|
|
||||||
new StaticTextWidget(_boss, _font, xpos, ypos + 1, "ARM emulation cycles:");
|
new StaticTextWidget(_boss, _font, xpos, ypos + 1, "ARM emulation cycles:");
|
||||||
xpos += INDENT; ypos += myLineHeight + VGAP;
|
xpos += INDENT; ypos += myLineHeight + VGAP;
|
||||||
myIncCycles = new CheckboxWidget(_boss, _font, xpos, ypos + 1, "Increase 6507 cycles", kIncCyclesChanged);
|
myIncCycles = new CheckboxWidget(_boss, _font, xpos, ypos + 1, "Increase 6507 cycles",
|
||||||
|
kIncCyclesChanged);
|
||||||
myIncCycles->setToolTip("Increase 6507 cycles with approximated ARM cycles.");
|
myIncCycles->setToolTip("Increase 6507 cycles with approximated ARM cycles.");
|
||||||
myIncCycles->setTarget(this);
|
myIncCycles->setTarget(this);
|
||||||
addFocusWidget(myIncCycles);
|
|
||||||
|
|
||||||
myCycleFactor = new SliderWidget(_boss, _font, myIncCycles->getRight() + _fontWidth * 2, ypos - 1,
|
myCycleFactor = new SliderWidget(_boss, _font, myIncCycles->getRight() + _fontWidth * 2, ypos - 1,
|
||||||
_fontWidth * 10, _lineHeight, "Factor ", _fontWidth * 7,
|
_fontWidth * 10, _lineHeight, "Cycle factor", _fontWidth * 14,
|
||||||
kFactorChanged, _fontWidth * 4, "%");
|
kFactorChanged, _fontWidth * 4, "%");
|
||||||
myCycleFactor->setMinValue(90); myCycleFactor->setMaxValue(110);
|
myCycleFactor->setMinValue(80); myCycleFactor->setMaxValue(100);
|
||||||
myCycleFactor->setTickmarkIntervals(4);
|
myCycleFactor->setTickmarkIntervals(4);
|
||||||
myCycleFactor->setToolTip("Multiply approximated ARM cycles by factor.");
|
myCycleFactor->setToolTip("Correct approximated ARM cycles by factor.");
|
||||||
myCycleFactor->setTarget(this);
|
myCycleFactor->setTarget(this);
|
||||||
addFocusWidget(myCycleFactor);
|
|
||||||
|
|
||||||
ypos += myLineHeight + VGAP;
|
ypos += (myLineHeight + VGAP) * 2;
|
||||||
StaticTextWidget* s = new StaticTextWidget(_boss, _font, xpos, ypos + 1, "Cycles ");
|
myCyclesLabel = new StaticTextWidget(_boss, _font, xpos, ypos + 1, "Cycles #");
|
||||||
|
|
||||||
myPrevThumbCycles = new EditTextWidget(_boss, _font, s->getRight(), ypos - 1,
|
myPrevThumbCycles = new DataGridWidget(_boss, _font, myCyclesLabel->getRight(), ypos - 1,
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
myPrevThumbCycles->setEditable(false);
|
myPrevThumbCycles->setEditable(false);
|
||||||
myPrevThumbCycles->setToolTip("Number of approximated CPU cycles of last but one ARM run.");
|
myPrevThumbCycles->setToolTip("Approximated CPU cycles of last but one ARM run.\n");
|
||||||
|
|
||||||
|
myThumbCycles = new DataGridWidget(_boss, _font,
|
||||||
|
myPrevThumbCycles->getRight() + _fontWidth / 2, ypos - 1,
|
||||||
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
|
|
||||||
myThumbCycles = new EditTextWidget(_boss, _font, myPrevThumbCycles->getRight() + _fontWidth / 2, ypos - 1,
|
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myThumbCycles->setEditable(false);
|
myThumbCycles->setEditable(false);
|
||||||
myThumbCycles->setToolTip("Number of approximated CPU cycles of last ARM run.");
|
myThumbCycles->setToolTip("Approximated CPU cycles of last ARM run.\n");
|
||||||
|
|
||||||
s = new StaticTextWidget(_boss, _font, myThumbCycles->getRight() + _fontWidth * 2, ypos + 1, "Fetches ");
|
StaticTextWidget* s = new StaticTextWidget(_boss, _font, myCycleFactor->getLeft(), ypos + 1,
|
||||||
myPrevThumbFetches = new EditTextWidget(_boss, _font, s->getRight(), ypos - 1,
|
"Instructions #");
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
|
||||||
myPrevThumbFetches->setEditable(false);
|
|
||||||
myPrevThumbFetches->setToolTip("Number of fetches/instructions of last but one ARM run.");
|
|
||||||
|
|
||||||
myThumbFetches = new EditTextWidget(_boss, _font, myPrevThumbFetches->getRight() + _fontWidth / 2, ypos - 1,
|
myPrevThumbInstructions = new DataGridWidget(_boss, _font, s->getRight(), ypos - 1,
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
myThumbFetches->setEditable(false);
|
myPrevThumbInstructions->setEditable(false);
|
||||||
myThumbFetches->setToolTip("Number of fetches/instructions of last ARM run.");
|
myPrevThumbInstructions->setToolTip("Instructions of last but one ARM run.\n");
|
||||||
|
|
||||||
ypos += myLineHeight + VGAP;
|
myThumbInstructions = new DataGridWidget(_boss, _font,
|
||||||
s = new StaticTextWidget(_boss, _font, xpos, ypos + 1, "Reads ");
|
myPrevThumbInstructions->getRight() + _fontWidth / 2, ypos - 1,
|
||||||
|
1, 1, 6, 32, Common::Base::Fmt::_10_6);
|
||||||
|
myThumbInstructions->setEditable(false);
|
||||||
|
myThumbInstructions->setToolTip("Instructions of last ARM run.\n");
|
||||||
|
|
||||||
myPrevThumbReads = new EditTextWidget(_boss, _font, myPrevThumbCycles->getLeft(), ypos - 1,
|
// add later to allow aligning
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
ypos -= myLineHeight + VGAP;
|
||||||
myPrevThumbReads->setEditable(false);
|
int pwidth = myThumbCycles->getRight() - myPrevThumbCycles->getLeft()
|
||||||
myPrevThumbReads->setToolTip("Number of reads of last but one ARM run.");
|
- PopUpWidget::dropDownWidth(_font);
|
||||||
|
|
||||||
myThumbReads = new EditTextWidget(_boss, _font, myThumbCycles->getLeft(), ypos - 1,
|
items.clear();
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
VarList::push_back(items, "LPC2101/2/3", static_cast<uInt32>(Thumbulator::ChipType::LPC2103));
|
||||||
myThumbReads->setEditable(false);
|
VarList::push_back(items, "LPC2104/5/6", static_cast<uInt32>(Thumbulator::ChipType::LPC2104));
|
||||||
myThumbReads->setToolTip("Number of reads of last ARM run.");
|
myChipType = new PopUpWidget(_boss, _font, xpos, ypos, pwidth, myLineHeight, items,
|
||||||
|
"Chip ", 0, kChipChanged);
|
||||||
|
myChipType->setToolTip("Select emulated ARM chip.");
|
||||||
|
myChipType->setTarget(this);
|
||||||
|
|
||||||
s = new StaticTextWidget(_boss, _font, myThumbReads->getRight() + _fontWidth * 2, ypos + 1, "Writes ");
|
myLockMamMode = new CheckboxWidget(_boss, _font, myCycleFactor->getLeft(), ypos + 1, "MAM Mode",
|
||||||
|
kMamLockChanged);
|
||||||
|
myLockMamMode->setToolTip("Check to lock Memory Accelerator Module (MAM) mode.");
|
||||||
|
myLockMamMode->setTarget(this);
|
||||||
|
|
||||||
myPrevThumbWrites = new EditTextWidget(_boss, _font, myPrevThumbFetches->getLeft(), ypos - 1,
|
pwidth = myThumbInstructions->getRight() - myPrevThumbInstructions->getLeft()
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
- PopUpWidget::dropDownWidth(_font);
|
||||||
myPrevThumbWrites->setEditable(false);
|
items.clear();
|
||||||
myPrevThumbWrites->setToolTip("Number of writes of last but one ARM run.");
|
VarList::push_back(items, "Off (0)", static_cast<uInt32>(Thumbulator::MamModeType::mode0));
|
||||||
|
VarList::push_back(items, "Partial (1)", static_cast<uInt32>(Thumbulator::MamModeType::mode1));
|
||||||
|
VarList::push_back(items, "Full (2)", static_cast<uInt32>(Thumbulator::MamModeType::mode2));
|
||||||
|
VarList::push_back(items, "1 Cycle (X)", static_cast<uInt32>(Thumbulator::MamModeType::modeX));
|
||||||
|
myMamMode = new PopUpWidget(_boss, _font, myPrevThumbInstructions->getLeft(), ypos,
|
||||||
|
pwidth, myLineHeight, items, "", 0, kMamModeChanged);
|
||||||
|
myMamMode->setToolTip("Select emulated Memory Accelerator Module (MAM) mode.");
|
||||||
|
myMamMode->setTarget(this);
|
||||||
|
|
||||||
myThumbWrites = new EditTextWidget(_boss, _font, myThumbFetches->getLeft(), ypos - 1,
|
// define the tab order
|
||||||
EditTextWidget::calcWidth(_font, 6), myLineHeight, "");
|
addFocusWidget(myIncCycles);
|
||||||
myThumbWrites->setEditable(false);
|
addFocusWidget(myCycleFactor);
|
||||||
myThumbWrites->setToolTip("Number of writes of last ARM run.");
|
addFocusWidget(myChipType);
|
||||||
|
addFocusWidget(myLockMamMode);
|
||||||
|
addFocusWidget(myMamMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeARMWidget::saveOldState()
|
void CartridgeARMWidget::saveOldState()
|
||||||
{
|
{
|
||||||
myOldState.armPrevStats.clear();
|
myOldState.armPrevRun.clear();
|
||||||
myOldState.armStats.clear();
|
myOldState.armRun.clear();
|
||||||
|
|
||||||
myOldState.armPrevStats.push_back(myCart.prevStats().cycles);
|
myOldState.mamMode = static_cast<uInt32>(myCart.mamMode());
|
||||||
myOldState.armPrevStats.push_back(myCart.prevStats().fetches);
|
|
||||||
myOldState.armPrevStats.push_back(myCart.prevStats().reads);
|
|
||||||
myOldState.armPrevStats.push_back(myCart.prevStats().writes);
|
|
||||||
|
|
||||||
myOldState.armStats.push_back(myCart.stats().cycles);
|
myOldState.armPrevRun.push_back(myCart.prevCycles());
|
||||||
myOldState.armStats.push_back(myCart.stats().fetches);
|
myOldState.armPrevRun.push_back(myCart.prevStats().instructions);
|
||||||
myOldState.armStats.push_back(myCart.stats().reads);
|
|
||||||
myOldState.armStats.push_back(myCart.stats().writes);
|
myOldState.armRun.push_back(myCart.cycles());
|
||||||
|
myOldState.armRun.push_back(myCart.stats().instructions);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeARMWidget::loadConfig()
|
void CartridgeARMWidget::loadConfig()
|
||||||
{
|
{
|
||||||
|
bool isChanged;
|
||||||
|
bool devSettings = instance().settings().getBool("dev.settings");
|
||||||
|
IntArray alist;
|
||||||
|
IntArray vlist;
|
||||||
|
BoolArray changed;
|
||||||
|
|
||||||
|
myChipType->setSelectedIndex(static_cast<uInt32>(instance().settings().getInt("dev.thumb.chiptype")));
|
||||||
|
handleChipType();
|
||||||
|
|
||||||
|
isChanged = static_cast<uInt32>(myCart.mamMode()) != myOldState.mamMode;
|
||||||
|
myMamMode->setSelectedIndex(static_cast<uInt32>(myCart.mamMode()), isChanged);
|
||||||
|
myMamMode->setEnabled(devSettings && myLockMamMode->getState());
|
||||||
|
myLockMamMode->setEnabled(devSettings);
|
||||||
|
|
||||||
// ARM cycles
|
// ARM cycles
|
||||||
myIncCycles->setState(instance().settings().getBool("dev.thumb.inccycles"));
|
myIncCycles->setState(instance().settings().getBool("dev.thumb.inccycles"));
|
||||||
myCycleFactor->setValue(std::round(instance().settings().getFloat("dev.thumb.cyclefactor") * 100.F));
|
myCycleFactor->setValue(std::round(instance().settings().getFloat("dev.thumb.cyclefactor") * 100.F));
|
||||||
handleArmCycles();
|
handleArmCycles();
|
||||||
|
|
||||||
bool isChanged;
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
|
alist.push_back(0); vlist.push_back(myCart.prevCycles());
|
||||||
|
changed.push_back(myCart.prevCycles() != uInt32(myOldState.armPrevRun[0]));
|
||||||
|
myPrevThumbCycles->setList(alist, vlist, changed);
|
||||||
|
|
||||||
isChanged = myCart.prevStats().cycles != myOldState.armPrevStats[0];
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
myPrevThumbCycles->setText(Common::Base::toString(myCart.prevStats().cycles,
|
alist.push_back(0); vlist.push_back(myCart.prevStats().instructions);
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
changed.push_back(myCart.prevStats().instructions != uInt32(myOldState.armPrevRun[1]));
|
||||||
isChanged = myCart.prevStats().fetches != myOldState.armPrevStats[1];
|
myPrevThumbInstructions->setList(alist, vlist, changed);
|
||||||
myPrevThumbFetches->setText(Common::Base::toString(myCart.prevStats().fetches,
|
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
|
||||||
isChanged = myCart.prevStats().reads != myOldState.armPrevStats[2];
|
|
||||||
myPrevThumbReads->setText(Common::Base::toString(myCart.prevStats().reads,
|
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
|
||||||
isChanged = myCart.prevStats().writes != myOldState.armPrevStats[3];
|
|
||||||
myPrevThumbWrites->setText(Common::Base::toString(myCart.prevStats().writes,
|
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
|
||||||
|
|
||||||
isChanged = myCart.stats().cycles != myOldState.armStats[0];
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
myThumbCycles->setText(Common::Base::toString(myCart.stats().cycles,
|
alist.push_back(0); vlist.push_back(myCart.cycles());
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
changed.push_back(myCart.cycles() != uInt32(myOldState.armRun[0]));
|
||||||
isChanged = myCart.stats().fetches != myOldState.armStats[1];
|
myThumbCycles->setList(alist, vlist, changed);
|
||||||
myThumbFetches->setText(Common::Base::toString(myCart.stats().fetches,
|
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
|
||||||
isChanged = myCart.stats().reads != myOldState.armStats[2];
|
alist.clear(); vlist.clear(); changed.clear();
|
||||||
myThumbReads->setText(Common::Base::toString(myCart.stats().reads,
|
alist.push_back(0); vlist.push_back(myCart.stats().instructions);
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
changed.push_back(myCart.stats().instructions != uInt32(myOldState.armRun[1]));
|
||||||
isChanged = myCart.stats().writes != myOldState.armStats[3];
|
myThumbInstructions->setList(alist, vlist, changed);
|
||||||
myThumbWrites->setText(Common::Base::toString(myCart.stats().writes,
|
|
||||||
Common::Base::Fmt::_10_6), isChanged);
|
|
||||||
|
|
||||||
CartDebugWidget::loadConfig();
|
CartDebugWidget::loadConfig();
|
||||||
}
|
}
|
||||||
|
@ -164,6 +188,18 @@ void CartridgeARMWidget::handleCommand(CommandSender* sender,
|
||||||
{
|
{
|
||||||
switch(cmd)
|
switch(cmd)
|
||||||
{
|
{
|
||||||
|
case kChipChanged:
|
||||||
|
handleChipType();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMamLockChanged:
|
||||||
|
handleMamLock();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMamModeChanged:
|
||||||
|
handleMamMode();
|
||||||
|
break;
|
||||||
|
|
||||||
case kIncCyclesChanged:
|
case kIncCyclesChanged:
|
||||||
case kFactorChanged:
|
case kFactorChanged:
|
||||||
handleArmCycles();
|
handleArmCycles();
|
||||||
|
@ -174,6 +210,40 @@ void CartridgeARMWidget::handleCommand(CommandSender* sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleChipType()
|
||||||
|
{
|
||||||
|
bool devSettings = instance().settings().getBool("dev.settings");
|
||||||
|
|
||||||
|
if(devSettings)
|
||||||
|
{
|
||||||
|
instance().settings().setValue("dev.thumb.chiptype", myChipType->getSelectedTag().toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
myChipType->setEnabled(devSettings);
|
||||||
|
|
||||||
|
myCart.setChipType(static_cast<Thumbulator::ChipType>(myChipType->getSelectedTag().toInt()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleMamLock()
|
||||||
|
{
|
||||||
|
bool checked = myLockMamMode->getState();
|
||||||
|
|
||||||
|
myMamMode->setEnabled(checked);
|
||||||
|
myCart.lockMamMode(checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARMWidget::handleMamMode()
|
||||||
|
{
|
||||||
|
// override MAM mode set by ROM
|
||||||
|
Int32 mode = myMamMode->getSelectedTag().toInt();
|
||||||
|
|
||||||
|
instance().settings().setValue("dev.thumb.mammode", mode);
|
||||||
|
myCart.setMamMode(static_cast<Thumbulator::MamModeType>(mode));
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeARMWidget::handleArmCycles()
|
void CartridgeARMWidget::handleArmCycles()
|
||||||
{
|
{
|
||||||
|
@ -188,8 +258,12 @@ void CartridgeARMWidget::handleArmCycles()
|
||||||
}
|
}
|
||||||
|
|
||||||
myIncCycles->setEnabled(devSettings);
|
myIncCycles->setEnabled(devSettings);
|
||||||
enable &= devSettings;
|
myCycleFactor->setEnabled(devSettings);
|
||||||
myCart.incCycles(enable);
|
myCyclesLabel->setEnabled(devSettings);
|
||||||
myCycleFactor->setEnabled(enable);
|
myThumbCycles->setEnabled(devSettings);
|
||||||
|
myPrevThumbCycles->setEnabled(devSettings);
|
||||||
|
|
||||||
|
myCart.incCycles(devSettings && enable);
|
||||||
myCart.cycleFactor(factor);
|
myCart.cycleFactor(factor);
|
||||||
|
myCart.enableCycleCount(devSettings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,8 @@
|
||||||
|
|
||||||
class CheckboxWidget;
|
class CheckboxWidget;
|
||||||
class SliderWidget;
|
class SliderWidget;
|
||||||
class EditTextWidget;
|
class PopUpWidget;
|
||||||
|
class DataGridWidget;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Abstract base class for ARM cart widgets.
|
Abstract base class for ARM cart widgets.
|
||||||
|
@ -48,30 +49,37 @@ class CartridgeARMWidget : public CartDebugWidget
|
||||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void handleChipType();
|
||||||
|
void handleMamLock();
|
||||||
|
void handleMamMode();
|
||||||
void handleArmCycles();
|
void handleArmCycles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct CartState {
|
struct CartState {
|
||||||
uIntArray armStats;
|
uInt32 mamMode{0};
|
||||||
uIntArray armPrevStats;
|
uIntArray armRun;
|
||||||
|
uIntArray armPrevRun;
|
||||||
};
|
};
|
||||||
|
|
||||||
CartridgeARM& myCart;
|
CartridgeARM& myCart;
|
||||||
|
|
||||||
CheckboxWidget* myIncCycles{nullptr};
|
CheckboxWidget* myIncCycles{nullptr};
|
||||||
SliderWidget* myCycleFactor{nullptr};
|
SliderWidget* myCycleFactor{nullptr};
|
||||||
EditTextWidget* myPrevThumbCycles{nullptr};
|
PopUpWidget* myChipType{nullptr};
|
||||||
EditTextWidget* myPrevThumbFetches{nullptr};
|
CheckboxWidget* myLockMamMode{nullptr};
|
||||||
EditTextWidget* myPrevThumbReads{nullptr};
|
PopUpWidget* myMamMode{nullptr};
|
||||||
EditTextWidget* myPrevThumbWrites{nullptr};
|
StaticTextWidget* myCyclesLabel{nullptr};
|
||||||
EditTextWidget* myThumbCycles{nullptr};
|
DataGridWidget* myPrevThumbCycles{nullptr};
|
||||||
EditTextWidget* myThumbFetches{nullptr};
|
DataGridWidget* myPrevThumbInstructions{nullptr};
|
||||||
EditTextWidget* myThumbReads{nullptr};
|
DataGridWidget* myThumbCycles{nullptr};
|
||||||
EditTextWidget* myThumbWrites{nullptr};
|
DataGridWidget* myThumbInstructions{nullptr};
|
||||||
|
|
||||||
CartState myOldState;
|
CartState myOldState;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
kChipChanged = 'chCh',
|
||||||
|
kMamLockChanged = 'mlCh',
|
||||||
|
kMamModeChanged = 'mmCh',
|
||||||
kIncCyclesChanged = 'inCH',
|
kIncCyclesChanged = 'inCH',
|
||||||
kFactorChanged = 'fcCH'
|
kFactorChanged = 'fcCH'
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,17 +23,37 @@
|
||||||
CartridgeARM::CartridgeARM(const string& md5, const Settings& settings)
|
CartridgeARM::CartridgeARM(const string& md5, const Settings& settings)
|
||||||
: Cartridge(settings, md5)
|
: Cartridge(settings, md5)
|
||||||
{
|
{
|
||||||
myIncCycles = settings.getBool("dev.settings")
|
}
|
||||||
&& settings.getBool("dev.thumb.inccycles");
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
void CartridgeARM::setInitialState()
|
||||||
|
{
|
||||||
|
bool devSettings = mySettings.getBool("dev.settings");
|
||||||
|
|
||||||
|
if(devSettings)
|
||||||
|
{
|
||||||
|
myIncCycles = mySettings.getBool("dev.thumb.inccycles");
|
||||||
|
myThumbEmulator->setChipType(static_cast<Thumbulator::ChipType>(mySettings.getInt("dev.thumb.chiptype")));
|
||||||
|
myThumbEmulator->setMamMode(static_cast<Thumbulator::MamModeType>(mySettings.getInt("dev.thumb.mammode")));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
myIncCycles = false;
|
||||||
|
}
|
||||||
|
enableCycleCount(devSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void CartridgeARM::updateCycles(int cycles)
|
void CartridgeARM::updateCycles(int cycles)
|
||||||
{
|
{
|
||||||
if(myIncCycles)
|
if(myIncCycles)
|
||||||
mySystem->incrementCycles(cycles); // * ~1.11 is the limit for ZEVIOUZ title screen (~142,000 cycles)
|
mySystem->incrementCycles(cycles);
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
myPrevStats = myStats;
|
||||||
myStats = myThumbEmulator->stats();
|
myStats = myThumbEmulator->stats();
|
||||||
myPrevStats = myThumbEmulator->prevStats();
|
myPrevCycles = myCycles;
|
||||||
|
myCycles = myThumbEmulator->cycles();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -51,43 +71,39 @@ void CartridgeARM::cycleFactor(double factor)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeARM::save(Serializer& out) const
|
bool CartridgeARM::save(Serializer& out) const
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
out.putInt(myPrevStats.cycles);
|
out.putInt(myPrevCycles);
|
||||||
out.putInt(myPrevStats.fetches);
|
out.putInt(myPrevStats.instructions);
|
||||||
out.putInt(myPrevStats.reads);
|
out.putInt(myCycles);
|
||||||
out.putInt(myPrevStats.writes);
|
out.putInt(myStats.instructions);
|
||||||
out.putInt(myStats.cycles);
|
|
||||||
out.putInt(myStats.fetches);
|
|
||||||
out.putInt(myStats.reads);
|
|
||||||
out.putInt(myStats.writes);
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
cerr << "ERROR: CartridgeARM::save" << endl;
|
cerr << "ERROR: CartridgeARM::save" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool CartridgeARM::load(Serializer& in)
|
bool CartridgeARM::load(Serializer& in)
|
||||||
{
|
{
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
myPrevStats.cycles = in.getInt();
|
myPrevCycles = in.getInt();
|
||||||
myPrevStats.fetches = in.getInt();
|
myPrevStats.instructions = in.getInt();
|
||||||
myPrevStats.reads = in.getInt();
|
myCycles = in.getInt();
|
||||||
myPrevStats.writes = in.getInt();
|
myStats.instructions = in.getInt();
|
||||||
myStats.cycles = in.getInt();
|
|
||||||
myStats.fetches = in.getInt();
|
|
||||||
myStats.reads = in.getInt();
|
|
||||||
myStats.writes = in.getInt();
|
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
cerr << "ERROR: CartridgeARM::load" << endl;
|
cerr << "ERROR: CartridgeARM::load" << endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,15 +51,26 @@ class CartridgeARM : public Cartridge
|
||||||
*/
|
*/
|
||||||
bool load(Serializer& in) override;
|
bool load(Serializer& in) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Sets the initial state of the MAM mode
|
||||||
|
*/
|
||||||
|
virtual void setInitialState();
|
||||||
|
|
||||||
|
void enableCycleCount(bool enable) const { myThumbEmulator->enableCycleCount(enable); }
|
||||||
// Get number of memory accesses of last and last but one ARM runs.
|
// Get number of memory accesses of last and last but one ARM runs.
|
||||||
void updateCycles(int cycles);
|
void updateCycles(int cycles);
|
||||||
const Thumbulator::Stats& stats() const { return myStats; }
|
const Thumbulator::Stats& stats() const { return myStats; }
|
||||||
const Thumbulator::Stats& prevStats() const { return myPrevStats; }
|
const Thumbulator::Stats& prevStats() const { return myPrevStats; }
|
||||||
|
const uInt32 cycles() const { return myCycles; }
|
||||||
|
const uInt32 prevCycles() const { return myPrevCycles; }
|
||||||
|
|
||||||
void incCycles(bool enable);
|
void incCycles(bool enable);
|
||||||
void cycleFactor(double factor);
|
void cycleFactor(double factor);
|
||||||
double cycleFactor() const { return myThumbEmulator->cycleFactor(); }
|
double cycleFactor() const { return myThumbEmulator->cycleFactor(); }
|
||||||
|
void setChipType(Thumbulator::ChipType armType) { myThumbEmulator->setChipType(armType); }
|
||||||
|
void lockMamMode(bool lock) { myThumbEmulator->lockMamMode(lock); }
|
||||||
|
void setMamMode(Thumbulator::MamModeType mamMode) { myThumbEmulator->setMamMode(mamMode); }
|
||||||
|
Thumbulator::MamModeType mamMode() const { return myThumbEmulator->mamMode(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Pointer to the Thumb ARM emulator object
|
// Pointer to the Thumb ARM emulator object
|
||||||
|
@ -67,9 +78,12 @@ class CartridgeARM : public Cartridge
|
||||||
|
|
||||||
// ARM code increases 6507 cycles
|
// ARM code increases 6507 cycles
|
||||||
bool myIncCycles{false};
|
bool myIncCycles{false};
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
Thumbulator::Stats myStats{0};
|
Thumbulator::Stats myStats{0};
|
||||||
Thumbulator::Stats myPrevStats{0};
|
Thumbulator::Stats myPrevStats{0};
|
||||||
|
uInt32 myCycles{0};
|
||||||
|
uInt32 myPrevCycles{0};
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -112,6 +112,8 @@ void CartridgeBUS::setInitialState()
|
||||||
mySTYZeroPageAddress = myJMPoperandAddress = 0;
|
mySTYZeroPageAddress = myJMPoperandAddress = 0;
|
||||||
|
|
||||||
myFastJumpActive = 0;
|
myFastJumpActive = 0;
|
||||||
|
|
||||||
|
CartridgeARM::setInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -205,7 +205,7 @@ class CartridgeBUS : public CartridgeARM
|
||||||
/**
|
/**
|
||||||
Sets the initial state of the DPC pointers and RAM
|
Sets the initial state of the DPC pointers and RAM
|
||||||
*/
|
*/
|
||||||
void setInitialState();
|
void setInitialState() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates any data fetchers in music mode based on the number of
|
Updates any data fetchers in music mode based on the number of
|
||||||
|
|
|
@ -145,6 +145,8 @@ void CartridgeCDF::setInitialState()
|
||||||
|
|
||||||
myBankOffset = myLDAimmediateOperandAddress = myJMPoperandAddress = 0;
|
myBankOffset = myLDAimmediateOperandAddress = myJMPoperandAddress = 0;
|
||||||
myFastJumpActive = myFastJumpStream = 0;
|
myFastJumpActive = myFastJumpStream = 0;
|
||||||
|
|
||||||
|
CartridgeARM::setInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -237,7 +237,7 @@ class CartridgeCDF : public CartridgeARM
|
||||||
/**
|
/**
|
||||||
Sets the initial state of the DPC pointers and RAM
|
Sets the initial state of the DPC pointers and RAM
|
||||||
*/
|
*/
|
||||||
void setInitialState();
|
void setInitialState() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates any data fetchers in music mode based on the number of
|
Updates any data fetchers in music mode based on the number of
|
||||||
|
|
|
@ -118,6 +118,8 @@ void CartridgeDPCPlus::setInitialState()
|
||||||
myFastFetch = myLDAimmediate = false;
|
myFastFetch = myLDAimmediate = false;
|
||||||
myAudioCycles = myARMCycles = 0;
|
myAudioCycles = myARMCycles = 0;
|
||||||
myFractionalClocks = 0.0;
|
myFractionalClocks = 0.0;
|
||||||
|
|
||||||
|
CartridgeARM::setInitialState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -199,7 +199,7 @@ class CartridgeDPCPlus : public CartridgeARM
|
||||||
/**
|
/**
|
||||||
Sets the initial state of the DPC pointers and RAM
|
Sets the initial state of the DPC pointers and RAM
|
||||||
*/
|
*/
|
||||||
void setInitialState();
|
void setInitialState() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clocks the random number generator to move it to its next state
|
Clocks the random number generator to move it to its next state
|
||||||
|
|
|
@ -246,8 +246,12 @@ Settings::Settings()
|
||||||
setPermanent("dev.eepromaccess", "true");
|
setPermanent("dev.eepromaccess", "true");
|
||||||
// Thumb ARM emulation options
|
// Thumb ARM emulation options
|
||||||
setPermanent("dev.thumb.trapfatal", "true");
|
setPermanent("dev.thumb.trapfatal", "true");
|
||||||
|
#ifdef DEBUGGER_SUPPORT
|
||||||
setPermanent("dev.thumb.inccycles", "true");
|
setPermanent("dev.thumb.inccycles", "true");
|
||||||
setPermanent("dev.thumb.cyclefactor", "1.05");
|
setPermanent("dev.thumb.cyclefactor", "0.95");
|
||||||
|
setPermanent("dev.thumb.chiptype", "0"); // = LPC2103
|
||||||
|
setPermanent("dev.thumb.mammode", "2");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -680,14 +684,19 @@ void Settings::usage() const
|
||||||
<< " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
|
<< " -dev.tiadriven <1|0> Drive unused TIA pins randomly on a\n"
|
||||||
<< " read/peek\n"
|
<< " read/peek\n"
|
||||||
#ifdef DEBUGGER_SUPPORT
|
#ifdef DEBUGGER_SUPPORT
|
||||||
<< " -dev.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
|
<< " -dev.rwportbreak <1|0> Debugger breaks on reads from write ports\n"
|
||||||
<< " -dev.wrportbreak <1|0> Debugger breaks on writes to read ports\n"
|
<< " -dev.wrportbreak <1|0> Debugger breaks on writes to read ports\n"
|
||||||
#endif
|
#endif
|
||||||
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
|
<< " -dev.thumb.trapfatal <1|0> Determines whether errors in ARM emulation\n"
|
||||||
<< " throw an exception\n"
|
<< " throw an exception\n"
|
||||||
<< " -dev.thumb.inccycles <1|0> Determines whether ARM emulation cycles\n"
|
#ifdef DEBUGGER_SUPPORT
|
||||||
|
<< " -dev.thumb.inccycles <1|0> Determines whether ARM emulation cycles\n"
|
||||||
<< " increase system cycles\n"
|
<< " increase system cycles\n"
|
||||||
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
|
<< " -dev.thumb.cyclefactor <float> Sets the ARM cycles correction multiplier\n"
|
||||||
|
<< " -dev.thumb.chiptype <0|1> Selects the ARM chip type\n"
|
||||||
|
<< " -dev.thumb.mammode <0-3> Selects the LPC's MAM mode\n"
|
||||||
|
#endif
|
||||||
|
<< " -dev.eepromaccess <1|0> Enable messages for AtariVox/SaveKey access\n"
|
||||||
<< " messages\n"
|
<< " messages\n"
|
||||||
<< " -dev.tia.type <standard|custom| Selects a TIA type\n"
|
<< " -dev.tia.type <standard|custom| Selects a TIA type\n"
|
||||||
<< " koolaidman|\n"
|
<< " koolaidman|\n"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -32,7 +32,6 @@ class Cartridge;
|
||||||
|
|
||||||
#ifdef RETRON77
|
#ifdef RETRON77
|
||||||
#define UNSAFE_OPTIMIZATIONS
|
#define UNSAFE_OPTIMIZATIONS
|
||||||
#define NO_THUMB_STATS
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ROMADDMASK 0x7FFFF
|
#define ROMADDMASK 0x7FFFF
|
||||||
|
@ -46,8 +45,16 @@ class Cartridge;
|
||||||
#define CPSR_C (1u<<29)
|
#define CPSR_C (1u<<29)
|
||||||
#define CPSR_V (1u<<28)
|
#define CPSR_V (1u<<28)
|
||||||
|
|
||||||
#define TIMER_0 // enable timer 0 support
|
#ifdef DEBUGGER_SUPPORT
|
||||||
//#define COUNT_OPS
|
#define THUMB_CYCLE_COUNT
|
||||||
|
//#define COUNT_OPS
|
||||||
|
//#define THUMB_STATS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
//#define EMULATE_PIPELINE // enable coarse ARM pipeline emulation
|
||||||
|
#define TIMER_0 // enable timer 0 support (e.g. for measuring cycle count)
|
||||||
|
#endif
|
||||||
|
|
||||||
class Thumbulator
|
class Thumbulator
|
||||||
{
|
{
|
||||||
|
@ -62,11 +69,24 @@ class Thumbulator
|
||||||
CDFJplus, // cartridges of type CDFJ+
|
CDFJplus, // cartridges of type CDFJ+
|
||||||
DPCplus // cartridges of type DPC+
|
DPCplus // cartridges of type DPC+
|
||||||
};
|
};
|
||||||
|
enum class ChipType {
|
||||||
|
LPC2103, // Harmony
|
||||||
|
LPC2104, // Encore (includes LPC2105)
|
||||||
|
LPC2132, // future use
|
||||||
|
numTypes
|
||||||
|
};
|
||||||
|
enum class MamModeType {
|
||||||
|
mode0, mode1, mode2, modeX
|
||||||
|
};
|
||||||
|
struct ChipPropsType {
|
||||||
|
double MHz;
|
||||||
|
uInt32 flashCycles;
|
||||||
|
uInt32 flashBanks;
|
||||||
|
};
|
||||||
struct Stats {
|
struct Stats {
|
||||||
#ifndef NO_THUMB_STATS
|
uInt32 instructions{0};
|
||||||
uInt32 fetches{0}, reads{0}, writes{0};
|
#ifdef THUMB_STATS
|
||||||
uInt32 cycles{0};
|
uInt32 reads{0}, writes{0};
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,10 +106,23 @@ class Thumbulator
|
||||||
*/
|
*/
|
||||||
string doRun(uInt32& cycles);
|
string doRun(uInt32& cycles);
|
||||||
string run(uInt32& cycles);
|
string run(uInt32& cycles);
|
||||||
|
void enableCycleCount(bool enable) { _countCycles = enable; }
|
||||||
const Stats& stats() const { return _stats; }
|
const Stats& stats() const { return _stats; }
|
||||||
const Stats& prevStats() const { return _prevStats; }
|
const uInt32 cycles() const { return _totalCycles; }
|
||||||
|
void setChipType(ChipType type);
|
||||||
|
void setMamMode(MamModeType mode) { mamcr = mode; }
|
||||||
|
void lockMamMode(bool lock) { _lockMamcr = lock; }
|
||||||
|
MamModeType mamMode() const { return static_cast<MamModeType>(mamcr); }
|
||||||
|
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
void cycleFactor(double factor) { _armCyclesFactor = factor; }
|
||||||
|
double cycleFactor() const { return _armCyclesFactor; }
|
||||||
|
#else
|
||||||
|
void cycleFactor(double) { }
|
||||||
|
double cycleFactor() const { return 1.0; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
/**
|
/**
|
||||||
Normally when a fatal error is encountered, the ARM emulation
|
Normally when a fatal error is encountered, the ARM emulation
|
||||||
immediately throws an exception and exits. This method allows execution
|
immediately throws an exception and exits. This method allows execution
|
||||||
|
@ -102,15 +135,8 @@ class Thumbulator
|
||||||
|
|
||||||
@param enable Enable (the default) or disable exceptions on fatal errors
|
@param enable Enable (the default) or disable exceptions on fatal errors
|
||||||
*/
|
*/
|
||||||
static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
void trapFatalErrors(bool enable) { trapOnFatal = enable; }
|
||||||
#endif
|
#endif
|
||||||
#ifndef NO_THUMB_STATS
|
|
||||||
static void cycleFactor(double factor) { arm_cycle_factor = factor; }
|
|
||||||
double cycleFactor() const { return arm_cycle_factor; }
|
|
||||||
#else
|
|
||||||
static void cycleFactor(double) { }
|
|
||||||
double cycleFactor() const { return 1.0; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Inform the Thumbulator class about the console currently in use,
|
Inform the Thumbulator class about the console currently in use,
|
||||||
|
@ -171,16 +197,24 @@ class Thumbulator
|
||||||
uxth,
|
uxth,
|
||||||
numOps
|
numOps
|
||||||
};
|
};
|
||||||
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
enum class CycleType {
|
||||||
|
S, N, I // Sequential, Non-sequential, Internal
|
||||||
|
};
|
||||||
|
enum class AccessType {
|
||||||
|
prefetch, branch, data
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uInt32 read_register(uInt32 reg);
|
uInt32 read_register(uInt32 reg);
|
||||||
void write_register(uInt32 reg, uInt32 data);
|
void write_register(uInt32 reg, uInt32 data, bool isFlowBreak = true);
|
||||||
uInt32 fetch16(uInt32 addr);
|
uInt32 fetch16(uInt32 addr);
|
||||||
uInt32 read16(uInt32 addr);
|
uInt32 read16(uInt32 addr);
|
||||||
uInt32 read32(uInt32 addr);
|
uInt32 read32(uInt32 addr);
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
bool isProtected(uInt32 addr);
|
bool isProtected(uInt32 addr);
|
||||||
#endif
|
#endif
|
||||||
void write16(uInt32 addr, uInt32 data);
|
void write16(uInt32 addr, uInt32 data);
|
||||||
void write32(uInt32 addr, uInt32 data);
|
void write32(uInt32 addr, uInt32 data);
|
||||||
void updateTimer(uInt32 cycles);
|
void updateTimer(uInt32 cycles);
|
||||||
|
@ -194,7 +228,7 @@ class Thumbulator
|
||||||
void do_cflag_bit(uInt32 x);
|
void do_cflag_bit(uInt32 x);
|
||||||
void do_vflag_bit(uInt32 x);
|
void do_vflag_bit(uInt32 x);
|
||||||
|
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
// Throw a runtime_error exception containing an error referencing the
|
// Throw a runtime_error exception containing an error referencing the
|
||||||
// given message and variables
|
// given message and variables
|
||||||
// Note that the return value is never used in these methods
|
// Note that the return value is never used in these methods
|
||||||
|
@ -203,10 +237,18 @@ class Thumbulator
|
||||||
|
|
||||||
void dump_counters();
|
void dump_counters();
|
||||||
void dump_regs();
|
void dump_regs();
|
||||||
#endif
|
#endif
|
||||||
int execute();
|
int execute();
|
||||||
int reset();
|
int reset();
|
||||||
|
|
||||||
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
|
bool isMamBuffered(uInt32 addr, AccessType = AccessType::data);
|
||||||
|
void incCycles(AccessType accessType, uInt32 cycles);
|
||||||
|
void incSCycles(uInt32 addr, AccessType = AccessType::data);
|
||||||
|
void incNCycles(uInt32 addr, AccessType = AccessType::data);
|
||||||
|
void incICycles(uInt32 m = 1);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const uInt16* rom{nullptr};
|
const uInt16* rom{nullptr};
|
||||||
uInt32 romSize{0};
|
uInt32 romSize{0};
|
||||||
|
@ -216,16 +258,17 @@ class Thumbulator
|
||||||
const unique_ptr<Op[]> decodedRom; // NOLINT
|
const unique_ptr<Op[]> decodedRom; // NOLINT
|
||||||
uInt16* ram{nullptr};
|
uInt16* ram{nullptr};
|
||||||
std::array<uInt32, 16> reg_norm; // normal execution mode, do not have a thread mode
|
std::array<uInt32, 16> reg_norm; // normal execution mode, do not have a thread mode
|
||||||
uInt32 cpsr{0}, mamcr{0};
|
uInt32 cpsr{0};
|
||||||
|
MamModeType mamcr{MamModeType::mode0};
|
||||||
bool handler_mode{false};
|
bool handler_mode{false};
|
||||||
uInt32 systick_ctrl{0}, systick_reload{0}, systick_count{0}, systick_calibrate{0};
|
uInt32 systick_ctrl{0}, systick_reload{0}, systick_count{0}, systick_calibrate{0};
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
ChipType _chipType{ChipType::LPC2103};
|
||||||
uInt32 instructions{0};
|
ConsoleTiming _consoleTiming{ConsoleTiming::ntsc};
|
||||||
#endif
|
double _MHz{70.0};
|
||||||
#ifndef NO_THUMB_STATS
|
uInt32 _flashCycles{4};
|
||||||
Stats _stats;
|
uInt32 _flashBanks{1};
|
||||||
Stats _prevStats;
|
Stats _stats{0};
|
||||||
#endif
|
uInt32 _totalCycles{0};
|
||||||
|
|
||||||
// For emulation of LPC2103's timer 1, used for NTSC/PAL/SECAM detection.
|
// For emulation of LPC2103's timer 1, used for NTSC/PAL/SECAM detection.
|
||||||
// Register names from documentation:
|
// Register names from documentation:
|
||||||
|
@ -240,17 +283,34 @@ class Thumbulator
|
||||||
uInt32 tim1Cycles{0};
|
uInt32 tim1Cycles{0};
|
||||||
double timing_factor{0.0};
|
double timing_factor{0.0};
|
||||||
|
|
||||||
#ifndef UNSAFE_OPTIMIZATIONS
|
#ifndef UNSAFE_OPTIMIZATIONS
|
||||||
ostringstream statusMsg;
|
ostringstream statusMsg;
|
||||||
|
bool trapOnFatal{true};
|
||||||
|
#endif
|
||||||
|
const std::array<ChipPropsType, uInt32(ChipType::numTypes)> ChipProps =
|
||||||
|
{{
|
||||||
|
{ 70.0, 4, 1 }, // LPC2101_02_03
|
||||||
|
{ 60.0, 3, 2 }, // LPC2104_05_06
|
||||||
|
{ 60.0, 3, 1 }, // LPC2132..
|
||||||
|
}};
|
||||||
|
|
||||||
static bool trapOnFatal;
|
bool _countCycles{false};
|
||||||
#endif
|
bool _lockMamcr{false};
|
||||||
#ifndef NO_THUMB_STATS
|
|
||||||
static double arm_cycle_factor;
|
#ifdef THUMB_CYCLE_COUNT
|
||||||
#endif
|
double _armCyclesFactor{0.90};
|
||||||
#ifdef COUNT_OPS
|
CycleType _fetchCycleType{CycleType::S};
|
||||||
|
#ifdef EMULATE_PIPELINE
|
||||||
|
uInt32 _fetchPipeline{0}; // reserve fetch cycles resulting from pipelining (execution stage)
|
||||||
|
uInt32 _memory0Pipeline{0}, _memory1Pipeline{0};
|
||||||
|
#endif
|
||||||
|
uInt32 _prefetchBufferAddr[2]{0};
|
||||||
|
uInt32 _branchBufferAddr[2]{0};
|
||||||
|
uInt32 _dataBufferAddr{0};
|
||||||
|
#endif
|
||||||
|
#ifdef COUNT_OPS
|
||||||
uInt32 opCount[size_t(Op::numOps)]{0};
|
uInt32 opCount[size_t(Op::numOps)]{0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ConfigureFor configuration;
|
ConfigureFor configuration;
|
||||||
|
|
||||||
|
|
|
@ -740,8 +740,7 @@ void VideoAudioDialog::saveConfig()
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
// TV Effects tab
|
// TV Effects tab
|
||||||
// TV Mode
|
// TV Mode
|
||||||
settings.setValue("tv.filter",
|
settings.setValue("tv.filter", myTVMode->getSelectedTag().toString());
|
||||||
myTVMode->getSelectedTag().toString());
|
|
||||||
// TV Custom adjustables
|
// TV Custom adjustables
|
||||||
NTSCFilter::Adjustable ntscAdj;
|
NTSCFilter::Adjustable ntscAdj;
|
||||||
ntscAdj.sharpness = myTVSharp->getValue();
|
ntscAdj.sharpness = myTVSharp->getValue();
|
||||||
|
|
Loading…
Reference in New Issue