Some updates to the last BUS/CDF commit:

- update some code to the '5.0' way of doing things
  - allow compilation in Linux
  - whitespace/tab fixes to match main codebase
  - add some extra comments
  - test compile under gcc 6 and clang 5, and fix some warnings
This commit is contained in:
Stephen Anthony 2017-03-24 18:02:08 -02:30
parent 7c6821dfcb
commit 95c7b30a45
16 changed files with 693 additions and 719 deletions

View File

@ -1,20 +1,18 @@
//============================================================================ //============================================================================
// //
// SSSS tt lll lll // SSSS tt lll lll
// SS SS tt ll ll // SS SS tt ll ll
// SS tttttt eeee ll ll aaaa // SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa // SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartBUSWidget.cxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#include "CartBUS.hxx" #include "CartBUS.hxx"
@ -76,7 +74,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Datastream Pointers: ", kTextAlignLeft); myFontHeight, "Datastream Pointers: ", kTextAlignLeft);
xpos += lwidth; xpos += lwidth;
myDatastreamPointers = new DataGridWidget(boss, _nfont, 0, ypos+myLineHeight-2, 4, 4, 6, 32, Common::Base::F_16_3_2); myDatastreamPointers = new DataGridWidget(boss, _nfont, 0, ypos+myLineHeight-2, 4, 4, 6, 32, Common::Base::F_16_3_2);
myDatastreamPointers->setTarget(this); myDatastreamPointers->setTarget(this);
myDatastreamPointers->setEditable(false); myDatastreamPointers->setEditable(false);
@ -85,20 +83,20 @@ CartridgeBUSWidget::CartridgeBUSWidget(
xpos = 0 + myDatastreamPointers->getWidth(); xpos = 0 + myDatastreamPointers->getWidth();
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Datastream Increments: ", kTextAlignLeft); myFontHeight, "Datastream Increments: ", kTextAlignLeft);
myDatastreamIncrements = new DataGridWidget(boss, _nfont, xpos, ypos+myLineHeight-2, 4, 4, 5, 32, Common::Base::F_16_2_2); myDatastreamIncrements = new DataGridWidget(boss, _nfont, xpos, ypos+myLineHeight-2, 4, 4, 5, 32, Common::Base::F_16_2_2);
myDatastreamIncrements->setTarget(this); myDatastreamIncrements->setTarget(this);
myDatastreamIncrements->setEditable(false); myDatastreamIncrements->setEditable(false);
// Datastream Maps // Datastream Maps
xpos = 0; ypos += myLineHeight*5 + 4; xpos = 0; ypos += myLineHeight*5 + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Address Maps: ", kTextAlignLeft); myFontHeight, "Address Maps: ", kTextAlignLeft);
myAddressMaps = new DataGridWidget(boss, _nfont, 0, ypos+myLineHeight-2, 8, 5, 8, 32, Common::Base::F_16_8); myAddressMaps = new DataGridWidget(boss, _nfont, 0, ypos+myLineHeight-2, 8, 5, 8, 32, Common::Base::F_16_8);
myAddressMaps->setTarget(this); myAddressMaps->setTarget(this);
myAddressMaps->setEditable(false); myAddressMaps->setEditable(false);
// Music counters // Music counters
xpos = 10; ypos += myLineHeight*6 + 4; xpos = 10; ypos += myLineHeight*6 + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
@ -138,8 +136,8 @@ CartridgeBUSWidget::CartridgeBUSWidget(
myMusicWaveformSizes = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2); myMusicWaveformSizes = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2);
myMusicWaveformSizes->setTarget(this); myMusicWaveformSizes->setTarget(this);
myMusicWaveformSizes->setEditable(false); myMusicWaveformSizes->setEditable(false);
// BUS stuff and ZP STY flags // BUS stuff and ZP STY flags
xpos = 10; ypos += myLineHeight + 4; xpos = 10; ypos += myLineHeight + 4;
myBusOverdrive = new CheckboxWidget(boss, _font, xpos, ypos, "BUS Overdrive enabled"); myBusOverdrive = new CheckboxWidget(boss, _font, xpos, ypos, "BUS Overdrive enabled");
@ -149,7 +147,6 @@ CartridgeBUSWidget::CartridgeBUSWidget(
myZPSTY = new CheckboxWidget(boss, _font, xpos, ypos, "Zero Page STY"); myZPSTY = new CheckboxWidget(boss, _font, xpos, ypos, "Zero Page STY");
myZPSTY->setTarget(this); myZPSTY->setTarget(this);
myZPSTY->setEditable(false); myZPSTY->setEditable(false);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -177,7 +174,7 @@ void CartridgeBUSWidget::saveOldState()
// P = Pointer // P = Pointer
// I = Increment // I = Increment
// F = Fractional // F = Fractional
myOldState.datastreampointers.push_back(myCart.getDatastreamPointer(i)>>12); myOldState.datastreampointers.push_back(myCart.getDatastreamPointer(i)>>12);
myOldState.datastreamincrements.push_back(myCart.getDatastreamIncrement(i)); myOldState.datastreamincrements.push_back(myCart.getDatastreamIncrement(i));
} }
@ -186,7 +183,7 @@ void CartridgeBUSWidget::saveOldState()
{ {
myOldState.addressmaps.push_back(myCart.getAddressMap(i)); myOldState.addressmaps.push_back(myCart.getAddressMap(i));
} }
for(uInt32 i = 0; i < 3; ++i) for(uInt32 i = 0; i < 3; ++i)
{ {
myOldState.mcounters.push_back(myCart.myMusicCounters[i]); myOldState.mcounters.push_back(myCart.myMusicCounters[i]);
@ -198,7 +195,7 @@ void CartridgeBUSWidget::saveOldState()
myOldState.mwaves.push_back(myCart.getWaveform(i) >> 5); myOldState.mwaves.push_back(myCart.getWaveform(i) >> 5);
myOldState.mwavesizes.push_back(myCart.getWaveformSize((i))); myOldState.mwavesizes.push_back(myCart.getWaveformSize((i)));
} }
for(uInt32 i = 0; i < internalRamSize(); ++i) for(uInt32 i = 0; i < internalRamSize(); ++i)
myOldState.internalram.push_back(myCart.myBUSRAM[i]); myOldState.internalram.push_back(myCart.myBUSRAM[i]);
} }
@ -225,8 +222,8 @@ void CartridgeBUSWidget::loadConfig()
// P = Pointer // P = Pointer
// I = Increment // I = Increment
// F = Fractional // F = Fractional
uInt32 pointervalue = myCart.getDatastreamPointer(i) >> 12; Int32 pointervalue = myCart.getDatastreamPointer(i) >> 12;
alist.push_back(0); vlist.push_back(pointervalue); alist.push_back(0); vlist.push_back(pointervalue);
changed.push_back(pointervalue != myOldState.datastreampointers[i]); changed.push_back(pointervalue != myOldState.datastreampointers[i]);
} }
@ -235,21 +232,21 @@ void CartridgeBUSWidget::loadConfig()
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 16; ++i) for(int i = 0; i < 16; ++i)
{ {
uInt32 incrementvalue = myCart.getDatastreamIncrement(i); Int32 incrementvalue = myCart.getDatastreamIncrement(i);
alist.push_back(0); vlist.push_back(incrementvalue); alist.push_back(0); vlist.push_back(incrementvalue);
changed.push_back(incrementvalue != myOldState.datastreamincrements[i]); changed.push_back(incrementvalue != myOldState.datastreamincrements[i]);
} }
myDatastreamIncrements->setList(alist, vlist, changed); myDatastreamIncrements->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 40; ++i) for(int i = 0; i < 40; ++i)
{ {
uInt32 mapvalue = myCart.getAddressMap(i); Int32 mapvalue = myCart.getAddressMap(i);
alist.push_back(0); vlist.push_back(mapvalue); alist.push_back(0); vlist.push_back(mapvalue);
changed.push_back(mapvalue != myOldState.addressmaps[i]); changed.push_back(mapvalue != myOldState.addressmaps[i]);
} }
myAddressMaps->setList(alist, vlist, changed); myAddressMaps->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
@ -270,7 +267,7 @@ void CartridgeBUSWidget::loadConfig()
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
alist.push_back(0); vlist.push_back(myCart.getWaveform(i) >> 5); alist.push_back(0); vlist.push_back(myCart.getWaveform(i) >> 5);
changed.push_back((myCart.getWaveform(i) >> 5) != myOldState.mwaves[i]); changed.push_back((myCart.getWaveform(i) >> 5) != uInt32(myOldState.mwaves[i]));
} }
myMusicWaveforms->setList(alist, vlist, changed); myMusicWaveforms->setList(alist, vlist, changed);
@ -278,10 +275,10 @@ void CartridgeBUSWidget::loadConfig()
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
alist.push_back(0); vlist.push_back(myCart.getWaveformSize(i)); alist.push_back(0); vlist.push_back(myCart.getWaveformSize(i));
changed.push_back((myCart.getWaveformSize(i)) != myOldState.mwavesizes[i]); changed.push_back((myCart.getWaveformSize(i)) != uInt32(myOldState.mwavesizes[i]));
} }
myMusicWaveformSizes->setList(alist, vlist, changed); myMusicWaveformSizes->setList(alist, vlist, changed);
myBusOverdrive->setState(myCart.getBusStuffFlag()); myBusOverdrive->setState(myCart.getBusStuffFlag());
myZPSTY->setState(myCart.mySTYZeroPage); myZPSTY->setState(myCart.mySTYZeroPage);
@ -290,7 +287,7 @@ void CartridgeBUSWidget::loadConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBUSWidget::handleCommand(CommandSender* sender, void CartridgeBUSWidget::handleCommand(CommandSender* sender,
int cmd, int data, int id) int cmd, int data, int id)
{ {
if(cmd == kBankChanged) if(cmd == kBankChanged)
{ {
@ -316,7 +313,7 @@ string CartridgeBUSWidget::bankState()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUSWidget::internalRamSize() uInt32 CartridgeBUSWidget::internalRamSize()
{ {
return 8*1024; return 8*1024;
} }
@ -328,7 +325,7 @@ uInt32 CartridgeBUSWidget::internalRamRPort(int start)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartridgeBUSWidget::internalRamDescription() string CartridgeBUSWidget::internalRamDescription()
{ {
ostringstream desc; ostringstream desc;
desc << "$0000 - $07FF - BUS driver\n" desc << "$0000 - $07FF - BUS driver\n"
@ -338,7 +335,7 @@ string CartridgeBUSWidget::internalRamDescription()
<< " via BUS's Data Stream registers\n" << " via BUS's Data Stream registers\n"
<< "$1800 - $1FFF - 2K C variable storage and stack\n" << "$1800 - $1FFF - 2K C variable storage and stack\n"
<< " not accessible to 6507"; << " not accessible to 6507";
return desc.str(); return desc.str();
} }

View File

@ -1,20 +1,18 @@
//============================================================================ //============================================================================
// //
// SSSS tt lll lll // SSSS tt lll lll
// SS SS tt ll ll // SS SS tt ll ll
// SS tttttt eeee ll ll aaaa // SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa // SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartBUSWidget.hxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#ifndef CARTRIDGEBUS_WIDGET_HXX #ifndef CARTRIDGEBUS_WIDGET_HXX
@ -31,10 +29,10 @@ class CartridgeBUSWidget : public CartDebugWidget
{ {
public: public:
CartridgeBUSWidget(GuiObject* boss, const GUI::Font& lfont, CartridgeBUSWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, const GUI::Font& nfont,
int x, int y, int w, int h, int x, int y, int w, int h,
CartridgeBUS& cart); CartridgeBUS& cart);
virtual ~CartridgeBUSWidget() { } virtual ~CartridgeBUSWidget() = default;
private: private:
struct CartState { struct CartState {
@ -67,14 +65,14 @@ class CartridgeBUSWidget : public CartDebugWidget
enum { kBankChanged = 'bkCH' }; enum { kBankChanged = 'bkCH' };
private: private:
void saveOldState() override; void saveOldState() override;
void loadConfig() override; void loadConfig() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
string bankState() override; string bankState() override;
// start of functions for Cartridge RAM tab // start of functions for Cartridge RAM tab
uInt32 internalRamSize() override; uInt32 internalRamSize() override;
uInt32 internalRamRPort(int start) override; uInt32 internalRamRPort(int start) override;
@ -84,7 +82,7 @@ private:
void internalRamSetValue(int addr, uInt8 value) override; void internalRamSetValue(int addr, uInt8 value) override;
uInt8 internalRamGetValue(int addr) override; uInt8 internalRamGetValue(int addr) override;
// end of functions for Cartridge RAM tab // end of functions for Cartridge RAM tab
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
CartridgeBUSWidget() = delete; CartridgeBUSWidget() = delete;
CartridgeBUSWidget(const CartridgeBUSWidget&) = delete; CartridgeBUSWidget(const CartridgeBUSWidget&) = delete;

96
src/debugger/gui/CartCDFWidget.cxx Executable file → Normal file
View File

@ -8,13 +8,11 @@
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartCDFWidget.cxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#include "CartCDF.hxx" #include "CartCDF.hxx"
@ -24,13 +22,13 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCDFWidget::CartridgeCDFWidget( CartridgeCDFWidget::CartridgeCDFWidget(
GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont, GuiObject* boss, const GUI::Font& lfont, const GUI::Font& nfont,
int x, int y, int w, int h, CartridgeCDF& cart) int x, int y, int w, int h, CartridgeCDF& cart)
: CartDebugWidget(boss, lfont, nfont, x, y, w, h), : CartDebugWidget(boss, lfont, nfont, x, y, w, h),
myCart(cart) myCart(cart)
{ {
uInt16 size = 8 * 4096; uInt16 size = 8 * 4096;
ostringstream info; ostringstream info;
info << "CDF Stuffing cartridge\n" info << "CDF Stuffing cartridge\n"
<< "32K ROM, seven 4K banks are accessible to 2600\n" << "32K ROM, seven 4K banks are accessible to 2600\n"
@ -38,7 +36,7 @@ myCart(cart)
<< "CDF registers accessible @ $F000 - $F03F\n" << "CDF registers accessible @ $F000 - $F03F\n"
<< "Banks accessible at hotspots $FF5 to $FFB\n" << "Banks accessible at hotspots $FF5 to $FFB\n"
<< "Startup bank = " << cart.myStartBank << "\n"; << "Startup bank = " << cart.myStartBank << "\n";
#if 0 #if 0
// Eventually, we should query this from the debugger/disassembler // Eventually, we should query this from the debugger/disassembler
for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF5; i < 7; ++i, offset += 0x1000) for(uInt32 i = 0, offset = 0xFFC, spot = 0xFF5; i < 7; ++i, offset += 0x1000)
@ -49,11 +47,11 @@ myCart(cart)
<< "$" << (start + 0xFFF) << " (hotspot = $" << (spot+i) << ")\n"; << "$" << (start + 0xFFF) << " (hotspot = $" << (spot+i) << ")\n";
} }
#endif #endif
int xpos = 10, int xpos = 10,
ypos = addBaseInformation(size, "AtariAge", info.str()) + ypos = addBaseInformation(size, "AtariAge", info.str()) +
myLineHeight; myLineHeight;
VariantList items; VariantList items;
VarList::push_back(items, "0 ($FF5)"); VarList::push_back(items, "0 ($FF5)");
VarList::push_back(items, "1 ($FF6)"); VarList::push_back(items, "1 ($FF6)");
@ -68,68 +66,68 @@ myCart(cart)
_font.getStringWidth("Set bank: "), kBankChanged); _font.getStringWidth("Set bank: "), kBankChanged);
myBank->setTarget(this); myBank->setTarget(this);
addFocusWidget(myBank); addFocusWidget(myBank);
int lwidth = _font.getStringWidth("Datastream Increments: "); // get width of the widest label int lwidth = _font.getStringWidth("Datastream Increments: "); // get width of the widest label
// Datastream Pointers // Datastream Pointers
xpos = 0; ypos += myLineHeight + 4; xpos = 0; ypos += myLineHeight + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Datastream Pointers: ", kTextAlignLeft); myFontHeight, "Datastream Pointers: ", kTextAlignLeft);
xpos += lwidth; xpos += lwidth;
myDatastreamPointers = new DataGridWidget(boss, _nfont, 0, ypos+myLineHeight-2, 4, 8, 6, 32, Common::Base::F_16_3_2); myDatastreamPointers = new DataGridWidget(boss, _nfont, 0, ypos+myLineHeight-2, 4, 8, 6, 32, Common::Base::F_16_3_2);
myDatastreamPointers->setTarget(this); myDatastreamPointers->setTarget(this);
myDatastreamPointers->setEditable(false); myDatastreamPointers->setEditable(false);
// Datastream Increments // Datastream Increments
xpos = 0 + myDatastreamPointers->getWidth(); xpos = 0 + myDatastreamPointers->getWidth();
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Datastream Increments: ", kTextAlignLeft); myFontHeight, "Datastream Increments: ", kTextAlignLeft);
myDatastreamIncrements = new DataGridWidget(boss, _nfont, xpos, ypos+myLineHeight-2, 4, 8, 5, 32, Common::Base::F_16_2_2); myDatastreamIncrements = new DataGridWidget(boss, _nfont, xpos, ypos+myLineHeight-2, 4, 8, 5, 32, Common::Base::F_16_2_2);
myDatastreamIncrements->setTarget(this); myDatastreamIncrements->setTarget(this);
myDatastreamIncrements->setEditable(false); myDatastreamIncrements->setEditable(false);
// Music counters // Music counters
xpos = 10; ypos += myLineHeight*10 + 4; xpos = 10; ypos += myLineHeight*10 + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Music Counters: ", kTextAlignLeft); myFontHeight, "Music Counters: ", kTextAlignLeft);
xpos += lwidth; xpos += lwidth;
myMusicCounters = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 8, 32, Common::Base::F_16_8); myMusicCounters = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 8, 32, Common::Base::F_16_8);
myMusicCounters->setTarget(this); myMusicCounters->setTarget(this);
myMusicCounters->setEditable(false); myMusicCounters->setEditable(false);
// Music frequencies // Music frequencies
xpos = 10; ypos += myLineHeight + 4; xpos = 10; ypos += myLineHeight + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Music Frequencies: ", kTextAlignLeft); myFontHeight, "Music Frequencies: ", kTextAlignLeft);
xpos += lwidth; xpos += lwidth;
myMusicFrequencies = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 8, 32, Common::Base::F_16_8); myMusicFrequencies = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 8, 32, Common::Base::F_16_8);
myMusicFrequencies->setTarget(this); myMusicFrequencies->setTarget(this);
myMusicFrequencies->setEditable(false); myMusicFrequencies->setEditable(false);
// Music waveforms // Music waveforms
xpos = 10; ypos += myLineHeight + 4; xpos = 10; ypos += myLineHeight + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Music Waveforms: ", kTextAlignLeft); myFontHeight, "Music Waveforms: ", kTextAlignLeft);
xpos += lwidth; xpos += lwidth;
myMusicWaveforms = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2); myMusicWaveforms = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2);
myMusicWaveforms->setTarget(this); myMusicWaveforms->setTarget(this);
myMusicWaveforms->setEditable(false); myMusicWaveforms->setEditable(false);
// Music waveform sizes // Music waveform sizes
xpos = 10; ypos += myLineHeight + 4; xpos = 10; ypos += myLineHeight + 4;
new StaticTextWidget(boss, _font, xpos, ypos, lwidth, new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
myFontHeight, "Music Waveform Sizes: ", kTextAlignLeft); myFontHeight, "Music Waveform Sizes: ", kTextAlignLeft);
xpos += lwidth; xpos += lwidth;
myMusicWaveformSizes = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2); myMusicWaveformSizes = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2);
myMusicWaveformSizes->setTarget(this); myMusicWaveformSizes->setTarget(this);
myMusicWaveformSizes->setEditable(false); myMusicWaveformSizes->setEditable(false);
// done differently than in DPC+, need to rethink debugger support // done differently than in DPC+, need to rethink debugger support
// // Fast fetch and immediate mode LDA flags // // Fast fetch and immediate mode LDA flags
// xpos = 10; ypos += myLineHeight + 4; // xpos = 10; ypos += myLineHeight + 4;
@ -155,7 +153,7 @@ void CartridgeCDFWidget::saveOldState()
myOldState.mwaves.clear(); myOldState.mwaves.clear();
myOldState.mwavesizes.clear(); myOldState.mwavesizes.clear();
myOldState.internalram.clear(); myOldState.internalram.clear();
for(uInt32 i = 0; i < 32; i++) for(uInt32 i = 0; i < 32; i++)
{ {
// Pointers are stored as: // Pointers are stored as:
@ -167,23 +165,23 @@ void CartridgeCDFWidget::saveOldState()
// P = Pointer // P = Pointer
// I = Increment // I = Increment
// F = Fractional // F = Fractional
myOldState.datastreampointers.push_back(myCart.getDatastreamPointer(i)>>12); myOldState.datastreampointers.push_back(myCart.getDatastreamPointer(i)>>12);
myOldState.datastreamincrements.push_back(myCart.getDatastreamIncrement(i)); myOldState.datastreamincrements.push_back(myCart.getDatastreamIncrement(i));
} }
for(uInt32 i = 0; i < 3; ++i) for(uInt32 i = 0; i < 3; ++i)
{ {
myOldState.mcounters.push_back(myCart.myMusicCounters[i]); myOldState.mcounters.push_back(myCart.myMusicCounters[i]);
} }
for(uInt32 i = 0; i < 3; ++i) for(uInt32 i = 0; i < 3; ++i)
{ {
myOldState.mfreqs.push_back(myCart.myMusicFrequencies[i]); myOldState.mfreqs.push_back(myCart.myMusicFrequencies[i]);
myOldState.mwaves.push_back(myCart.getWaveform(i) >> 5); myOldState.mwaves.push_back(myCart.getWaveform(i) >> 5);
myOldState.mwavesizes.push_back(myCart.getWaveformSize((i))); myOldState.mwavesizes.push_back(myCart.getWaveformSize((i)));
} }
for(uInt32 i = 0; i < internalRamSize(); ++i) for(uInt32 i = 0; i < internalRamSize(); ++i)
myOldState.internalram.push_back(myCart.myCDFRAM[i]); myOldState.internalram.push_back(myCart.myCDFRAM[i]);
} }
@ -192,12 +190,12 @@ void CartridgeCDFWidget::saveOldState()
void CartridgeCDFWidget::loadConfig() void CartridgeCDFWidget::loadConfig()
{ {
myBank->setSelectedIndex(myCart.myCurrentBank); myBank->setSelectedIndex(myCart.myCurrentBank);
// Get registers, using change tracking // Get registers, using change tracking
IntArray alist; IntArray alist;
IntArray vlist; IntArray vlist;
BoolArray changed; BoolArray changed;
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 32; ++i) for(int i = 0; i < 32; ++i)
{ {
@ -210,58 +208,58 @@ void CartridgeCDFWidget::loadConfig()
// P = Pointer // P = Pointer
// I = Increment // I = Increment
// F = Fractional // F = Fractional
uInt32 pointervalue = myCart.getDatastreamPointer(i) >> 12; Int32 pointervalue = myCart.getDatastreamPointer(i) >> 12;
alist.push_back(0); vlist.push_back(pointervalue); alist.push_back(0); vlist.push_back(pointervalue);
changed.push_back(pointervalue != myOldState.datastreampointers[i]); changed.push_back(pointervalue != myOldState.datastreampointers[i]);
} }
myDatastreamPointers->setList(alist, vlist, changed); myDatastreamPointers->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 32; ++i) for(int i = 0; i < 32; ++i)
{ {
uInt32 incrementvalue = myCart.getDatastreamIncrement(i); Int32 incrementvalue = myCart.getDatastreamIncrement(i);
alist.push_back(0); vlist.push_back(incrementvalue); alist.push_back(0); vlist.push_back(incrementvalue);
changed.push_back(incrementvalue != myOldState.datastreamincrements[i]); changed.push_back(incrementvalue != myOldState.datastreamincrements[i]);
} }
myDatastreamIncrements->setList(alist, vlist, changed); myDatastreamIncrements->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
alist.push_back(0); vlist.push_back(myCart.myMusicCounters[i]); alist.push_back(0); vlist.push_back(myCart.myMusicCounters[i]);
changed.push_back(myCart.myMusicCounters[i] != (uInt32)myOldState.mcounters[i]); changed.push_back(myCart.myMusicCounters[i] != uInt32(myOldState.mcounters[i]));
} }
myMusicCounters->setList(alist, vlist, changed); myMusicCounters->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
alist.push_back(0); vlist.push_back(myCart.myMusicFrequencies[i]); alist.push_back(0); vlist.push_back(myCart.myMusicFrequencies[i]);
changed.push_back(myCart.myMusicFrequencies[i] != (uInt32)myOldState.mfreqs[i]); changed.push_back(myCart.myMusicFrequencies[i] != uInt32(myOldState.mfreqs[i]));
} }
myMusicFrequencies->setList(alist, vlist, changed); myMusicFrequencies->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
alist.push_back(0); vlist.push_back(myCart.getWaveform(i) >> 5); alist.push_back(0); vlist.push_back(myCart.getWaveform(i) >> 5);
changed.push_back((myCart.getWaveform(i) >> 5) != myOldState.mwaves[i]); changed.push_back((myCart.getWaveform(i) >> 5) != uInt32(myOldState.mwaves[i]));
} }
myMusicWaveforms->setList(alist, vlist, changed); myMusicWaveforms->setList(alist, vlist, changed);
alist.clear(); vlist.clear(); changed.clear(); alist.clear(); vlist.clear(); changed.clear();
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
{ {
alist.push_back(0); vlist.push_back(myCart.getWaveformSize(i)); alist.push_back(0); vlist.push_back(myCart.getWaveformSize(i));
changed.push_back((myCart.getWaveformSize(i)) != myOldState.mwavesizes[i]); changed.push_back((myCart.getWaveformSize(i)) != uInt32(myOldState.mwavesizes[i]));
} }
myMusicWaveformSizes->setList(alist, vlist, changed); myMusicWaveformSizes->setList(alist, vlist, changed);
// done differently than in DPC+, need to rethink debugger support // done differently than in DPC+, need to rethink debugger support
// myFastFetch->setState(myCart.myFastFetch); // myFastFetch->setState(myCart.myFastFetch);
// myIMLDA->setState(myCart.myLDAimmediate); // myIMLDA->setState(myCart.myLDAimmediate);
CartDebugWidget::loadConfig(); CartDebugWidget::loadConfig();
} }
@ -282,13 +280,13 @@ void CartridgeCDFWidget::handleCommand(CommandSender* sender,
string CartridgeCDFWidget::bankState() string CartridgeCDFWidget::bankState()
{ {
ostringstream& buf = buffer(); ostringstream& buf = buffer();
static const char* spot[] = { static const char* spot[] = {
"$FF5", "$FF6", "$FF7", "$FF8", "$FF9", "$FFA", "$FFB" "$FF5", "$FF6", "$FF7", "$FF8", "$FF9", "$FFA", "$FFB"
}; };
buf << "Bank = " << std::dec << myCart.myCurrentBank buf << "Bank = " << std::dec << myCart.myCurrentBank
<< ", hotspot = " << spot[myCart.myCurrentBank]; << ", hotspot = " << spot[myCart.myCurrentBank];
return buf.str(); return buf.str();
} }
@ -315,7 +313,7 @@ string CartridgeCDFWidget::internalRamDescription()
<< " via CDF's Data Stream registers\n" << " via CDF's Data Stream registers\n"
<< "$1800 - $1FFF - 2K C variable storage and stack\n" << "$1800 - $1FFF - 2K C variable storage and stack\n"
<< " not accessible to 6507"; << " not accessible to 6507";
return desc.str(); return desc.str();
} }

128
src/debugger/gui/CartCDFWidget.hxx Executable file → Normal file
View File

@ -8,13 +8,11 @@
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartCDFWidget.hxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#ifndef CARTRIDGECDF_WIDGET_HXX #ifndef CARTRIDGECDF_WIDGET_HXX
@ -29,68 +27,68 @@ class DataGridWidget;
class CartridgeCDFWidget : public CartDebugWidget class CartridgeCDFWidget : public CartDebugWidget
{ {
public: public:
CartridgeCDFWidget(GuiObject* boss, const GUI::Font& lfont, CartridgeCDFWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, const GUI::Font& nfont,
int x, int y, int w, int h, int x, int y, int w, int h,
CartridgeCDF& cart); CartridgeCDF& cart);
virtual ~CartridgeCDFWidget() { } virtual ~CartridgeCDFWidget() = default;
private: private:
struct CartState { struct CartState {
ByteArray tops; ByteArray tops;
ByteArray bottoms; ByteArray bottoms;
IntArray datastreampointers; IntArray datastreampointers;
IntArray datastreamincrements; IntArray datastreamincrements;
IntArray addressmaps; IntArray addressmaps;
IntArray mcounters; IntArray mcounters;
IntArray mfreqs; IntArray mfreqs;
IntArray mwaves; IntArray mwaves;
IntArray mwavesizes; IntArray mwavesizes;
uInt32 random; uInt32 random;
ByteArray internalram; ByteArray internalram;
}; };
CartridgeCDF& myCart; CartridgeCDF& myCart;
PopUpWidget* myBank; PopUpWidget* myBank;
DataGridWidget* myDatastreamPointers; DataGridWidget* myDatastreamPointers;
DataGridWidget* myDatastreamIncrements; DataGridWidget* myDatastreamIncrements;
DataGridWidget* myMusicCounters; DataGridWidget* myMusicCounters;
DataGridWidget* myMusicFrequencies; DataGridWidget* myMusicFrequencies;
DataGridWidget* myMusicWaveforms; DataGridWidget* myMusicWaveforms;
DataGridWidget* myMusicWaveformSizes; DataGridWidget* myMusicWaveformSizes;
// done differently than in DPC+, need to rethink debugger support // done differently than in DPC+, need to rethink debugger support
// CheckboxWidget* myFastFetch; // CheckboxWidget* myFastFetch;
// CheckboxWidget* myIMLDA; // CheckboxWidget* myIMLDA;
CartState myOldState; CartState myOldState;
enum { kBankChanged = 'bkCH' }; enum { kBankChanged = 'bkCH' };
private: private:
void saveOldState() override; void saveOldState() override;
void loadConfig() override; void loadConfig() override;
void handleCommand(CommandSender* sender, int cmd, int data, int id) override; void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
string bankState() override; string bankState() override;
// start of functions for Cartridge RAM tab // start of functions for Cartridge RAM tab
uInt32 internalRamSize() override; uInt32 internalRamSize() override;
uInt32 internalRamRPort(int start) override; uInt32 internalRamRPort(int start) override;
string internalRamDescription() override; string internalRamDescription() override;
const ByteArray& internalRamOld(int start, int count) override; const ByteArray& internalRamOld(int start, int count) override;
const ByteArray& internalRamCurrent(int start, int count) override; const ByteArray& internalRamCurrent(int start, int count) override;
void internalRamSetValue(int addr, uInt8 value) override; void internalRamSetValue(int addr, uInt8 value) override;
uInt8 internalRamGetValue(int addr) override; uInt8 internalRamGetValue(int addr) override;
// end of functions for Cartridge RAM tab // end of functions for Cartridge RAM tab
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
CartridgeCDFWidget() = delete; CartridgeCDFWidget() = delete;
CartridgeCDFWidget(const CartridgeCDFWidget&) = delete; CartridgeCDFWidget(const CartridgeCDFWidget&) = delete;
CartridgeCDFWidget(CartridgeCDFWidget&&) = delete; CartridgeCDFWidget(CartridgeCDFWidget&&) = delete;
CartridgeCDFWidget& operator=(const CartridgeCDFWidget&) = delete; CartridgeCDFWidget& operator=(const CartridgeCDFWidget&) = delete;
CartridgeCDFWidget& operator=(CartridgeCDFWidget&&) = delete; CartridgeCDFWidget& operator=(CartridgeCDFWidget&&) = delete;
}; };
#endif #endif

View File

@ -690,6 +690,7 @@ void DataGridWidget::endEditMode()
editString().insert(0, 1, '#'); editString().insert(0, 1, '#');
break; break;
case Common::Base::F_DEFAULT: case Common::Base::F_DEFAULT:
default:
break; break;
} }
} }

View File

@ -111,6 +111,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& lfont,
return (c >= '0' && c <= '9') || c == ' '; return (c >= '0' && c <= '9') || c == ' ';
case Common::Base::F_DEFAULT: case Common::Base::F_DEFAULT:
default:
return false; return false;
} }
return false; return false;

View File

@ -31,6 +31,8 @@ MODULE_OBJS := \
src/debugger/gui/Cart4KWidget.o \ src/debugger/gui/Cart4KWidget.o \
src/debugger/gui/Cart4KSCWidget.o \ src/debugger/gui/Cart4KSCWidget.o \
src/debugger/gui/CartARWidget.o \ src/debugger/gui/CartARWidget.o \
src/debugger/gui/CartBUSWidget.o \
src/debugger/gui/CartCDFWidget.o \
src/debugger/gui/CartCMWidget.o \ src/debugger/gui/CartCMWidget.o \
src/debugger/gui/CartCTYWidget.o \ src/debugger/gui/CartCTYWidget.o \
src/debugger/gui/CartCVWidget.o \ src/debugger/gui/CartCVWidget.o \
@ -74,5 +76,5 @@ MODULE_OBJS := \
MODULE_DIRS += \ MODULE_DIRS += \
src/debugger/gui src/debugger/gui
# Include common rules # Include common rules
include $(srcdir)/common.rules include $(srcdir)/common.rules

View File

@ -1030,7 +1030,7 @@ Cartridge::BankswitchType Cartridge::ourBSList[ourNumBSTypes] = {
{ "BF", "BF (CPUWIZ 256K)" }, { "BF", "BF (CPUWIZ 256K)" },
{ "BFSC", "BFSC (CPUWIZ 256K + ram)" }, { "BFSC", "BFSC (CPUWIZ 256K + ram)" },
{ "BUS", "BUS (Bus Stuffing)" }, { "BUS", "BUS (Bus Stuffing)" },
{ "CDF", "CDF (Chris, Darrell, Fred)" }, { "CDF", "CDF (Chris, Darrell, Fred)" },
{ "CM", "CM (SpectraVideo CompuMate)" }, { "CM", "CM (SpectraVideo CompuMate)" },
{ "CTY", "CTY (CDW - Chetiry)" }, { "CTY", "CTY (CDW - Chetiry)" },
{ "CV", "CV (Commavid extra ram)" }, { "CV", "CV (Commavid extra ram)" },

View File

@ -178,7 +178,7 @@ class Cartridge : public Device
to pass values back to the cartridge class to emulate those subroutines. to pass values back to the cartridge class to emulate those subroutines.
*/ */
virtual uInt32 thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) { return 0; } virtual uInt32 thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) { return 0; }
/** /**
Get debugger widget responsible for accessing the inner workings Get debugger widget responsible for accessing the inner workings
of the cart. This will need to be overridden and implemented by of the cart. This will need to be overridden and implemented by
@ -314,12 +314,12 @@ class Cartridge : public Device
Returns true if the image is probably a BUS bankswitching cartridge Returns true if the image is probably a BUS bankswitching cartridge
*/ */
static bool isProbablyBUS(const uInt8* image, uInt32 size); static bool isProbablyBUS(const uInt8* image, uInt32 size);
/** /**
Returns true if the image is probably a CDF bankswitching cartridge Returns true if the image is probably a CDF bankswitching cartridge
*/ */
static bool isProbablyCDF(const uInt8* image, uInt32 size); static bool isProbablyCDF(const uInt8* image, uInt32 size);
/** /**
Returns true if the image is probably a CTY bankswitching cartridge Returns true if the image is probably a CTY bankswitching cartridge
*/ */

View File

@ -8,13 +8,11 @@
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartBUS.cxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#include <cstring> #include <cstring>
@ -45,14 +43,14 @@ CartridgeBUS::CartridgeBUS(const uInt8* image, uInt32 size,
{ {
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size)); memcpy(myImage, image, std::min(32768u, size));
// even though the ROM is 32K, only 28K is accessible to the 6507 // even though the ROM is 32K, only 28K is accessible to the 6507
createCodeAccessBase(4096 * 7); createCodeAccessBase(4096 * 7);
// Pointer to the program ROM (28K @ 0 byte offset) // Pointer to the program ROM (28K @ 0 byte offset)
// which starts after the 2K BUS Driver and 2K C Code // which starts after the 2K BUS Driver and 2K C Code
myProgramImage = myImage + 4096; myProgramImage = myImage + 4096;
// Pointer to BUS driver in RAM // Pointer to BUS driver in RAM
myBusDriverImage = myBUSRAM; myBusDriverImage = myBUSRAM;
@ -61,36 +59,27 @@ CartridgeBUS::CartridgeBUS(const uInt8* image, uInt32 size,
#ifdef THUMB_SUPPORT #ifdef THUMB_SUPPORT
// Create Thumbulator ARM emulator // Create Thumbulator ARM emulator
myThumbEmulator = make_ptr<Thumbulator> myThumbEmulator = make_ptr<Thumbulator>((uInt16*)myImage, (uInt16*)myBUSRAM,
((uInt16*)myImage, (uInt16*)myBUSRAM, settings.getBool("thumb.trapfatal"), Thumbulator::ConfigureFor::BUS, this);
settings.getBool("thumb.trapfatal"),
Thumbulator::ConfigureFor::BUS,
this);
#endif #endif
setInitialState(); setInitialState();
// BUS always starts in bank 6 // BUS always starts in bank 6
myStartBank = 6; myStartBank = 6;
// bus stuffing is off by default // bus stuffing is off by default
myBusStuff = false; myBusStuff = false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeBUS::~CartridgeBUS()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBUS::reset() void CartridgeBUS::reset()
{ {
// Initialize RAM // Initialize RAM
if(mySettings.getBool("ramrandom")) if(mySettings.getBool("ramrandom"))
for(uInt32 t = 2048; t < 8192; ++t) initializeRAM(myBUSRAM+2048, 8192-2048);
myBUSRAM[t] = mySystem->randGenerator().next();
else else
memset(myBUSRAM+2048, 0, 8192-2048); memset(myBUSRAM+2048, 0, 8192-2048);
// Update cycles to the current system cycles // Update cycles to the current system cycles
mySystemCycles = mySystem->cycles(); mySystemCycles = mySystem->cycles();
myFractionalClocks = 0.0; myFractionalClocks = 0.0;
@ -106,7 +95,7 @@ void CartridgeBUS::setInitialState()
{ {
// Copy initial BUS driver to Harmony RAM // Copy initial BUS driver to Harmony RAM
memcpy(myBusDriverImage, myImage, 0x0800); memcpy(myBusDriverImage, myImage, 0x0800);
for (int i=0; i < 3; ++i) for (int i=0; i < 3; ++i)
myMusicWaveformSize[i] = 27; myMusicWaveformSize[i] = 27;
} }
@ -135,12 +124,12 @@ void CartridgeBUS::install(System& system)
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
for(uInt32 i = 0x1000; i < 0x1040; i += (1 << System::PAGE_SHIFT)) for(uInt32 i = 0x1000; i < 0x1040; i += (1 << System::PAGE_SHIFT))
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access); mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
// Mirror all access in TIA and RIOT; by doing so we're taking responsibility // Mirror all access in TIA and RIOT; by doing so we're taking responsibility
// for that address space in peek and poke below. // for that address space in peek and poke below.
mySystem->tia().installDelegate(system, *this); mySystem->tia().installDelegate(system, *this);
mySystem->m6532().installDelegate(system, *this); mySystem->m6532().installDelegate(system, *this);
// Install pages for the startup bank // Install pages for the startup bank
bank(myStartBank); bank(myStartBank);
} }
@ -212,28 +201,28 @@ uInt8 CartridgeBUS::peek(uInt16 address)
else else
{ {
address &= 0x0FFF; address &= 0x0FFF;
uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address]; uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address];
// In debugger/bank-locked mode, we ignore all hotspots and in general // In debugger/bank-locked mode, we ignore all hotspots and in general
// anything that can change the internal state of the cart // anything that can change the internal state of the cart
if(bankLocked()) if(bankLocked())
return peekvalue; return peekvalue;
// save the STY's zero page address // save the STY's zero page address
if (getBusStuffFlag() && mySTYZeroPage) if (getBusStuffFlag() && mySTYZeroPage)
myBusOverdriveAddress = peekvalue; myBusOverdriveAddress = peekvalue;
mySTYZeroPage = false; mySTYZeroPage = false;
if(address < 0x20) if(address < 0x20)
{ {
uInt8 result = 0; uInt8 result = 0;
// Get the index of the data fetcher that's being accessed // Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x0f; uInt32 index = address & 0x0f;
uInt32 function = (address >> 4) & 0x01; uInt32 function = (address >> 4) & 0x01;
switch(function) switch(function)
{ {
case 0x00: // read from a datastream case 0x00: // read from a datastream
@ -257,24 +246,24 @@ uInt8 CartridgeBUS::peek(uInt16 address)
case 0x09: // 0x19 STUFFMODE case 0x09: // 0x19 STUFFMODE
case 0x0a: // 0x1A CALLFN case 0x0a: // 0x1A CALLFN
break; break;
case 0x08: // 0x18 = AMPLITUDE case 0x08: // 0x18 = AMPLITUDE
// Update the music data fetchers (counter & flag) // Update the music data fetchers (counter & flag)
updateMusicModeDataFetchers(); updateMusicModeDataFetchers();
// using myDisplayImage[] instead of myProgramImage[] because waveforms // using myDisplayImage[] instead of myProgramImage[] because waveforms
// can be modified during runtime. // can be modified during runtime.
uInt32 i = myDisplayImage[(getWaveform(0) ) + (myMusicCounters[0] >> myMusicWaveformSize[0])] + uInt32 i = myDisplayImage[(getWaveform(0) ) + (myMusicCounters[0] >> myMusicWaveformSize[0])] +
myDisplayImage[(getWaveform(1) ) + (myMusicCounters[1] >> myMusicWaveformSize[1])] + myDisplayImage[(getWaveform(1) ) + (myMusicCounters[1] >> myMusicWaveformSize[1])] +
myDisplayImage[(getWaveform(2) ) + (myMusicCounters[2] >> myMusicWaveformSize[2])]; myDisplayImage[(getWaveform(2) ) + (myMusicCounters[2] >> myMusicWaveformSize[2])];
result = uInt8(i); result = uInt8(i);
break; break;
} }
break; break;
} }
} }
return result; return result;
} }
else else
@ -286,48 +275,50 @@ uInt8 CartridgeBUS::peek(uInt16 address)
// Set the current bank to the first 4k bank // Set the current bank to the first 4k bank
bank(0); bank(0);
break; break;
case 0x0FF6: case 0x0FF6:
// Set the current bank to the second 4k bank // Set the current bank to the second 4k bank
bank(1); bank(1);
break; break;
case 0x0FF7: case 0x0FF7:
// Set the current bank to the third 4k bank // Set the current bank to the third 4k bank
bank(2); bank(2);
break; break;
case 0x0FF8: case 0x0FF8:
// Set the current bank to the fourth 4k bank // Set the current bank to the fourth 4k bank
bank(3); bank(3);
break; break;
case 0x0FF9: case 0x0FF9:
// Set the current bank to the fifth 4k bank // Set the current bank to the fifth 4k bank
bank(4); bank(4);
break; break;
case 0x0FFA: case 0x0FFA:
// Set the current bank to the sixth 4k bank // Set the current bank to the sixth 4k bank
bank(5); bank(5);
break; break;
case 0x0FFB: case 0x0FFB:
// Set the current bank to the last 4k bank // Set the current bank to the last 4k bank
bank(6); bank(6);
break; break;
default: default:
break; break;
} }
// this might not work right for STY $84 // this might not work right for STY $84
if (getBusStuffFlag()) if (getBusStuffFlag())
mySTYZeroPage = (peekvalue == 0x84); mySTYZeroPage = (peekvalue == 0x84);
return peekvalue; return peekvalue;
} }
} }
return 0; // make compiler happy
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -336,25 +327,24 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
if (!(address & 0x1000)) if (!(address & 0x1000))
{ {
value &= busOverdrive(address); value &= busOverdrive(address);
// Check for RAM or TIA mirroring // Check for RAM or TIA mirroring
uInt16 lowAddress = address & 0x3ff; uInt16 lowAddress = address & 0x3ff;
if(lowAddress & 0x80) if(lowAddress & 0x80)
mySystem->m6532().poke(address, value); mySystem->m6532().poke(address, value);
else if(!(lowAddress & 0x200)) else if(!(lowAddress & 0x200))
mySystem->tia().poke(address, value); mySystem->tia().poke(address, value);
} }
else else
{ {
address &= 0x0FFF; address &= 0x0FFF;
if ((address >= 0x10) && (address <= 0x1F)) if ((address >= 0x10) && (address <= 0x1F))
{ {
// Get the index of the data fetcher that's being accessed // Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x0f; uInt32 index = address & 0x0f;
uInt32 pointer; uInt32 pointer;
switch (index) switch (index)
{ {
case 0x00: // DS0WRITE case 0x00: // DS0WRITE
@ -366,13 +356,13 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
// //
// P = Pointer // P = Pointer
// F = Fractional // F = Fractional
pointer = getDatastreamPointer(index); pointer = getDatastreamPointer(index);
myDisplayImage[ pointer >> 20 ] = value; myDisplayImage[ pointer >> 20 ] = value;
pointer += 0x100000; // always increment by 1 when writing pointer += 0x100000; // always increment by 1 when writing
setDatastreamPointer(index, pointer); setDatastreamPointer(index, pointer);
break; break;
case 0x04: // 0x14 DS0PTR case 0x04: // 0x14 DS0PTR
case 0x05: // 0x15 DS1PTR case 0x05: // 0x15 DS1PTR
case 0x06: // 0x16 DS2PTR case 0x06: // 0x16 DS2PTR
@ -382,7 +372,7 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
// //
// P = Pointer // P = Pointer
// F = Fractional // F = Fractional
index &= 0x03; index &= 0x03;
pointer = getDatastreamPointer(index); pointer = getDatastreamPointer(index);
pointer <<=8; pointer <<=8;
@ -390,11 +380,11 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
pointer |= (value << 20); pointer |= (value << 20);
setDatastreamPointer(index, pointer); setDatastreamPointer(index, pointer);
break; break;
case 0x09: // 0x19 turn on STY ZP bus stuffing if value is 0 case 0x09: // 0x19 turn on STY ZP bus stuffing if value is 0
setBusStuffFlag(value==0); setBusStuffFlag(value==0);
break; break;
case 0x0A: // 0x1A CALLFUNCTION case 0x0A: // 0x1A CALLFUNCTION
callFunction(value); callFunction(value);
break; break;
@ -409,37 +399,37 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
// Set the current bank to the first 4k bank // Set the current bank to the first 4k bank
bank(0); bank(0);
break; break;
case 0x0FF6: case 0x0FF6:
// Set the current bank to the second 4k bank // Set the current bank to the second 4k bank
bank(1); bank(1);
break; break;
case 0x0FF7: case 0x0FF7:
// Set the current bank to the third 4k bank // Set the current bank to the third 4k bank
bank(2); bank(2);
break; break;
case 0x0FF8: case 0x0FF8:
// Set the current bank to the fourth 4k bank // Set the current bank to the fourth 4k bank
bank(3); bank(3);
break; break;
case 0x0FF9: case 0x0FF9:
// Set the current bank to the fifth 4k bank // Set the current bank to the fifth 4k bank
bank(4); bank(4);
break; break;
case 0x0FFA: case 0x0FFA:
// Set the current bank to the sixth 4k bank // Set the current bank to the sixth 4k bank
bank(5); bank(5);
break; break;
case 0x0FFB: case 0x0FFB:
// Set the current bank to the last 4k bank // Set the current bank to the last 4k bank
bank(6); bank(6);
break; break;
default: default:
break; break;
} }
@ -506,46 +496,43 @@ const uInt8* CartridgeBUS::getImage(int& size) const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeBUS::busOverdrive(uInt16 address) uInt8 CartridgeBUS::busOverdrive(uInt16 address)
{ {
uInt8 overdrive = 0xff; uInt8 overdrive = 0xff;
// Not sure how to do this, check with stephena. // Not sure how to do this, check with stephena.
// //
// Per discussion with cd-w, have this routine check that the Y register has a // Per discussion with cd-w, have this routine check that the Y register has a
// value of 0xFF. Of it doesn't then "crash the emulation". // value of 0xFF. Of it doesn't then "crash the emulation".
// only overdrive if the address matches // only overdrive if the address matches
if (address == myBusOverdriveAddress) if (address == myBusOverdriveAddress)
{ {
uInt8 map = address & 0x7f; uInt8 map = address & 0x7f;
if (map <= 0x24) // map TIA registers VSYNC thru HMBL inclusive if (map <= 0x24) // map TIA registers VSYNC thru HMBL inclusive
{ {
uInt32 alldatastreams = getAddressMap(map); uInt32 alldatastreams = getAddressMap(map);
uInt8 datastream = alldatastreams & 0x0f; // lowest nybble has the current datastream to use uInt8 datastream = alldatastreams & 0x0f; // lowest nybble has the current datastream to use
overdrive = readFromDatastream(datastream); overdrive = readFromDatastream(datastream);
// rotate map nybbles for next time // rotate map nybbles for next time
alldatastreams >>= 4; alldatastreams >>= 4;
alldatastreams |= (datastream << 28); alldatastreams |= (datastream << 28);
setAddressMap(map, alldatastreams); setAddressMap(map, alldatastreams);
// overdrive |= 0x7c; // breaks bus stuffing to match hobo's system // overdrive |= 0x7c; // breaks bus stuffing to match hobo's system
} }
} }
myBusOverdriveAddress = 0xff; // turns off overdrive for next poke event myBusOverdriveAddress = 0xff; // turns off overdrive for next poke event
return overdrive; return overdrive;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUS::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) uInt32 CartridgeBUS::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2)
{ {
switch (function) switch (function)
{ {
case 0: case 0:
@ -558,7 +545,7 @@ uInt32 CartridgeBUS::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2)
case 1: case 1:
myMusicCounters[value1] = 0; myMusicCounters[value1] = 0;
break; break;
// _GetWavePtr - return the counter // _GetWavePtr - return the counter
case 2: case 2:
return myMusicCounters[value1]; return myMusicCounters[value1];
@ -569,11 +556,10 @@ uInt32 CartridgeBUS::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2)
myMusicWaveformSize[value1] = value2; myMusicWaveformSize[value1] = value2;
break; break;
} }
return 0; return 0;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBUS::save(Serializer& out) const bool CartridgeBUS::save(Serializer& out) const
{ {
@ -629,16 +615,18 @@ bool CartridgeBUS::load(Serializer& in)
return true; return true;
} }
uInt32 CartridgeBUS::getDatastreamPointer(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUS::getDatastreamPointer(uInt8 index) const
{ {
// index &= 0x0f; // index &= 0x0f;
return myBUSRAM[DSxPTR + index*4 + 0] + // low byte return myBUSRAM[DSxPTR + index*4 + 0] + // low byte
(myBUSRAM[DSxPTR + index*4 + 1] << 8) + (myBUSRAM[DSxPTR + index*4 + 1] << 8) +
(myBUSRAM[DSxPTR + index*4 + 2] << 16) + (myBUSRAM[DSxPTR + index*4 + 2] << 16) +
(myBUSRAM[DSxPTR + index*4 + 3] << 24) ; // high byte (myBUSRAM[DSxPTR + index*4 + 3] << 24) ; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBUS::setDatastreamPointer(uInt8 index, uInt32 value) void CartridgeBUS::setDatastreamPointer(uInt8 index, uInt32 value)
{ {
// index &= 0x0f; // index &= 0x0f;
@ -648,7 +636,8 @@ void CartridgeBUS::setDatastreamPointer(uInt8 index, uInt32 value)
myBUSRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte myBUSRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte
} }
uInt32 CartridgeBUS::getDatastreamIncrement(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUS::getDatastreamIncrement(uInt8 index) const
{ {
// index &= 0x0f; // index &= 0x0f;
return myBUSRAM[DSxINC + index*4 + 0] + // low byte return myBUSRAM[DSxINC + index*4 + 0] + // low byte
@ -657,6 +646,7 @@ uInt32 CartridgeBUS::getDatastreamIncrement(uInt8 index)
(myBUSRAM[DSxINC + index*4 + 3] << 24) ; // high byte (myBUSRAM[DSxINC + index*4 + 3] << 24) ; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBUS::setDatastreamIncrement(uInt8 index, uInt32 value) void CartridgeBUS::setDatastreamIncrement(uInt8 index, uInt32 value)
{ {
// index &= 0x0f; // index &= 0x0f;
@ -666,7 +656,8 @@ void CartridgeBUS::setDatastreamIncrement(uInt8 index, uInt32 value)
myBUSRAM[DSxINC + index*4 + 3] = (value >> 24) & 0xff; // high byte myBUSRAM[DSxINC + index*4 + 3] = (value >> 24) & 0xff; // high byte
} }
uInt32 CartridgeBUS::getAddressMap(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUS::getAddressMap(uInt8 index) const
{ {
// index &= 0x0f; // index &= 0x0f;
return myBUSRAM[DSMAPS + index*4 + 0] + // low byte return myBUSRAM[DSMAPS + index*4 + 0] + // low byte
@ -675,40 +666,43 @@ uInt32 CartridgeBUS::getAddressMap(uInt8 index)
(myBUSRAM[DSMAPS + index*4 + 3] << 24) ; // high byte (myBUSRAM[DSMAPS + index*4 + 3] << 24) ; // high byte
} }
uInt32 CartridgeBUS::getWaveform(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUS::getWaveform(uInt8 index) const
{ {
// instead of 0, 1, 2, etc. this returned // instead of 0, 1, 2, etc. this returned
// 0x40000800 for 0 // 0x40000800 for 0
// 0x40000820 for 1 // 0x40000820 for 1
// 0x40000840 for 2 // 0x40000840 for 2
// ... // ...
// return myBUSRAM[WAVEFORM + index*4 + 0] + // low byte // return myBUSRAM[WAVEFORM + index*4 + 0] + // low byte
// (myBUSRAM[WAVEFORM + index*4 + 1] << 8) + // (myBUSRAM[WAVEFORM + index*4 + 1] << 8) +
// (myBUSRAM[WAVEFORM + index*4 + 2] << 16) + // (myBUSRAM[WAVEFORM + index*4 + 2] << 16) +
// (myBUSRAM[WAVEFORM + index*4 + 3] << 24) - // high byte // (myBUSRAM[WAVEFORM + index*4 + 3] << 24) - // high byte
// 0x40000800; // 0x40000800;
uInt32 result; uInt32 result;
result = myBUSRAM[WAVEFORM + index*4 + 0] + // low byte result = myBUSRAM[WAVEFORM + index*4 + 0] + // low byte
(myBUSRAM[WAVEFORM + index*4 + 1] << 8) + (myBUSRAM[WAVEFORM + index*4 + 1] << 8) +
(myBUSRAM[WAVEFORM + index*4 + 2] << 16) + (myBUSRAM[WAVEFORM + index*4 + 2] << 16) +
(myBUSRAM[WAVEFORM + index*4 + 3] << 24); (myBUSRAM[WAVEFORM + index*4 + 3] << 24);
result -= 0x40000800; result -= 0x40000800;
if (result >= 4096) if (result >= 4096)
result = 0; result = 0;
return result; return result;
} }
uInt32 CartridgeBUS::getWaveformSize(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeBUS::getWaveformSize(uInt8 index) const
{ {
return myMusicWaveformSize[index]; return myMusicWaveformSize[index];
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBUS::setAddressMap(uInt8 index, uInt32 value) void CartridgeBUS::setAddressMap(uInt8 index, uInt32 value)
{ {
// index &= 0x0f; // index &= 0x0f;
@ -718,16 +712,19 @@ void CartridgeBUS::setAddressMap(uInt8 index, uInt32 value)
myBUSRAM[DSMAPS + index*4 + 3] = (value >> 24) & 0xff; // high byte myBUSRAM[DSMAPS + index*4 + 3] = (value >> 24) & 0xff; // high byte
} }
bool CartridgeBUS::getBusStuffFlag(void) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartridgeBUS::getBusStuffFlag(void) const
{ {
return myBusStuff; return myBusStuff;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeBUS::setBusStuffFlag(bool value) void CartridgeBUS::setBusStuffFlag(bool value)
{ {
myBusStuff = value; myBusStuff = value;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeBUS::readFromDatastream(uInt8 index) uInt8 CartridgeBUS::readFromDatastream(uInt8 index)
{ {
// Pointers are stored as: // Pointers are stored as:
@ -739,7 +736,7 @@ uInt8 CartridgeBUS::readFromDatastream(uInt8 index)
// P = Pointer // P = Pointer
// I = Increment // I = Increment
// F = Fractional // F = Fractional
uInt32 pointer = getDatastreamPointer(index); uInt32 pointer = getDatastreamPointer(index);
uInt16 increment = getDatastreamIncrement(index); uInt16 increment = getDatastreamIncrement(index);
uInt8 value = myDisplayImage[ pointer >> 20 ]; uInt8 value = myDisplayImage[ pointer >> 20 ];
@ -747,4 +744,3 @@ uInt8 CartridgeBUS::readFromDatastream(uInt8 index)
setDatastreamPointer(index, pointer); setDatastreamPointer(index, pointer);
return value; return value;
} }

View File

@ -8,13 +8,11 @@
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartBUS.hxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#ifndef CARTRIDGE_BUS_HXX #ifndef CARTRIDGE_BUS_HXX
@ -22,7 +20,7 @@
class System; class System;
#ifdef THUMB_SUPPORT #ifdef THUMB_SUPPORT
class Thumbulator; class Thumbulator;
#endif #endif
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "CartBUSWidget.hxx" #include "CartBUSWidget.hxx"
@ -32,22 +30,22 @@ class Thumbulator;
#include "Cart.hxx" #include "Cart.hxx"
/** /**
Cartridge class used for BUS. Cartridge class used for BUS.
THIS NEEDS TO BE UPDATED THIS NEEDS TO BE UPDATED
There are seven 4K program banks, a 4K Display Data RAM, There are seven 4K program banks, a 4K Display Data RAM,
1K C Varaible and Stack, and the BUS chip. 1K C Varaible and Stack, and the BUS chip.
BUS chip access is mapped to $1000 - $103F. BUS chip access is mapped to $1000 - $103F.
@author Darrell Spice Jr, Chris Walton, Fred Quimby, Stephen Anthony, Bradford W. Mott Authors: Darrell Spice Jr, Chris Walton, Fred Quimby,
@version $Id: CartBUS.hxx 3131 2015-01-01 03:49:32Z stephena $ Stephen Anthony, Bradford W. Mott
*/ */
class CartridgeBUS : public Cartridge class CartridgeBUS : public Cartridge
{ {
friend class CartridgeBUSWidget; friend class CartridgeBUSWidget;
friend class CartridgeRamBUSWidget; friend class CartridgeRamBUSWidget;
public: public:
/** /**
@ -58,11 +56,7 @@ class CartridgeBUS : public Cartridge
@param settings A reference to the various settings (read-only) @param settings A reference to the various settings (read-only)
*/ */
CartridgeBUS(const uInt8* image, uInt32 size, const Settings& settings); CartridgeBUS(const uInt8* image, uInt32 size, const Settings& settings);
virtual ~CartridgeBUS() = default;
/**
Destructor
*/
virtual ~CartridgeBUS();
public: public:
/** /**
@ -74,11 +68,11 @@ class CartridgeBUS : public Cartridge
Notification method invoked by the system when the console type Notification method invoked by the system when the console type
has changed. We need this to inform the Thumbulator that the has changed. We need this to inform the Thumbulator that the
timing has changed. timing has changed.
@param timing Enum representing the new console type @param timing Enum representing the new console type
*/ */
void consoleChanged(ConsoleTiming timing) override; void consoleChanged(ConsoleTiming timing) override;
/** /**
Notification method invoked by the system right before the Notification method invoked by the system right before the
system resets its cycle counter to zero. It may be necessary system resets its cycle counter to zero. It may be necessary
@ -150,14 +144,14 @@ class CartridgeBUS : public Cartridge
@return The name of the object @return The name of the object
*/ */
string name() const override { return "CartridgeBUS"; } string name() const override { return "CartridgeBUS"; }
uInt8 busOverdrive(uInt16 address); uInt8 busOverdrive(uInt16 address);
/** /**
Used for Thumbulator to pass values back to the cartridge Used for Thumbulator to pass values back to the cartridge
*/ */
uInt32 thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) override; uInt32 thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) override;
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
/** /**
@ -189,49 +183,49 @@ class CartridgeBUS : public Cartridge
bool poke(uInt16 address, uInt8 value) override; bool poke(uInt16 address, uInt8 value) override;
private: private:
/** /**
Sets the initial state of the DPC pointers and RAM Sets the initial state of the DPC pointers and RAM
*/ */
void setInitialState(); void setInitialState();
/** /**
Updates any data fetchers in music mode based on the number of Updates any data fetchers in music mode based on the number of
CPU cycles which have passed since the last update. CPU cycles which have passed since the last update.
*/ */
void updateMusicModeDataFetchers(); void updateMusicModeDataFetchers();
/** /**
Call Special Functions Call Special Functions
*/ */
void callFunction(uInt8 value); void callFunction(uInt8 value);
uInt32 getDatastreamPointer(uInt8 index); uInt32 getDatastreamPointer(uInt8 index) const;
void setDatastreamPointer(uInt8 index, uInt32 value); void setDatastreamPointer(uInt8 index, uInt32 value);
uInt32 getDatastreamIncrement(uInt8 index); uInt32 getDatastreamIncrement(uInt8 index) const;
void setDatastreamIncrement(uInt8 index, uInt32 value); void setDatastreamIncrement(uInt8 index, uInt32 value);
uInt32 getAddressMap(uInt8 index); uInt32 getAddressMap(uInt8 index) const;
void setAddressMap(uInt8 index, uInt32 value); void setAddressMap(uInt8 index, uInt32 value);
bool getBusStuffFlag(void); bool getBusStuffFlag(void) const;
void setBusStuffFlag(bool value); void setBusStuffFlag(bool value);
uInt8 readFromDatastream(uInt8 index); uInt8 readFromDatastream(uInt8 index);
uInt32 getWaveform(uInt8 index); uInt32 getWaveform(uInt8 index) const;
uInt32 getWaveformSize(uInt8 index); uInt32 getWaveformSize(uInt8 index) const;
private: private:
// The 32K ROM image of the cartridge // The 32K ROM image of the cartridge
uInt8 myImage[32768]; uInt8 myImage[32768];
// Pointer to the 28K program ROM image of the cartridge // Pointer to the 28K program ROM image of the cartridge
uInt8* myProgramImage; uInt8* myProgramImage;
// Pointer to the 4K display ROM image of the cartridge // Pointer to the 4K display ROM image of the cartridge
uInt8* myDisplayImage; uInt8* myDisplayImage;
// Pointer to the 2K BUS driver image in RAM // Pointer to the 2K BUS driver image in RAM
uInt8* myBusDriverImage; uInt8* myBusDriverImage;
@ -248,7 +242,7 @@ class CartridgeBUS : public Cartridge
// Indicates which bank is currently active // Indicates which bank is currently active
uInt16 myCurrentBank; uInt16 myCurrentBank;
// Address to override the bus for // Address to override the bus for
uInt16 myBusOverdriveAddress; uInt16 myBusOverdriveAddress;
@ -257,25 +251,25 @@ class CartridgeBUS : public Cartridge
// System cycle count when the last update to music data fetchers occurred // System cycle count when the last update to music data fetchers occurred
Int32 mySystemCycles; Int32 mySystemCycles;
uInt8 mySetAddress; uInt8 mySetAddress;
// The music mode counters // The music mode counters
uInt32 myMusicCounters[3]; uInt32 myMusicCounters[3];
// The music frequency // The music frequency
uInt32 myMusicFrequencies[3]; uInt32 myMusicFrequencies[3];
// The music waveform sizes // The music waveform sizes
uInt8 myMusicWaveformSize[3]; uInt8 myMusicWaveformSize[3];
// Fractional DPC music OSC clocks unused during the last update // Fractional DPC music OSC clocks unused during the last update
double myFractionalClocks; double myFractionalClocks;
// Flags that Bus Stuffing is active // Flags that Bus Stuffing is active
bool myBusStuff; bool myBusStuff;
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
CartridgeBUS() = delete; CartridgeBUS() = delete;
CartridgeBUS(const CartridgeBUS&) = delete; CartridgeBUS(const CartridgeBUS&) = delete;

228
src/emucore/CartCDF.cxx Executable file → Normal file
View File

@ -8,20 +8,19 @@
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartCDF.cxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#include <cstring> #include <cstring>
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "Debugger.hxx" #include "Debugger.hxx"
#endif #endif
#include "System.hxx" #include "System.hxx"
#include "Thumbulator.hxx" #include "Thumbulator.hxx"
#include "CartCDF.hxx" #include "CartCDF.hxx"
@ -35,70 +34,60 @@
#define FAST_FETCH_ON ((myMode & 0x0F) == 0) #define FAST_FETCH_ON ((myMode & 0x0F) == 0)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCDF::CartridgeCDF(const uInt8* image, uInt32 size, CartridgeCDF::CartridgeCDF(const uInt8* image, uInt32 size,
const Settings& settings) const Settings& settings)
: Cartridge(settings), : Cartridge(settings),
mySystemCycles(0), mySystemCycles(0),
myARMCycles(0), myARMCycles(0),
myFractionalClocks(0.0) myFractionalClocks(0.0)
{ {
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
memcpy(myImage, image, std::min(32768u, size)); memcpy(myImage, image, std::min(32768u, size));
// even though the ROM is 32K, only 28K is accessible to the 6507 // even though the ROM is 32K, only 28K is accessible to the 6507
createCodeAccessBase(4096 * 7); createCodeAccessBase(4096 * 7);
// Pointer to the program ROM (28K @ 0 byte offset) // Pointer to the program ROM (28K @ 0 byte offset)
// which starts after the 2K CDF Driver and 2K C Code // which starts after the 2K CDF Driver and 2K C Code
myProgramImage = myImage + 4096; myProgramImage = myImage + 4096;
// Pointer to CDF driver in RAM // Pointer to CDF driver in RAM
myBusDriverImage = myCDFRAM; myBusDriverImage = myCDFRAM;
// Pointer to the display RAM // Pointer to the display RAM
myDisplayImage = myCDFRAM + DSRAM; myDisplayImage = myCDFRAM + DSRAM;
#ifdef THUMB_SUPPORT #ifdef THUMB_SUPPORT
// Create Thumbulator ARM emulator // Create Thumbulator ARM emulator
myThumbEmulator = make_ptr<Thumbulator> myThumbEmulator = make_ptr<Thumbulator>((uInt16*)myImage, (uInt16*)myCDFRAM,
((uInt16*)myImage, (uInt16*)myCDFRAM, settings.getBool("thumb.trapfatal"), Thumbulator::ConfigureFor::CDF, this);
settings.getBool("thumb.trapfatal"),
Thumbulator::ConfigureFor::CDF,
this);
#endif #endif
setInitialState(); setInitialState();
// CDF always starts in bank 6 // CDF always starts in bank 6
myStartBank = 6; myStartBank = 6;
// Assuming mode starts out with Fast Fetch off and 3-Voice music, // Assuming mode starts out with Fast Fetch off and 3-Voice music,
// need to confirm with Chris // need to confirm with Chris
myMode = 0xFF; myMode = 0xFF;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeCDF::~CartridgeCDF()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCDF::reset() void CartridgeCDF::reset()
{ {
// Initialize RAM // Initialize RAM
if(mySettings.getBool("ramrandom")) if(mySettings.getBool("ramrandom"))
for(uInt32 t = 2048; t < 8192; ++t) initializeRAM(myCDFRAM+2048, 8192-2048);
myCDFRAM[t] = mySystem->randGenerator().next();
else else
memset(myCDFRAM+2048, 0, 8192-2048); memset(myCDFRAM+2048, 0, 8192-2048);
// Update cycles to the current system cycles // Update cycles to the current system cycles
mySystemCycles = mySystem->cycles(); mySystemCycles = mySystem->cycles();
myARMCycles = mySystem->cycles(); myARMCycles = mySystem->cycles();
myFractionalClocks = 0.0; myFractionalClocks = 0.0;
setInitialState(); setInitialState();
// Upon reset we switch to the startup bank // Upon reset we switch to the startup bank
bank(myStartBank); bank(myStartBank);
} }
@ -108,7 +97,7 @@ void CartridgeCDF::setInitialState()
{ {
// Copy initial CDF driver to Harmony RAM // Copy initial CDF driver to Harmony RAM
memcpy(myBusDriverImage, myImage, 0x0800); memcpy(myBusDriverImage, myImage, 0x0800);
for (int i=0; i < 3; ++i) for (int i=0; i < 3; ++i)
myMusicWaveformSize[i] = 27; myMusicWaveformSize[i] = 27;
} }
@ -133,14 +122,14 @@ void CartridgeCDF::systemCyclesReset()
void CartridgeCDF::install(System& system) void CartridgeCDF::install(System& system)
{ {
mySystem = &system; mySystem = &system;
// Map all of the accesses to call peek and poke // Map all of the accesses to call peek and poke
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
for(uInt32 i = 0x1000; i < 0x1040; i += (1 << System::PAGE_SHIFT)) for(uInt32 i = 0x1000; i < 0x1040; i += (1 << System::PAGE_SHIFT))
mySystem->setPageAccess(i >> System::PAGE_SHIFT, access); mySystem->setPageAccess(i >> System::PAGE_SHIFT, access);
// Install pages for the startup bank // Install pages for the startup bank
bank(myStartBank); bank(myStartBank);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -149,17 +138,17 @@ inline void CartridgeCDF::updateMusicModeDataFetchers()
// Calculate the number of cycles since the last update // Calculate the number of cycles since the last update
Int32 cycles = mySystem->cycles() - mySystemCycles; Int32 cycles = mySystem->cycles() - mySystemCycles;
mySystemCycles = mySystem->cycles(); mySystemCycles = mySystem->cycles();
// Calculate the number of CDF OSC clocks since the last update // Calculate the number of CDF OSC clocks since the last update
double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks; double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks;
Int32 wholeClocks = Int32(clocks); Int32 wholeClocks = Int32(clocks);
myFractionalClocks = clocks - double(wholeClocks); myFractionalClocks = clocks - double(wholeClocks);
if(wholeClocks <= 0) if(wholeClocks <= 0)
{ {
return; return;
} }
// Let's update counters and flags of the music mode data fetchers // Let's update counters and flags of the music mode data fetchers
for(int x = 0; x <= 2; ++x) for(int x = 0; x <= 2; ++x)
{ {
@ -176,11 +165,11 @@ inline void CartridgeCDF::callFunction(uInt8 value)
// Call user written ARM code (will most likely be C compiled for ARM) // Call user written ARM code (will most likely be C compiled for ARM)
case 254: // call with IRQ driven audio, no special handling needed at this case 254: // call with IRQ driven audio, no special handling needed at this
// time for Stella as ARM code "runs in zero 6507 cycles". // time for Stella as ARM code "runs in zero 6507 cycles".
case 255: // call without IRQ driven audio case 255: // call without IRQ driven audio
try { try {
Int32 cycles = mySystem->cycles() - myARMCycles; Int32 cycles = mySystem->cycles() - myARMCycles;
myARMCycles = mySystem->cycles(); myARMCycles = mySystem->cycles();
myThumbEmulator->run(cycles); myThumbEmulator->run(cycles);
} }
catch(const runtime_error& e) { catch(const runtime_error& e) {
@ -202,14 +191,14 @@ inline void CartridgeCDF::callFunction(uInt8 value)
uInt8 CartridgeCDF::peek(uInt16 address) uInt8 CartridgeCDF::peek(uInt16 address)
{ {
address &= 0x0FFF; address &= 0x0FFF;
uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address]; uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address];
// In debugger/bank-locked mode, we ignore all hotspots and in general // In debugger/bank-locked mode, we ignore all hotspots and in general
// anything that can change the internal state of the cart // anything that can change the internal state of the cart
if(bankLocked()) if(bankLocked())
return peekvalue; return peekvalue;
// Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value) // Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value)
if(FAST_FETCH_ON && myLDAimmediateOperandAddress == address) if(FAST_FETCH_ON && myLDAimmediateOperandAddress == address)
{ {
@ -219,15 +208,14 @@ uInt8 CartridgeCDF::peek(uInt16 address)
} }
myLDAimmediateOperandAddress = 0; myLDAimmediateOperandAddress = 0;
if(address <= 0x20) if(address <= 0x20)
{ {
uInt8 result = 0; uInt8 result = 0;
// Get the index of the data fetcher that's being accessed // Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x1f; uInt32 index = address & 0x1f;
uInt32 function = (address >> 5) & 0x01; uInt32 function = (address >> 5) & 0x01;
switch(function) switch(function)
{ {
case 0x00: // read from a datastream case 0x00: // read from a datastream
@ -240,18 +228,18 @@ uInt8 CartridgeCDF::peek(uInt16 address)
// index will be 0 for address 0x20 = AMPLITUDE // index will be 0 for address 0x20 = AMPLITUDE
// Update the music data fetchers (counter & flag) // Update the music data fetchers (counter & flag)
updateMusicModeDataFetchers(); updateMusicModeDataFetchers();
// using myDisplayImage[] instead of myProgramImage[] because waveforms // using myDisplayImage[] instead of myProgramImage[] because waveforms
// can be modified during runtime. // can be modified during runtime.
uInt32 i = myDisplayImage[(getWaveform(0) ) + (myMusicCounters[0] >> myMusicWaveformSize[0])] + uInt32 i = myDisplayImage[(getWaveform(0) ) + (myMusicCounters[0] >> myMusicWaveformSize[0])] +
myDisplayImage[(getWaveform(1) ) + (myMusicCounters[1] >> myMusicWaveformSize[1])] + myDisplayImage[(getWaveform(1) ) + (myMusicCounters[1] >> myMusicWaveformSize[1])] +
myDisplayImage[(getWaveform(2) ) + (myMusicCounters[2] >> myMusicWaveformSize[2])]; myDisplayImage[(getWaveform(2) ) + (myMusicCounters[2] >> myMusicWaveformSize[2])];
result = uInt8(i); result = uInt8(i);
break; break;
} }
} }
return result; return result;
} }
else else
@ -263,44 +251,44 @@ uInt8 CartridgeCDF::peek(uInt16 address)
// Set the current bank to the first 4k bank // Set the current bank to the first 4k bank
bank(0); bank(0);
break; break;
case 0x0FF6: case 0x0FF6:
// Set the current bank to the second 4k bank // Set the current bank to the second 4k bank
bank(1); bank(1);
break; break;
case 0x0FF7: case 0x0FF7:
// Set the current bank to the third 4k bank // Set the current bank to the third 4k bank
bank(2); bank(2);
break; break;
case 0x0FF8: case 0x0FF8:
// Set the current bank to the fourth 4k bank // Set the current bank to the fourth 4k bank
bank(3); bank(3);
break; break;
case 0x0FF9: case 0x0FF9:
// Set the current bank to the fifth 4k bank // Set the current bank to the fifth 4k bank
bank(4); bank(4);
break; break;
case 0x0FFA: case 0x0FFA:
// Set the current bank to the sixth 4k bank // Set the current bank to the sixth 4k bank
bank(5); bank(5);
break; break;
case 0x0FFB: case 0x0FFB:
// Set the current bank to the last 4k bank // Set the current bank to the last 4k bank
bank(6); bank(6);
break; break;
default: default:
break; break;
} }
if(FAST_FETCH_ON && peekvalue == 0xA9) if(FAST_FETCH_ON && peekvalue == 0xA9)
myLDAimmediateOperandAddress = address + 1; myLDAimmediateOperandAddress = address + 1;
return peekvalue; return peekvalue;
} }
} }
@ -309,31 +297,31 @@ uInt8 CartridgeCDF::peek(uInt16 address)
bool CartridgeCDF::poke(uInt16 address, uInt8 value) bool CartridgeCDF::poke(uInt16 address, uInt8 value)
{ {
address &= 0x0FFF; address &= 0x0FFF;
if ((address >= 0x21) && (address <= 0x2B)) if ((address >= 0x21) && (address <= 0x2B))
{ {
// Get the index of the data fetcher that's being accessed // Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x0f; uInt32 index = address & 0x0f;
uInt32 pointer; uInt32 pointer;
uInt32 stream = address & 0x03; uInt32 stream = address & 0x03;
switch (index) switch (index)
{ {
case 0x00: // 0x20 AMPLITUDE - read register case 0x00: // 0x20 AMPLITUDE - read register
break; break;
case 0x01: // 0x21 SETMODE case 0x01: // 0x21 SETMODE
myMode = value; myMode = value;
break; break;
case 0x02: // 0x22 CALLFN case 0x02: // 0x22 CALLFN
callFunction(value); callFunction(value);
break; break;
case 0x03: // 0x23 RESERVED case 0x03: // 0x23 RESERVED
break; break;
case 0x04: // 0x24 DS0WRITE case 0x04: // 0x24 DS0WRITE
case 0x05: // 0x25 DS1WRITE case 0x05: // 0x25 DS1WRITE
case 0x06: // 0x26 DS2WRITE case 0x06: // 0x26 DS2WRITE
@ -343,13 +331,13 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
// //
// P = Pointer // P = Pointer
// F = Fractional // F = Fractional
pointer = getDatastreamPointer(stream); pointer = getDatastreamPointer(stream);
myDisplayImage[ pointer >> 20 ] = value; myDisplayImage[ pointer >> 20 ] = value;
pointer += 0x100000; // always increment by 1 when writing pointer += 0x100000; // always increment by 1 when writing
setDatastreamPointer(stream, pointer); setDatastreamPointer(stream, pointer);
break; break;
case 0x08: // 0x28 DS0PTR case 0x08: // 0x28 DS0PTR
case 0x09: // 0x29 DS1PTR case 0x09: // 0x29 DS1PTR
case 0x0A: // 0x2A DS2PTR case 0x0A: // 0x2A DS2PTR
@ -359,7 +347,7 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
// //
// P = Pointer // P = Pointer
// F = Fractional // F = Fractional
pointer = getDatastreamPointer(stream); pointer = getDatastreamPointer(stream);
pointer <<=8; pointer <<=8;
pointer &= 0xf0000000; pointer &= 0xf0000000;
@ -377,42 +365,42 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
// Set the current bank to the first 4k bank // Set the current bank to the first 4k bank
bank(0); bank(0);
break; break;
case 0x0FF6: case 0x0FF6:
// Set the current bank to the second 4k bank // Set the current bank to the second 4k bank
bank(1); bank(1);
break; break;
case 0x0FF7: case 0x0FF7:
// Set the current bank to the third 4k bank // Set the current bank to the third 4k bank
bank(2); bank(2);
break; break;
case 0x0FF8: case 0x0FF8:
// Set the current bank to the fourth 4k bank // Set the current bank to the fourth 4k bank
bank(3); bank(3);
break; break;
case 0x0FF9: case 0x0FF9:
// Set the current bank to the fifth 4k bank // Set the current bank to the fifth 4k bank
bank(4); bank(4);
break; break;
case 0x0FFA: case 0x0FFA:
// Set the current bank to the sixth 4k bank // Set the current bank to the sixth 4k bank
bank(5); bank(5);
break; break;
case 0x0FFB: case 0x0FFB:
// Set the current bank to the last 4k bank // Set the current bank to the last 4k bank
bank(6); bank(6);
break; break;
default: default:
break; break;
} }
} }
return false; return false;
} }
@ -420,14 +408,14 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
bool CartridgeCDF::bank(uInt16 bank) bool CartridgeCDF::bank(uInt16 bank)
{ {
if(bankLocked()) return false; if(bankLocked()) return false;
// Remember what bank we're in // Remember what bank we're in
myCurrentBank = bank; myCurrentBank = bank;
uInt16 offset = myCurrentBank << 12; uInt16 offset = myCurrentBank << 12;
// Setup the page access methods for the current bank // Setup the page access methods for the current bank
System::PageAccess access(this, System::PA_READ); System::PageAccess access(this, System::PA_READ);
// Map Program ROM image into the system // Map Program ROM image into the system
for(uInt32 address = 0x1040; address < 0x2000; for(uInt32 address = 0x1040; address < 0x2000;
address += (1 << System::PAGE_SHIFT)) address += (1 << System::PAGE_SHIFT))
@ -454,7 +442,7 @@ uInt16 CartridgeCDF::bankCount() const
bool CartridgeCDF::patch(uInt16 address, uInt8 value) bool CartridgeCDF::patch(uInt16 address, uInt8 value)
{ {
address &= 0x0FFF; address &= 0x0FFF;
// For now, we ignore attempts to patch the CDF address space // For now, we ignore attempts to patch the CDF address space
if(address >= 0x0040) if(address >= 0x0040)
{ {
@ -478,31 +466,30 @@ const uInt8* CartridgeCDF::getImage(int& size) const
uInt32 CartridgeCDF::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) uInt32 CartridgeCDF::thumbCallback(uInt8 function, uInt32 value1, uInt32 value2)
{ {
switch (function) switch (function)
{ {
case 0: case 0:
// _SetNote - set the note/frequency // _SetNote - set the note/frequency
myMusicFrequencies[value1] = value2; myMusicFrequencies[value1] = value2;
break; break;
// _ResetWave - reset counter, // _ResetWave - reset counter,
// used to make sure digital samples start from the beginning // used to make sure digital samples start from the beginning
case 1: case 1:
myMusicCounters[value1] = 0; myMusicCounters[value1] = 0;
break; break;
// _GetWavePtr - return the counter // _GetWavePtr - return the counter
case 2: case 2:
return myMusicCounters[value1]; return myMusicCounters[value1];
break; break;
// _SetWaveSize - set size of waveform buffer // _SetWaveSize - set size of waveform buffer
case 3: case 3:
myMusicWaveformSize[value1] = value2; myMusicWaveformSize[value1] = value2;
break; break;
} }
return 0; return 0;
} }
@ -513,13 +500,13 @@ bool CartridgeCDF::save(Serializer& out) const
try try
{ {
out.putString(name()); out.putString(name());
// Indicates which bank is currently active // Indicates which bank is currently active
out.putShort(myCurrentBank); out.putShort(myCurrentBank);
// Harmony RAM // Harmony RAM
out.putByteArray(myCDFRAM, 8192); out.putByteArray(myCDFRAM, 8192);
out.putInt(mySystemCycles); out.putInt(mySystemCycles);
out.putInt((uInt32)(myFractionalClocks * 100000000.0)); out.putInt((uInt32)(myFractionalClocks * 100000000.0));
out.putInt(myARMCycles); out.putInt(myARMCycles);
@ -529,7 +516,7 @@ bool CartridgeCDF::save(Serializer& out) const
cerr << "ERROR: CartridgeCDF::save" << endl; cerr << "ERROR: CartridgeCDF::save" << endl;
return false; return false;
} }
return true; return true;
} }
@ -540,17 +527,17 @@ bool CartridgeCDF::load(Serializer& in)
{ {
if(in.getString() != name()) if(in.getString() != name())
return false; return false;
// Indicates which bank is currently active // Indicates which bank is currently active
myCurrentBank = in.getShort(); myCurrentBank = in.getShort();
// Harmony RAM // Harmony RAM
in.getByteArray(myCDFRAM, 8192); in.getByteArray(myCDFRAM, 8192);
// Get system cycles and fractional clocks // Get system cycles and fractional clocks
mySystemCycles = (Int32)in.getInt(); mySystemCycles = (Int32)in.getInt();
myFractionalClocks = (double)in.getInt() / 100000000.0; myFractionalClocks = (double)in.getInt() / 100000000.0;
myARMCycles = (Int32)in.getInt(); myARMCycles = (Int32)in.getInt();
} }
catch(...) catch(...)
@ -558,23 +545,25 @@ bool CartridgeCDF::load(Serializer& in)
cerr << "ERROR: CartridgeCDF::load" << endl; cerr << "ERROR: CartridgeCDF::load" << endl;
return false; return false;
} }
// Now, go to the current bank // Now, go to the current bank
bank(myCurrentBank); bank(myCurrentBank);
return true; return true;
} }
uInt32 CartridgeCDF::getDatastreamPointer(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCDF::getDatastreamPointer(uInt8 index) const
{ {
// index &= 0x0f; // index &= 0x0f;
return myCDFRAM[DSxPTR + index*4 + 0] + // low byte return myCDFRAM[DSxPTR + index*4 + 0] + // low byte
(myCDFRAM[DSxPTR + index*4 + 1] << 8) + (myCDFRAM[DSxPTR + index*4 + 1] << 8) +
(myCDFRAM[DSxPTR + index*4 + 2] << 16) + (myCDFRAM[DSxPTR + index*4 + 2] << 16) +
(myCDFRAM[DSxPTR + index*4 + 3] << 24) ; // high byte (myCDFRAM[DSxPTR + index*4 + 3] << 24) ; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value) void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value)
{ {
// index &= 0x1f; // index &= 0x1f;
@ -584,15 +573,17 @@ void CartridgeCDF::setDatastreamPointer(uInt8 index, uInt32 value)
myCDFRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte myCDFRAM[DSxPTR + index*4 + 3] = (value >> 24) & 0xff; // high byte
} }
uInt32 CartridgeCDF::getDatastreamIncrement(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCDF::getDatastreamIncrement(uInt8 index) const
{ {
// index &= 0x1f; // index &= 0x1f;
return myCDFRAM[DSxINC + index*4 + 0] + // low byte return myCDFRAM[DSxINC + index*4 + 0] + // low byte
(myCDFRAM[DSxINC + index*4 + 1] << 8) + (myCDFRAM[DSxINC + index*4 + 1] << 8) +
(myCDFRAM[DSxINC + index*4 + 2] << 16) + (myCDFRAM[DSxINC + index*4 + 2] << 16) +
(myCDFRAM[DSxINC + index*4 + 3] << 24) ; // high byte (myCDFRAM[DSxINC + index*4 + 3] << 24) ; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeCDF::setDatastreamIncrement(uInt8 index, uInt32 value) void CartridgeCDF::setDatastreamIncrement(uInt8 index, uInt32 value)
{ {
// index &= 0x1f; // index &= 0x1f;
@ -602,41 +593,43 @@ void CartridgeCDF::setDatastreamIncrement(uInt8 index, uInt32 value)
myCDFRAM[DSxINC + index*4 + 3] = (value >> 24) & 0xff; // high byte myCDFRAM[DSxINC + index*4 + 3] = (value >> 24) & 0xff; // high byte
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCDF::getWaveform(uInt8 index) uInt32 CartridgeCDF::getWaveform(uInt8 index) const
{ {
// instead of 0, 1, 2, etc. this returned // instead of 0, 1, 2, etc. this returned
// 0x40000800 for 0 // 0x40000800 for 0
// 0x40000820 for 1 // 0x40000820 for 1
// 0x40000840 for 2 // 0x40000840 for 2
// ... // ...
// return myCDFRAM[WAVEFORM + index*4 + 0] + // low byte // return myCDFRAM[WAVEFORM + index*4 + 0] + // low byte
// (myCDFRAM[WAVEFORM + index*4 + 1] << 8) + // (myCDFRAM[WAVEFORM + index*4 + 1] << 8) +
// (myCDFRAM[WAVEFORM + index*4 + 2] << 16) + // (myCDFRAM[WAVEFORM + index*4 + 2] << 16) +
// (myCDFRAM[WAVEFORM + index*4 + 3] << 24) - // high byte // (myCDFRAM[WAVEFORM + index*4 + 3] << 24) - // high byte
// 0x40000800; // 0x40000800;
uInt32 result; uInt32 result;
result = myCDFRAM[WAVEFORM + index*4 + 0] + // low byte result = myCDFRAM[WAVEFORM + index*4 + 0] + // low byte
(myCDFRAM[WAVEFORM + index*4 + 1] << 8) + (myCDFRAM[WAVEFORM + index*4 + 1] << 8) +
(myCDFRAM[WAVEFORM + index*4 + 2] << 16) + (myCDFRAM[WAVEFORM + index*4 + 2] << 16) +
(myCDFRAM[WAVEFORM + index*4 + 3] << 24); (myCDFRAM[WAVEFORM + index*4 + 3] << 24);
result -= 0x40000800; result -= 0x40000800;
if (result >= 4096) if (result >= 4096)
result = 0; result = 0;
return result; return result;
} }
uInt32 CartridgeCDF::getWaveformSize(uInt8 index) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 CartridgeCDF::getWaveformSize(uInt8 index) const
{ {
return myMusicWaveformSize[index]; return myMusicWaveformSize[index];
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeCDF::readFromDatastream(uInt8 index) uInt8 CartridgeCDF::readFromDatastream(uInt8 index)
{ {
// Pointers are stored as: // Pointers are stored as:
@ -648,7 +641,7 @@ uInt8 CartridgeCDF::readFromDatastream(uInt8 index)
// P = Pointer // P = Pointer
// I = Increment // I = Increment
// F = Fractional // F = Fractional
uInt32 pointer = getDatastreamPointer(index); uInt32 pointer = getDatastreamPointer(index);
uInt16 increment = getDatastreamIncrement(index); uInt16 increment = getDatastreamIncrement(index);
uInt8 value = myDisplayImage[ pointer >> 20 ]; uInt8 value = myDisplayImage[ pointer >> 20 ];
@ -656,4 +649,3 @@ uInt8 CartridgeCDF::readFromDatastream(uInt8 index)
setDatastreamPointer(index, pointer); setDatastreamPointer(index, pointer);
return value; return value;
} }

488
src/emucore/CartCDF.hxx Executable file → Normal file
View File

@ -8,13 +8,11 @@
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa // SSSS ttt eeeee llll llll aaaaa
// //
// Copyright (c) 1995-2015 by Bradford W. Mott, Stephen Anthony // Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// and the Stella Team // and the Stella Team
// //
// See the file "License.txt" for information on usage and redistribution of // See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES. // this file, and for a DISCLAIMER OF ALL WARRANTIES.
//
// $Id: CartCDF.hxx 3131 2015-01-01 03:49:32Z stephena $
//============================================================================ //============================================================================
#ifndef CARTRIDGE_CDF_HXX #ifndef CARTRIDGE_CDF_HXX
@ -22,264 +20,260 @@
class System; class System;
#ifdef THUMB_SUPPORT #ifdef THUMB_SUPPORT
class Thumbulator; class Thumbulator;
#endif #endif
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
#include "CartCDFWidget.hxx" #include "CartCDFWidget.hxx"
#endif #endif
#include "bspf.hxx" #include "bspf.hxx"
#include "Cart.hxx" #include "Cart.hxx"
/** /**
Cartridge class used for CDF. Cartridge class used for CDF.
THIS NEEDS TO BE UPDATED THIS NEEDS TO BE UPDATED
There are seven 4K program banks, a 4K Display Data RAM, There are seven 4K program banks, a 4K Display Data RAM,
1K C Varaible and Stack, and the CDF chip. 1K C Varaible and Stack, and the CDF chip.
CDF chip access is mapped to $1000 - $103F. CDF chip access is mapped to $1000 - $103F.
@author Darrell Spice Jr, Chris Walton, Fred Quimby, Stephen Anthony, Bradford W. Mott Authors: Darrell Spice Jr, Chris Walton, Fred Quimby,
@version $Id: CartCDF.hxx 3131 2015-01-01 03:49:32Z stephena $ Stephen Anthony, Bradford W. Mott
*/ */
class CartridgeCDF : public Cartridge class CartridgeCDF : public Cartridge
{ {
friend class CartridgeCDFWidget; friend class CartridgeCDFWidget;
friend class CartridgeRamCDFWidget; friend class CartridgeRamCDFWidget;
public:
/**
Create a new cartridge using the specified image
@param image Pointer to the ROM image
@param size The size of the ROM image
@param settings A reference to the various settings (read-only)
*/
CartridgeCDF(const uInt8* image, uInt32 size, const Settings& settings);
/**
Destructor
*/
virtual ~CartridgeCDF();
public:
/**
Reset device to its power-on state
*/
void reset() override;
/**
Notification method invoked by the system when the console type
has changed. We need this to inform the Thumbulator that the
timing has changed.
@param timing Enum representing the new console type
*/
void consoleChanged(ConsoleTiming timing) override;
/** public:
Notification method invoked by the system right before the /**
system resets its cycle counter to zero. It may be necessary Create a new cartridge using the specified image
to override this method for devices that remember cycle counts.
*/ @param image Pointer to the ROM image
void systemCyclesReset() override; @param size The size of the ROM image
@param settings A reference to the various settings (read-only)
/** */
Install cartridge in the specified system. Invoked by the system CartridgeCDF(const uInt8* image, uInt32 size, const Settings& settings);
when the cartridge is attached to it. virtual ~CartridgeCDF() = default;
@param system The system the device should install itself in public:
*/ /**
void install(System& system) override; Reset device to its power-on state
*/
/** void reset() override;
Install pages for the specified bank in the system.
/**
@param bank The bank that should be installed in the system Notification method invoked by the system when the console type
*/ has changed. We need this to inform the Thumbulator that the
bool bank(uInt16 bank) override; timing has changed.
/** @param timing Enum representing the new console type
Get the current bank. */
*/ void consoleChanged(ConsoleTiming timing) override;
uInt16 getBank() const override;
/**
/** Notification method invoked by the system right before the
Query the number of banks supported by the cartridge. system resets its cycle counter to zero. It may be necessary
*/ to override this method for devices that remember cycle counts.
uInt16 bankCount() const override; */
void systemCyclesReset() override;
/**
Patch the cartridge ROM. /**
Install cartridge in the specified system. Invoked by the system
@param address The ROM address to patch when the cartridge is attached to it.
@param value The value to place into the address
@return Success or failure of the patch operation @param system The system the device should install itself in
*/ */
bool patch(uInt16 address, uInt8 value) override; void install(System& system) override;
/** /**
Access the internal ROM image for this cartridge. Install pages for the specified bank in the system.
@param size Set to the size of the internal ROM image data @param bank The bank that should be installed in the system
@return A pointer to the internal ROM image data */
*/ bool bank(uInt16 bank) override;
const uInt8* getImage(int& size) const override;
/**
/** Get the current bank.
Save the current state of this cart to the given Serializer. */
uInt16 getBank() const override;
@param out The Serializer object to use
@return False on any errors, else true /**
*/ Query the number of banks supported by the cartridge.
bool save(Serializer& out) const override; */
uInt16 bankCount() const override;
/**
Load the current state of this cart from the given Serializer. /**
Patch the cartridge ROM.
@param in The Serializer object to use
@return False on any errors, else true @param address The ROM address to patch
*/ @param value The value to place into the address
bool load(Serializer& in) override; @return Success or failure of the patch operation
*/
/** bool patch(uInt16 address, uInt8 value) override;
Get a descriptor for the device name (used in error checking).
/**
@return The name of the object Access the internal ROM image for this cartridge.
*/
string name() const override { return "CartridgeCDF"; } @param size Set to the size of the internal ROM image data
@return A pointer to the internal ROM image data
// uInt8 busOverdrive(uInt16 address) override; */
const uInt8* getImage(int& size) const override;
/**
Used for Thumbulator to pass values back to the cartridge /**
*/ Save the current state of this cart to the given Serializer.
uInt32 thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) override;
@param out The Serializer object to use
@return False on any errors, else true
*/
bool save(Serializer& out) const override;
/**
Load the current state of this cart from the given Serializer.
@param in The Serializer object to use
@return False on any errors, else true
*/
bool load(Serializer& in) override;
/**
Get a descriptor for the device name (used in error checking).
@return The name of the object
*/
string name() const override { return "CartridgeCDF"; }
// uInt8 busOverdrive(uInt16 address) override;
/**
Used for Thumbulator to pass values back to the cartridge
*/
uInt32 thumbCallback(uInt8 function, uInt32 value1, uInt32 value2) override;
#ifdef DEBUGGER_SUPPORT #ifdef DEBUGGER_SUPPORT
/** /**
Get debugger widget responsible for accessing the inner workings Get debugger widget responsible for accessing the inner workings
of the cart. of the cart.
*/ */
CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont, CartDebugWidget* debugWidget(GuiObject* boss, const GUI::Font& lfont,
const GUI::Font& nfont, int x, int y, int w, int h) override const GUI::Font& nfont, int x, int y, int w, int h) override
{ {
return new CartridgeCDFWidget(boss, lfont, nfont, x, y, w, h, *this); return new CartridgeCDFWidget(boss, lfont, nfont, x, y, w, h, *this);
} }
#endif #endif
public: public:
/** /**
Get the byte at the specified address. Get the byte at the specified address.
@return The byte at the specified address @return The byte at the specified address
*/ */
uInt8 peek(uInt16 address) override; uInt8 peek(uInt16 address) override;
/** /**
Change the byte at the specified address to the given value Change the byte at the specified address to the given value
@param address The address where the value should be stored @param address The address where the value should be stored
@param value The value to be stored at the address @param value The value to be stored at the address
@return True if the poke changed the device address space, else false @return True if the poke changed the device address space, else false
*/ */
bool poke(uInt16 address, uInt8 value) override; bool poke(uInt16 address, uInt8 value) override;
private: private:
/** /**
Sets the initial state of the DPC pointers and RAM Sets the initial state of the DPC pointers and RAM
*/ */
void setInitialState(); void setInitialState();
/** /**
Updates any data fetchers in music mode based on the number of Updates any data fetchers in music mode based on the number of
CPU cycles which have passed since the last update. CPU cycles which have passed since the last update.
*/ */
void updateMusicModeDataFetchers(); void updateMusicModeDataFetchers();
/** /**
Call Special Functions Call Special Functions
*/ */
void callFunction(uInt8 value); void callFunction(uInt8 value);
uInt32 getDatastreamPointer(uInt8 index); uInt32 getDatastreamPointer(uInt8 index) const;
void setDatastreamPointer(uInt8 index, uInt32 value); void setDatastreamPointer(uInt8 index, uInt32 value);
uInt32 getDatastreamIncrement(uInt8 index); uInt32 getDatastreamIncrement(uInt8 index) const;
void setDatastreamIncrement(uInt8 index, uInt32 value); void setDatastreamIncrement(uInt8 index, uInt32 value);
uInt8 readFromDatastream(uInt8 index); uInt8 readFromDatastream(uInt8 index);
uInt32 getWaveform(uInt8 index); uInt32 getWaveform(uInt8 index) const;
uInt32 getWaveformSize(uInt8 index); uInt32 getWaveformSize(uInt8 index) const;
private: private:
// The 32K ROM image of the cartridge // The 32K ROM image of the cartridge
uInt8 myImage[32768]; uInt8 myImage[32768];
// Pointer to the 28K program ROM image of the cartridge // Pointer to the 28K program ROM image of the cartridge
uInt8* myProgramImage; uInt8* myProgramImage;
// Pointer to the 4K display ROM image of the cartridge // Pointer to the 4K display ROM image of the cartridge
uInt8* myDisplayImage; uInt8* myDisplayImage;
// Pointer to the 2K CDF driver image in RAM // Pointer to the 2K CDF driver image in RAM
uInt8* myBusDriverImage; uInt8* myBusDriverImage;
// The CDF 8k RAM image, used as: // The CDF 8k RAM image, used as:
// $0000 - 2K CDF driver // $0000 - 2K CDF driver
// $0800 - 4K Display Data // $0800 - 4K Display Data
// $1800 - 2K C Variable & Stack // $1800 - 2K C Variable & Stack
uInt8 myCDFRAM[8192]; uInt8 myCDFRAM[8192];
#ifdef THUMB_SUPPORT #ifdef THUMB_SUPPORT
// Pointer to the Thumb ARM emulator object // Pointer to the Thumb ARM emulator object
unique_ptr<Thumbulator> myThumbEmulator; unique_ptr<Thumbulator> myThumbEmulator;
#endif #endif
// Indicates which bank is currently active // Indicates which bank is currently active
uInt16 myCurrentBank; uInt16 myCurrentBank;
// System cycle count when the last update to music data fetchers occurred // System cycle count when the last update to music data fetchers occurred
Int32 mySystemCycles; Int32 mySystemCycles;
Int32 myARMCycles; Int32 myARMCycles;
uInt8 mySetAddress; uInt8 mySetAddress;
// The music mode counters // The music mode counters
uInt32 myMusicCounters[3]; uInt32 myMusicCounters[3];
// The music frequency // The music frequency
uInt32 myMusicFrequencies[3]; uInt32 myMusicFrequencies[3];
// The music waveform sizes // The music waveform sizes
uInt8 myMusicWaveformSize[3]; uInt8 myMusicWaveformSize[3];
// Fractional DPC music OSC clocks unused during the last update // Fractional DPC music OSC clocks unused during the last update
double myFractionalClocks; double myFractionalClocks;
// Controls mode, lower nybble sets Fast Fetch, upper nybble sets audio // Controls mode, lower nybble sets Fast Fetch, upper nybble sets audio
// -0 = Fast Fetch ON // -0 = Fast Fetch ON
// -F = Fast Fetch OFF // -F = Fast Fetch OFF
// 0- = Packed Digital Sample // 0- = Packed Digital Sample
// F- = 3 Voice Music // F- = 3 Voice Music
uInt8 myMode; uInt8 myMode;
// set to address of #value if last byte peeked was A9 (LDA #) // set to address of #value if last byte peeked was A9 (LDA #)
uInt16 myLDAimmediateOperandAddress; uInt16 myLDAimmediateOperandAddress;
TIA* myTIA; TIA* myTIA;
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported
CartridgeCDF() = delete; CartridgeCDF() = delete;
CartridgeCDF(const CartridgeCDF&) = delete; CartridgeCDF(const CartridgeCDF&) = delete;
CartridgeCDF(CartridgeCDF&&) = delete; CartridgeCDF(CartridgeCDF&&) = delete;
CartridgeCDF& operator=(const CartridgeCDF&) = delete; CartridgeCDF& operator=(const CartridgeCDF&) = delete;
CartridgeCDF& operator=(CartridgeCDF&&) = delete; CartridgeCDF& operator=(CartridgeCDF&&) = delete;
}; };
#endif #endif

View File

@ -85,6 +85,7 @@ string Thumbulator::run()
return statusMsg.str(); return statusMsg.str();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::setConsoleTiming(ConsoleTiming timing) void Thumbulator::setConsoleTiming(ConsoleTiming timing)
{ {
// this sets how many ticks of the Harmony/Melody clock // this sets how many ticks of the Harmony/Melody clock
@ -92,7 +93,7 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing)
constexpr double NTSC = 70.0 / 1.193182; // NTSC 6507 clock rate constexpr double NTSC = 70.0 / 1.193182; // NTSC 6507 clock rate
constexpr double PAL = 70.0 / 1.182298; // PAL 6507 clock rate constexpr double PAL = 70.0 / 1.182298; // PAL 6507 clock rate
constexpr double SECAM = 70.0 / 1.187500; // SECAM 6507 clock rate constexpr double SECAM = 70.0 / 1.187500; // SECAM 6507 clock rate
switch (timing) switch (timing)
{ {
case ConsoleTiming::ntsc: timing_factor = NTSC; break; case ConsoleTiming::ntsc: timing_factor = NTSC; break;
@ -104,22 +105,15 @@ void Thumbulator::setConsoleTiming(ConsoleTiming timing)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Thumbulator::updateTimer(uInt32 cycles) void Thumbulator::updateTimer(uInt32 cycles)
{ {
double increment;
increment = cycles * timing_factor;
if (T1TCR & 1) // bit 0 controls timer on/off if (T1TCR & 1) // bit 0 controls timer on/off
{ T1TC += uInt32(cycles * timing_factor);
T1TC += uInt32(increment);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Thumbulator::run(uInt32 cycles) string Thumbulator::run(uInt32 cycles)
{ {
updateTimer(cycles); updateTimer(cycles);
return this->run(); return run();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -230,23 +224,23 @@ void Thumbulator::write16(uInt32 addr, uInt32 data)
{ {
if((addr > 0x40001fff) && (addr < 0x50000000)) if((addr > 0x40001fff) && (addr < 0x50000000))
fatalError("write16", addr, "abort - out of range"); fatalError("write16", addr, "abort - out of range");
switch(configuration) switch(configuration)
{ {
// this protects 2K Harmony/Melody Drivers // this protects 2K Harmony/Melody Drivers
// Initial section of driver is the bootstrap which copies the driver // Initial section of driver is the bootstrap which copies the driver
// from ROM to RAM, so it can safely be used by the custom ARM code // from ROM to RAM, so it can safely be used by the custom ARM code
// as additional RAM // as additional RAM
case ConfigureFor::BUS: case ConfigureFor::BUS:
case ConfigureFor::CDF: case ConfigureFor::CDF:
if((addr > 0x40000028) && (addr < 0x40000800)) if((addr > 0x40000028) && (addr < 0x40000800))
fatalError("write16", addr, "to bankswitch code area"); fatalError("write16", addr, "to bankswitch code area");
break; break;
// this protects 3K Harmony/Melody Drivers // this protects 3K Harmony/Melody Drivers
// Initial section of driver is the bootstrap which copies the driver // Initial section of driver is the bootstrap which copies the driver
// from ROM to RAM, so it can safely be used by the custom ARM code // from ROM to RAM, so it can safely be used by the custom ARM code
// as additional RAM // as additional RAM
case ConfigureFor::DPCplus: case ConfigureFor::DPCplus:
if((addr > 0x40000028) && (addr < 0x40000c00)) if((addr > 0x40000028) && (addr < 0x40000c00))
fatalError("write16", addr, "to bankswitch code area"); fatalError("write16", addr, "to bankswitch code area");
@ -299,11 +293,11 @@ void Thumbulator::write32(uInt32 addr, uInt32 data)
case 0xE0000000: case 0xE0000000:
DO_DISS(statusMsg << "uart: [" << char(data&0xFF) << "]" << endl); DO_DISS(statusMsg << "uart: [" << char(data&0xFF) << "]" << endl);
break; break;
case 0xE0008004: // T1TCR - Timer 1 Control Register case 0xE0008004: // T1TCR - Timer 1 Control Register
T1TCR = data; T1TCR = data;
break; break;
case 0xE0008008: // T1TC - Timer 1 Counter case 0xE0008008: // T1TC - Timer 1 Counter
T1TC = data; T1TC = data;
break; break;
@ -423,11 +417,11 @@ uInt32 Thumbulator::read32(uInt32 addr)
case 0xE0008004: // T1TCR - Timer 1 Control Register case 0xE0008004: // T1TCR - Timer 1 Control Register
data = T1TCR; data = T1TCR;
return data; return data;
case 0xE0008008: // T1TC - Timer 1 Counter case 0xE0008008: // T1TC - Timer 1 Counter
data = T1TC; data = T1TC;
return data; return data;
case 0xE000E010: case 0xE000E010:
data = systick_ctrl; data = systick_ctrl;
systick_ctrl &= (~0x00010000); systick_ctrl &= (~0x00010000);
@ -1076,9 +1070,9 @@ int Thumbulator::execute()
// branch to even address denotes 32 bit ARM code, which the Thumbulator // branch to even address denotes 32 bit ARM code, which the Thumbulator
// class does not support. So capture relavent information and hand it // class does not support. So capture relavent information and hand it
// off to the Cartridge class for it to handle. // off to the Cartridge class for it to handle.
bool handled = false; bool handled = false;
switch(configuration) switch(configuration)
{ {
case ConfigureFor::BUS: case ConfigureFor::BUS:
@ -1097,13 +1091,14 @@ int Thumbulator::execute()
// _SetWaveSize: // _SetWaveSize:
// ldr r4, =WaveSizeStore // ldr r4, =WaveSizeStore
// bx r4 // bx instruction at 0x000006ee // bx r4 // bx instruction at 0x000006ee
// address to test for is + 4 due to pipelining // address to test for is + 4 due to pipelining
#define BUS_SetNote (0x000006e2 + 4)
#define BUS_ResetWave (0x000006e6 + 4) #define BUS_SetNote (0x000006e2 + 4)
#define BUS_GetWavePtr (0x000006ea + 4) #define BUS_ResetWave (0x000006e6 + 4)
#define BUS_SetWaveSize (0x000006ee + 4) #define BUS_GetWavePtr (0x000006ea + 4)
#define BUS_SetWaveSize (0x000006ee + 4)
if (pc == BUS_SetNote) if (pc == BUS_SetNote)
{ {
myCartridge->thumbCallback(0, read_register(2), read_register(3)); myCartridge->thumbCallback(0, read_register(2), read_register(3));
@ -1130,22 +1125,23 @@ int Thumbulator::execute()
} }
else else
{ {
// just for testing #if 0 // uncomment this for testing
uInt32 r0 = read_register(0); uInt32 r0 = read_register(0);
uInt32 r1 = read_register(1); uInt32 r1 = read_register(1);
uInt32 r2 = read_register(2); uInt32 r2 = read_register(2);
uInt32 r3 = read_register(3); uInt32 r3 = read_register(3);
uInt32 r4 = read_register(4); uInt32 r4 = read_register(4);
myCartridge->thumbCallback(255,0,0); #endif
myCartridge->thumbCallback(255, 0, 0);
} }
break; break;
case ConfigureFor::DPCplus: case ConfigureFor::DPCplus:
// no 32-bit subroutines in DPC+ // no 32-bit subroutines in DPC+
break; break;
} }
if (handled) if (handled)
{ {
rc = read_register(14); // lr rc = read_register(14); // lr
@ -1154,7 +1150,7 @@ int Thumbulator::execute()
write_register(15, rc); write_register(15, rc);
return 0; return 0;
} }
return 1; return 1;
} }
} }
@ -2206,20 +2202,20 @@ int Thumbulator::reset()
switch(configuration) switch(configuration)
{ {
// future 2K Harmony/Melody drivers will most likely use these settings // future 2K Harmony/Melody drivers will most likely use these settings
case ConfigureFor::BUS: case ConfigureFor::BUS:
case ConfigureFor::CDF: case ConfigureFor::CDF:
reg_norm[14] = 0x00000800; // Link Register reg_norm[14] = 0x00000800; // Link Register
reg_norm[15] = 0x0000080B; // Program Counter reg_norm[15] = 0x0000080B; // Program Counter
break; break;
// future 3K Harmony/Melody drivers will most likely use these settings // future 3K Harmony/Melody drivers will most likely use these settings
case ConfigureFor::DPCplus: case ConfigureFor::DPCplus:
reg_norm[14] = 0x00000C00; // Link Register reg_norm[14] = 0x00000C00; // Link Register
reg_norm[15] = 0x00000C0B; // Program Counter reg_norm[15] = 0x00000C0B; // Program Counter
break; break;
} }
cpsr = mamcr = 0; cpsr = mamcr = 0;
handler_mode = false; handler_mode = false;

View File

@ -52,7 +52,7 @@ class Thumbulator
CDF, // cartridges of type CDF CDF, // cartridges of type CDF
DPCplus // cartridges of type DPC+ DPCplus // cartridges of type DPC+
}; };
Thumbulator(const uInt16* rom, uInt16* ram, bool traponfatal, Thumbulator(const uInt16* rom, uInt16* ram, bool traponfatal,
Thumbulator::ConfigureFor configurefor, Cartridge* cartridge); Thumbulator::ConfigureFor configurefor, Cartridge* cartridge);
@ -80,8 +80,13 @@ 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; } static void trapFatalErrors(bool enable) { trapOnFatal = enable; }
void setConsoleTiming(ConsoleTiming timing); /**
Inform the Thumbulator class about the console currently in use,
which is used to accurately determine how many 6507 cycles have
passed while ARM code is being executed.
*/
void setConsoleTiming(ConsoleTiming timing);
private: private:
uInt32 read_register(uInt32 reg); uInt32 read_register(uInt32 reg);
@ -121,7 +126,7 @@ class Thumbulator
bool handler_mode; bool handler_mode;
uInt32 systick_ctrl, systick_reload, systick_count, systick_calibrate; uInt32 systick_ctrl, systick_reload, systick_count, systick_calibrate;
uInt64 instructions, fetches, reads, writes, systick_ints; uInt64 instructions, fetches, reads, writes, systick_ints;
// 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:
// http://www.nxp.com/documents/user_manual/UM10161.pdf // http://www.nxp.com/documents/user_manual/UM10161.pdf
@ -132,9 +137,9 @@ class Thumbulator
ostringstream statusMsg; ostringstream statusMsg;
static bool trapOnFatal; static bool trapOnFatal;
ConfigureFor configuration; ConfigureFor configuration;
Cartridge* myCartridge; Cartridge* myCartridge;
private: private:

View File

@ -13,6 +13,8 @@ MODULE_OBJS := \
src/emucore/Cart4K.o \ src/emucore/Cart4K.o \
src/emucore/Cart4KSC.o \ src/emucore/Cart4KSC.o \
src/emucore/CartAR.o \ src/emucore/CartAR.o \
src/emucore/CartBUS.o \
src/emucore/CartCDF.o \
src/emucore/CartCM.o \ src/emucore/CartCM.o \
src/emucore/CartCTY.o \ src/emucore/CartCTY.o \
src/emucore/CartCV.o \ src/emucore/CartCV.o \