Merge branch 'SpiceWare-master'

This commit is contained in:
Stephen Anthony 2017-05-07 17:42:41 -02:30
commit 1cb83f4a68
8 changed files with 431 additions and 267 deletions

View File

@ -33,8 +33,8 @@ CartridgeBUSWidget::CartridgeBUSWidget(
info << "BUS Stuffing cartridge\n" info << "BUS Stuffing cartridge\n"
<< "32K ROM, seven 4K banks are accessible to 2600\n" << "32K ROM, seven 4K banks are accessible to 2600\n"
<< "8K BUS RAM\n" << "8K BUS RAM\n"
<< "BUS registers accessible @ $F000 - $F03F\n" << "BUS registers accessible @ $FFEE - $FFF3\n"
<< "Banks accessible at hotspots $FFF5 to $FFFB\n" << "Banks accessible at hotspots $FFFF to $FFFB\n"
<< "Startup bank = " << cart.myStartBank << "\n"; << "Startup bank = " << cart.myStartBank << "\n";
#if 0 #if 0
@ -49,7 +49,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
#endif #endif
int xpos = 10, int xpos = 10,
ypos = addBaseInformation(size, "AtariAge", info.str()) + ypos = addBaseInformation(size, "AtariAge", info.str(), 4) +
myLineHeight; myLineHeight;
VariantList items; VariantList items;
@ -70,28 +70,57 @@ CartridgeBUSWidget::CartridgeBUSWidget(
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; #define DS_X 30
xpos = DS_X;
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, 4, 6, 32, Common::Base::F_16_3_2); myDatastreamPointers = new DataGridWidget(boss, _nfont, DS_X, 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);
myDatastreamPointers2 = new DataGridWidget(boss, _nfont, DS_X + myDatastreamPointers->getWidth() * 3 / 4, ypos+myLineHeight-2 + 4*myLineHeight, 1, 2, 6, 32, Common::Base::F_16_3_2);
myDatastreamPointers2->setTarget(this);
myDatastreamPointers2->setEditable(false);
uInt32 row;
for(row = 0; row < 4; ++row)
{
myDatastreamLabels[row] =
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
ypos+myLineHeight-2 + row*myLineHeight + 2,
myFontWidth*2, myFontHeight, "", kTextAlignLeft);
myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2));
}
lwidth = _font.getStringWidth("Write Data (stream 16)");
myDatastreamLabels[4] =
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
ypos+myLineHeight-2 + 4*myLineHeight + 2,
lwidth, myFontHeight, "Write Data (stream 16)", kTextAlignLeft);
myDatastreamLabels[5] =
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
ypos+myLineHeight-2 + 5*myLineHeight + 2,
lwidth, myFontHeight, "Jump Data (stream 17)", kTextAlignLeft);
// Datastream Increments // Datastream Increments
xpos = 0 + myDatastreamPointers->getWidth(); xpos = DS_X + myDatastreamPointers->getWidth() + 20;
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);
myDatastreamIncrements2 = new DataGridWidget(boss, _nfont, xpos, ypos+myLineHeight-2 + 4*myLineHeight, 1, 2, 5, 32, Common::Base::F_16_2_2);
myDatastreamIncrements2->setTarget(this);
myDatastreamIncrements2->setEditable(false);
// Datastream Maps // Datastream Maps
xpos = 0; ypos += myLineHeight*5 + 4; xpos = 0; ypos += myLineHeight*7 + 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);
@ -100,7 +129,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
// 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,
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);
@ -110,7 +139,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
// 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);
@ -120,17 +149,26 @@ CartridgeBUSWidget::CartridgeBUSWidget(
// 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);
int xpossp = xpos + myMusicWaveforms->getWidth() + 20;
int lwidth2 = _font.getStringWidth("Sample Pointer ");
new StaticTextWidget(boss, _font, xpossp, ypos, lwidth2,
myFontHeight, "Sample Pointer ", kTextAlignLeft);
mySamplePointer = new DataGridWidget(boss, _nfont, xpossp + lwidth2, ypos-2, 1, 1, 8, 32, Common::Base::F_16_8);
mySamplePointer->setTarget(this);
mySamplePointer->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);
@ -138,15 +176,15 @@ CartridgeBUSWidget::CartridgeBUSWidget(
myMusicWaveformSizes->setEditable(false); myMusicWaveformSizes->setEditable(false);
// BUS stuff and ZP STY flags // BUS stuff and Digital Audio 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");
myBusOverdrive->setTarget(this); myBusOverdrive->setTarget(this);
myBusOverdrive->setEditable(false); myBusOverdrive->setEditable(false);
xpos = _font.getStringWidth("CHECKBOX BUS Overdrive enabled");
myZPSTY = new CheckboxWidget(boss, _font, xpos, ypos, "Zero Page STY"); myDigitalSample = new CheckboxWidget(boss, _font, xpossp, ypos, "Digital Sample mode");
myZPSTY->setTarget(this); myDigitalSample->setTarget(this);
myZPSTY->setEditable(false); myDigitalSample->setEditable(false);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -162,8 +200,9 @@ void CartridgeBUSWidget::saveOldState()
myOldState.mwaves.clear(); myOldState.mwaves.clear();
myOldState.mwavesizes.clear(); myOldState.mwavesizes.clear();
myOldState.internalram.clear(); myOldState.internalram.clear();
myOldState.samplepointer.clear();
for(uInt32 i = 0; i < 16; i++) for(uInt32 i = 0; i < 18; i++)
{ {
// Pointers are stored as: // Pointers are stored as:
// PPPFF--- // PPPFF---
@ -176,13 +215,21 @@ void CartridgeBUSWidget::saveOldState()
// 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)); if (i < 16)
myOldState.datastreamincrements.push_back(myCart.getDatastreamIncrement(i));
else
myOldState.datastreamincrements.push_back(0x100);
} }
for(uInt32 i = 0; i < 40; i++) for(uInt32 i = 0; i < 37; i++) // only 37 map values
{ {
myOldState.addressmaps.push_back(myCart.getAddressMap(i)); myOldState.addressmaps.push_back(myCart.getAddressMap(i));
} }
for(uInt32 i = 37; i < 40; i++) // but need 40 for the grid
{
myOldState.addressmaps.push_back(0);
}
for(uInt32 i = 0; i < 3; ++i) for(uInt32 i = 0; i < 3; ++i)
{ {
@ -198,6 +245,8 @@ void CartridgeBUSWidget::saveOldState()
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]);
myOldState.samplepointer.push_back(myCart.getSample());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -228,7 +277,16 @@ void CartridgeBUSWidget::loadConfig()
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();
for(int i = 16; i < 18; ++i)
{
Int32 pointervalue = myCart.getDatastreamPointer(i) >> 12;
alist.push_back(0); vlist.push_back(pointervalue);
changed.push_back(pointervalue != myOldState.datastreampointers[i]);
}
myDatastreamPointers2->setList(alist, vlist, changed);
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)
{ {
@ -237,14 +295,29 @@ void CartridgeBUSWidget::loadConfig()
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();
for(int i = 16; i < 18; ++i)
{
Int32 incrementvalue = 0x100;
alist.push_back(0); vlist.push_back(incrementvalue);
changed.push_back(incrementvalue != myOldState.datastreamincrements[i]);
}
myDatastreamIncrements2->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 < 37; ++i) // only 37 map values
{ {
Int32 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]);
} }
for(int i = 37; i < 40; ++i) // but need 40 for the grid
{
Int32 mapvalue = 0;
alist.push_back(0); vlist.push_back(mapvalue);
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();
@ -279,8 +352,26 @@ void CartridgeBUSWidget::loadConfig()
} }
myMusicWaveformSizes->setList(alist, vlist, changed); myMusicWaveformSizes->setList(alist, vlist, changed);
// myBusOverdrive->setState(myCart.getBusStuffFlag()); alist.clear(); vlist.clear(); changed.clear();
// myZPSTY->setState(myCart.mySTYZeroPage); alist.push_back(0); vlist.push_back(myCart.getSample());
changed.push_back((myCart.getSample()) != uInt32(myOldState.samplepointer[0]));
mySamplePointer->setList(alist, vlist, changed);
myBusOverdrive->setState((myCart.myMode & 0x0f) == 0);
myDigitalSample->setState((myCart.myMode & 0xf0) == 0);
if ((myCart.myMode & 0xf0) == 0)
{
myMusicWaveforms->setCrossed(true);
myMusicWaveformSizes->setCrossed(true);
mySamplePointer->setCrossed(false);
}
else
{
myMusicWaveforms->setCrossed(false);
myMusicWaveformSizes->setCrossed(false);
mySamplePointer->setCrossed(true);
}
CartDebugWidget::loadConfig(); CartDebugWidget::loadConfig();
} }

View File

@ -45,6 +45,7 @@ class CartridgeBUSWidget : public CartDebugWidget
IntArray mfreqs; IntArray mfreqs;
IntArray mwaves; IntArray mwaves;
IntArray mwavesizes; IntArray mwavesizes;
IntArray samplepointer;
uInt32 random; uInt32 random;
ByteArray internalram; ByteArray internalram;
}; };
@ -54,13 +55,17 @@ class CartridgeBUSWidget : public CartDebugWidget
DataGridWidget* myDatastreamPointers; DataGridWidget* myDatastreamPointers;
DataGridWidget* myDatastreamIncrements; DataGridWidget* myDatastreamIncrements;
DataGridWidget* myDatastreamPointers2;
DataGridWidget* myDatastreamIncrements2;
DataGridWidget* myAddressMaps; DataGridWidget* myAddressMaps;
DataGridWidget* myMusicCounters; DataGridWidget* myMusicCounters;
DataGridWidget* myMusicFrequencies; DataGridWidget* myMusicFrequencies;
DataGridWidget* myMusicWaveforms; DataGridWidget* myMusicWaveforms;
DataGridWidget* myMusicWaveformSizes; DataGridWidget* myMusicWaveformSizes;
DataGridWidget* mySamplePointer;
StaticTextWidget* myDatastreamLabels[6];
CheckboxWidget* myBusOverdrive; CheckboxWidget* myBusOverdrive;
CheckboxWidget* myZPSTY; CheckboxWidget* myDigitalSample;
CartState myOldState; CartState myOldState;
enum { kBankChanged = 'bkCH' }; enum { kBankChanged = 'bkCH' };

View File

@ -96,16 +96,14 @@ CartridgeCDFWidget::CartridgeCDFWidget(
myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2)); myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2));
} }
lwidth = _font.getStringWidth("Write Data (stream 20)"); lwidth = _font.getStringWidth("Write Data (stream 20)");
myDatastreamLabels[row] = myDatastreamLabels[8] =
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "), new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
ypos+myLineHeight-2 + 8*myLineHeight + 2, ypos+myLineHeight-2 + 8*myLineHeight + 2,
lwidth, myFontHeight, "Write Data (stream 20)", kTextAlignLeft); lwidth, myFontHeight, "Write Data (stream 20)", kTextAlignLeft);
// myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2)); myDatastreamLabels[9] =
myDatastreamLabels[row] =
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "), new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
ypos+myLineHeight-2 + 9*myLineHeight + 2, ypos+myLineHeight-2 + 9*myLineHeight + 2,
lwidth, myFontHeight, "Jump Data (stream 21)", kTextAlignLeft); lwidth, myFontHeight, "Jump Data (stream 21)", kTextAlignLeft);
// myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2));
// Datastream Increments // Datastream Increments
xpos = DS_X + myDatastreamPointers->getWidth() + 20; xpos = DS_X + myDatastreamPointers->getWidth() + 20;

View File

@ -65,7 +65,6 @@ class CartridgeCDFWidget : public CartDebugWidget
DataGridWidget* mySamplePointer; DataGridWidget* mySamplePointer;
StaticTextWidget* myDatastreamLabels[10]; StaticTextWidget* myDatastreamLabels[10];
// done differently than in DPC+, need to rethink debugger support
CheckboxWidget* myFastFetch; CheckboxWidget* myFastFetch;
CheckboxWidget* myDigitalSample; CheckboxWidget* myDigitalSample;
CartState myOldState; CartState myOldState;

View File

@ -27,12 +27,15 @@
#include "CartBUS.hxx" #include "CartBUS.hxx"
// Location of data within the RAM copy of the BUS Driver. // Location of data within the RAM copy of the BUS Driver.
#define DSxPTR 0x06E0 #define DSxPTR 0x06D8
#define DSxINC 0x0720 #define DSxINC 0x0720
#define DSMAPS 0x0760 #define DSMAPS 0x0760
#define WAVEFORM 0x07F4 #define WAVEFORM 0x07F4
#define DSRAM 0x0800 #define DSRAM 0x0800
#define COMMSTREAM 0x10
#define JUMPSTREAM 0x11
#define BUS_STUFF_ON ((myMode & 0x0F) == 0) #define BUS_STUFF_ON ((myMode & 0x0F) == 0)
#define DIGITAL_AUDIO_ON ((myMode & 0xF0) == 0) #define DIGITAL_AUDIO_ON ((myMode & 0xF0) == 0)
@ -41,6 +44,7 @@ CartridgeBUS::CartridgeBUS(const uInt8* image, uInt32 size,
const Settings& settings) const Settings& settings)
: Cartridge(settings), : Cartridge(settings),
mySystemCycles(0), mySystemCycles(0),
myARMCycles(0),
myFractionalClocks(0.0) myFractionalClocks(0.0)
{ {
// Copy the ROM image into my buffer // Copy the ROM image into my buffer
@ -78,6 +82,7 @@ void CartridgeBUS::reset()
// Update cycles to the current system cycles // Update cycles to the current system cycles
mySystemCycles = mySystem->cycles(); mySystemCycles = mySystem->cycles();
myARMCycles = mySystem->cycles();
myFractionalClocks = 0.0; myFractionalClocks = 0.0;
setInitialState(); setInitialState();
@ -116,6 +121,7 @@ void CartridgeBUS::systemCyclesReset()
{ {
// Adjust the cycle counter so that it reflects the new value // Adjust the cycle counter so that it reflects the new value
mySystemCycles -= mySystem->cycles(); mySystemCycles -= mySystem->cycles();
myARMCycles -= mySystem->cycles();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -172,7 +178,10 @@ inline void CartridgeBUS::callFunction(uInt8 value)
// 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 {
myThumbEmulator->run(); Int32 cycles = mySystem->cycles() - myARMCycles;
myARMCycles = mySystem->cycles();
myThumbEmulator->run(cycles);
} }
catch(const runtime_error& e) { catch(const runtime_error& e) {
if(!mySystem->autodetectMode()) if(!mySystem->autodetectMode())
@ -211,6 +220,32 @@ uInt8 CartridgeBUS::peek(uInt16 address)
// 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;
// implement JMP FASTJMP which fetches the destination address from stream 33
if (myFastJumpActive)
{
uInt32 pointer;
uInt8 value;
myFastJumpActive--;
pointer = getDatastreamPointer(JUMPSTREAM);
value = myDisplayImage[ pointer >> 20 ];
pointer += 0x100000; // always increment by 1
setDatastreamPointer(JUMPSTREAM, pointer);
return value;
}
// test for JMP FASTJUMP where FASTJUMP = $0000
if (BUS_STUFF_ON
&& peekvalue == 0x4C
&& myProgramImage[(myCurrentBank << 12) + address+1] == 0
&& myProgramImage[(myCurrentBank << 12) + address+2] == 0)
{
myFastJumpActive = 2; // return next two peeks from datastream 31
return peekvalue;
}
// save the STY's zero page address // save the STY's zero page address
if (BUS_STUFF_ON && mySTYZeroPageAddress == address) if (BUS_STUFF_ON && mySTYZeroPageAddress == address)
@ -218,120 +253,90 @@ uInt8 CartridgeBUS::peek(uInt16 address)
mySTYZeroPageAddress = 0; mySTYZeroPageAddress = 0;
if(address < 0x20) switch(address)
{ {
uInt8 result = 0; case 0xFEE: // AMPLITUDE
// Get the index of the data fetcher that's being accessed // Update the music data fetchers (counter & flag)
uInt32 index = address & 0x0f; updateMusicModeDataFetchers();
uInt32 function = (address >> 4) & 0x01;
if DIGITAL_AUDIO_ON
switch(function)
{
case 0x00: // read from a datastream
{ {
result = readFromDatastream(index); // retrieve packed sample (max size is 2K, or 4K of unpacked data)
break; peekvalue = myImage[getSample() + (myMusicCounters[0] >> 21)];
//
if ((myMusicCounters[0] & (1<<20)) == 0)
peekvalue >>= 4;
peekvalue &= 0x0f;
} }
case 0x01: // misc read registers else
{ {
switch(index) // using myDisplayImage[] instead of myProgramImage[] because waveforms
{ // can be modified during runtime.
// the following are POKE ONLY uInt32 i = myDisplayImage[(getWaveform(0) ) + (myMusicCounters[0] >> myMusicWaveformSize[0])] +
case 0x00: // 0x10 DF0WRITE myDisplayImage[(getWaveform(1) ) + (myMusicCounters[1] >> myMusicWaveformSize[1])] +
case 0x01: // 0x11 DF1WRITE myDisplayImage[(getWaveform(2) ) + (myMusicCounters[2] >> myMusicWaveformSize[2])];
case 0x02: // 0x12 DF2WRITE
case 0x03: // 0x13 DF3WRITE peekvalue = uInt8(i);
case 0x04: // 0x14 DF0PTR
case 0x05: // 0x15 DF1PTR
case 0x06: // 0x16 DF2PTR
case 0x07: // 0x17 DF3PTR
case 0x09: // 0x19 STUFFMODE
case 0x0a: // 0x1A CALLFN
break;
case 0x08: // 0x18 = AMPLITUDE
// Update the music data fetchers (counter & flag)
updateMusicModeDataFetchers();
if DIGITAL_AUDIO_ON
{
// retrieve packed sample (max size is 2K, or 4K of unpacked data)
result = myImage[getSample() + (myMusicCounters[0] >> 21)];
//
if ((myMusicCounters[0] & (1<<20)) == 0)
result >>= 4;
result &= 0x0f;
}
else
{
// using myDisplayImage[] instead of myProgramImage[] because waveforms
// can be modified during runtime.
uInt32 i = myDisplayImage[(getWaveform(0) ) + (myMusicCounters[0] >> myMusicWaveformSize[0])] +
myDisplayImage[(getWaveform(1) ) + (myMusicCounters[1] >> myMusicWaveformSize[1])] +
myDisplayImage[(getWaveform(2) ) + (myMusicCounters[2] >> myMusicWaveformSize[2])];
result = uInt8(i);
}
break;
}
break;
} }
} break;
return result; case 0xFEF: // DSREAD
} peekvalue = readFromDatastream(COMMSTREAM);
else break;
{
// Switch banks if necessary case 0xFF0: // DSWRITE
switch(address) case 0xFF1: // DSPTR
{ case 0xFF2: // SETMODE
case 0xFF5: case 0xFF3: // CALLFN
// Set the current bank to the first 4k bank // these are write-only
bank(0); break;
break;
case 0xFF5:
case 0x0FF6: // Set the current bank to the first 4k bank
// Set the current bank to the second 4k bank bank(0);
bank(1); break;
break;
case 0x0FF6:
case 0x0FF7: // Set the current bank to the second 4k bank
// Set the current bank to the third 4k bank bank(1);
bank(2); break;
break;
case 0x0FF7:
case 0x0FF8: // Set the current bank to the third 4k bank
// Set the current bank to the fourth 4k bank bank(2);
bank(3); break;
break;
case 0x0FF8:
case 0x0FF9: // Set the current bank to the fourth 4k bank
// Set the current bank to the fifth 4k bank bank(3);
bank(4); break;
break;
case 0x0FF9:
case 0x0FFA: // Set the current bank to the fifth 4k bank
// Set the current bank to the sixth 4k bank bank(4);
bank(5); break;
break;
case 0x0FFA:
case 0x0FFB: // Set the current bank to the sixth 4k bank
// Set the current bank to the last 4k bank bank(5);
bank(6); break;
break;
case 0x0FFB:
default: // Set the current bank to the last 4k bank
break; bank(6);
} break;
// this might not work right for STY $84 default:
if (BUS_STUFF_ON && peekvalue == 0x84) break;
mySTYZeroPageAddress = address + 1;
return peekvalue;
} }
// this might not work right for STY $84
if (BUS_STUFF_ON && peekvalue == 0x84)
mySTYZeroPageAddress = address + 1;
return peekvalue;
} }
return 0; // make compiler happy return 0; // make compiler happy
@ -353,102 +358,77 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
} }
else else
{ {
uInt32 pointer;
address &= 0x0FFF; address &= 0x0FFF;
if ((address >= 0x10) && (address <= 0x1F)) switch(address)
{ {
// Get the index of the data fetcher that's being accessed case 0xFEE: // AMPLITUDE
uInt32 index = address & 0x0f; case 0xFEF: // DSREAD
uInt32 pointer; // these are read-only
break;
switch (index)
{ case 0xFF0: // DSWRITE
case 0x00: // DS0WRITE pointer = getDatastreamPointer(COMMSTREAM);
case 0x01: // DS1WRITE myDisplayImage[ pointer >> 20 ] = value;
case 0x02: // DS2WRITE pointer += 0x100000; // always increment by 1 when writing
case 0x03: // DS3WRITE setDatastreamPointer(COMMSTREAM, pointer);
// Pointers are stored as: break;
// PPPFF---
// case 0xFF1: // DSPTR
// P = Pointer pointer = getDatastreamPointer(COMMSTREAM);
// F = Fractional pointer <<=8;
pointer &= 0xf0000000;
pointer = getDatastreamPointer(index); pointer |= (value << 20);
myDisplayImage[ pointer >> 20 ] = value; setDatastreamPointer(COMMSTREAM, pointer);
pointer += 0x100000; // always increment by 1 when writing break;
setDatastreamPointer(index, pointer);
break; case 0xFF2: // SETMODE
myMode = value;
case 0x04: // 0x14 DS0PTR break;
case 0x05: // 0x15 DS1PTR
case 0x06: // 0x16 DS2PTR case 0xFF3: // CALLFN
case 0x07: // 0x17 DS3PTR callFunction(value);
// Pointers are stored as: break;
// PPPFF---
// case 0xFF5:
// P = Pointer // Set the current bank to the first 4k bank
// F = Fractional bank(0);
break;
index &= 0x03;
pointer = getDatastreamPointer(index); case 0x0FF6:
pointer <<=8; // Set the current bank to the second 4k bank
pointer &= 0xf0000000; bank(1);
pointer |= (value << 20); break;
setDatastreamPointer(index, pointer);
break; case 0x0FF7:
// Set the current bank to the third 4k bank
case 0x09: // 0x19 SETMODE bank(2);
myMode = value; break;
break;
case 0x0FF8:
case 0x0A: // 0x1A CALLFUNCTION // Set the current bank to the fourth 4k bank
callFunction(value); bank(3);
break; break;
}
} case 0x0FF9:
else // Set the current bank to the fifth 4k bank
{ bank(4);
// Switch banks if necessary break;
switch(address)
{ case 0x0FFA:
case 0xFF5: // Set the current bank to the sixth 4k bank
// Set the current bank to the first 4k bank bank(5);
bank(0); break;
break;
case 0x0FFB:
case 0x0FF6: // Set the current bank to the last 4k bank
// Set the current bank to the second 4k bank bank(6);
bank(1); break;
break;
default:
case 0x0FF7: break;
// Set the current bank to the third 4k bank
bank(2);
break;
case 0x0FF8:
// Set the current bank to the fourth 4k bank
bank(3);
break;
case 0x0FF9:
// Set the current bank to the fifth 4k bank
bank(4);
break;
case 0x0FFA:
// Set the current bank to the sixth 4k bank
bank(5);
break;
case 0x0FFB:
// Set the current bank to the last 4k bank
bank(6);
break;
default:
break;
}
} }
} }
@ -516,12 +496,6 @@ uInt8 CartridgeBUS::busOverdrive(uInt16 address)
{ {
uInt8 overdrive = 0xff; uInt8 overdrive = 0xff;
// Not sure how to do this, check with stephena.
//
// 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".
// only overdrive if the address matches // only overdrive if the address matches
if (address == myBusOverdriveAddress) if (address == myBusOverdriveAddress)
{ {
@ -536,8 +510,6 @@ uInt8 CartridgeBUS::busOverdrive(uInt16 address)
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
} }
} }
@ -588,9 +560,26 @@ bool CartridgeBUS::save(Serializer& out) const
// Harmony RAM // Harmony RAM
out.putByteArray(myBUSRAM, 8192); out.putByteArray(myBUSRAM, 8192);
// Addresses for bus override logic
out.putShort(myBusOverdriveAddress);
out.putShort(mySTYZeroPageAddress);
// Save cycles and clocks
out.putInt(mySystemCycles); out.putInt(mySystemCycles);
out.putInt((uInt32)(myFractionalClocks * 100000000.0)); out.putInt((uInt32)(myFractionalClocks * 100000000.0));
out.putInt(myARMCycles);
// Audio info
out.putIntArray(myMusicCounters, 3);
out.putIntArray(myMusicFrequencies, 3);
out.putByteArray(myMusicWaveformSize, 3);
// Indicates current mode
out.putByte(myMode);
// Indicates if in the middle of a fast jump
out.putByte(myFastJumpActive);
} }
catch(...) catch(...)
{ {
@ -614,10 +603,26 @@ bool CartridgeBUS::load(Serializer& in)
// Harmony RAM // Harmony RAM
in.getByteArray(myBUSRAM, 8192); in.getByteArray(myBUSRAM, 8192);
// Addresses for bus override logic
myBusOverdriveAddress = in.getShort();
mySTYZeroPageAddress = in.getShort();
// 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();
// Audio info
in.getIntArray(myMusicCounters, 3);
in.getIntArray(myMusicFrequencies, 3);
in.getByteArray(myMusicWaveformSize, 3);
// Indicates current mode
myMode = in.getByte();
// Indicates if in the middle of a fast jump
myFastJumpActive = in.getByte();
} }
catch(...) catch(...)
{ {

View File

@ -249,8 +249,9 @@ 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; // ARM cycle count from when the last callFunction() occurred
Int32 myARMCycles;
// The music mode counters // The music mode counters
uInt32 myMusicCounters[3]; uInt32 myMusicCounters[3];
@ -270,6 +271,8 @@ class CartridgeBUS : public Cartridge
// 0- = Packed Digital Sample // 0- = Packed Digital Sample
// F- = 3 Voice Music // F- = 3 Voice Music
uInt8 myMode; uInt8 myMode;
uInt8 myFastJumpActive;
private: private:
// Following constructors and assignment operators not supported // Following constructors and assignment operators not supported

View File

@ -32,7 +32,7 @@
#define WAVEFORM 0x07F0 #define WAVEFORM 0x07F0
#define DSRAM 0x0800 #define DSRAM 0x0800
#define WRITESTREAM 0x20 #define COMMSTREAM 0x20
#define JUMPSTREAM 0x21 #define JUMPSTREAM 0x21
#define AMPLITUDE 0x22 #define AMPLITUDE 0x22
@ -228,11 +228,15 @@ uInt8 CartridgeCDF::peek(uInt16 address)
return peekvalue; return peekvalue;
} }
// Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value) // Do a FAST FETCH LDA# if:
// 1) in Fast Fetch mode
// 2) peeking the operand of an LDA # instruction
// 3) peek value is 0-34
if(FAST_FETCH_ON if(FAST_FETCH_ON
&& myLDAimmediateOperandAddress == address && myLDAimmediateOperandAddress == address
&& peekvalue <= AMPLITUDE) && peekvalue <= AMPLITUDE)
{ {
myLDAimmediateOperandAddress = 0;
if (peekvalue == AMPLITUDE) if (peekvalue == AMPLITUDE)
{ {
updateMusicModeDataFetchers(); updateMusicModeDataFetchers();
@ -318,22 +322,21 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
address &= 0x0FFF; address &= 0x0FFF;
// Switch banks if necessary
switch(address) switch(address)
{ {
case 0xFF0: // DSWRITE case 0xFF0: // DSWRITE
pointer = getDatastreamPointer(WRITESTREAM); pointer = getDatastreamPointer(COMMSTREAM);
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(WRITESTREAM, pointer); setDatastreamPointer(COMMSTREAM, pointer);
break; break;
case 0xFF1: // DSPTR case 0xFF1: // DSPTR
pointer = getDatastreamPointer(WRITESTREAM); pointer = getDatastreamPointer(COMMSTREAM);
pointer <<=8; pointer <<=8;
pointer &= 0xf0000000; pointer &= 0xf0000000;
pointer |= (value << 20); pointer |= (value << 20);
setDatastreamPointer(WRITESTREAM, pointer); setDatastreamPointer(COMMSTREAM, pointer);
break; break;
case 0xFF2: // SETMODE case 0xFF2: // SETMODE

View File

@ -1076,29 +1076,28 @@ int Thumbulator::execute()
switch(configuration) switch(configuration)
{ {
case ConfigureFor::BUS: case ConfigureFor::BUS:
case ConfigureFor::CDF: // this subroutine interface is used in the BUS driver,
// this subroutine interface is used in BUS and CDF drivers, // it starts at address 0x000006d8
// and starts at address 0x000006e0 in both.
// _SetNote: // _SetNote:
// ldr r4, =NoteStore // ldr r4, =NoteStore
// bx r4 // bx instruction at 0x000006e2 // bx r4 // bx instruction at 0x000006da
// _ResetWave: // _ResetWave:
// ldr r4, =ResetWaveStore // ldr r4, =ResetWaveStore
// bx r4 // bx instruction at 0x000006e6 // bx r4 // bx instruction at 0x000006de
// _GetWavePtr: // _GetWavePtr:
// ldr r4, =WavePtrFetch // ldr r4, =WavePtrFetch
// bx r4 // bx instruction at 0x000006ea // bx r4 // bx instruction at 0x000006e2
// _SetWaveSize: // _SetWaveSize:
// ldr r4, =WaveSizeStore // ldr r4, =WaveSizeStore
// bx r4 // bx instruction at 0x000006ee // bx r4 // bx instruction at 0x000006e6
// 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_SetNote (0x000006da + 4)
#define BUS_ResetWave (0x000006e6 + 4) #define BUS_ResetWave (0x000006de + 4)
#define BUS_GetWavePtr (0x000006ea + 4) #define BUS_GetWavePtr (0x000006e2 + 4)
#define BUS_SetWaveSize (0x000006ee + 4) #define BUS_SetWaveSize (0x000006e6 + 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));
@ -1125,6 +1124,67 @@ int Thumbulator::execute()
} }
else else
{ {
#if 0 // uncomment this for testing
uInt32 r0 = read_register(0);
uInt32 r1 = read_register(1);
uInt32 r2 = read_register(2);
uInt32 r3 = read_register(3);
uInt32 r4 = read_register(4);
#endif
myCartridge->thumbCallback(255, 0, 0);
}
break;
case ConfigureFor::CDF:
// this subroutine interface is used in the CDF driver,
// it starts at address 0x000006e0
// _SetNote:
// ldr r4, =NoteStore
// bx r4 // bx instruction at 0x000006e2
// _ResetWave:
// ldr r4, =ResetWaveStore
// bx r4 // bx instruction at 0x000006e6
// _GetWavePtr:
// ldr r4, =WavePtrFetch
// bx r4 // bx instruction at 0x000006ea
// _SetWaveSize:
// ldr r4, =WaveSizeStore
// bx r4 // bx instruction at 0x000006ee
// address to test for is + 4 due to pipelining
#define CDF_SetNote (0x000006e2 + 4)
#define CDF_ResetWave (0x000006e6 + 4)
#define CDF_GetWavePtr (0x000006ea + 4)
#define CDF_SetWaveSize (0x000006ee + 4)
if (pc == CDF_SetNote)
{
myCartridge->thumbCallback(0, read_register(2), read_register(3));
handled = true;
}
else if (pc == CDF_ResetWave)
{
myCartridge->thumbCallback(1, read_register(2), 0);
handled = true;
}
else if (pc == CDF_GetWavePtr)
{
write_register(2, myCartridge->thumbCallback(2, read_register(2), 0));
handled = true;
}
else if (pc == CDF_SetWaveSize)
{
myCartridge->thumbCallback(3, read_register(2), read_register(3));
handled = true;
}
else if (pc == 0x0000083a)
{
// exiting Custom ARM code, returning to BUS Driver control
}
else
{
#if 0 // uncomment this 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);