mirror of https://github.com/stella-emu/stella.git
Merge branch 'SpiceWare-master'
This commit is contained in:
commit
1cb83f4a68
|
@ -33,8 +33,8 @@ CartridgeBUSWidget::CartridgeBUSWidget(
|
|||
info << "BUS Stuffing cartridge\n"
|
||||
<< "32K ROM, seven 4K banks are accessible to 2600\n"
|
||||
<< "8K BUS RAM\n"
|
||||
<< "BUS registers accessible @ $F000 - $F03F\n"
|
||||
<< "Banks accessible at hotspots $FFF5 to $FFFB\n"
|
||||
<< "BUS registers accessible @ $FFEE - $FFF3\n"
|
||||
<< "Banks accessible at hotspots $FFFF to $FFFB\n"
|
||||
<< "Startup bank = " << cart.myStartBank << "\n";
|
||||
|
||||
#if 0
|
||||
|
@ -49,7 +49,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
|
|||
#endif
|
||||
|
||||
int xpos = 10,
|
||||
ypos = addBaseInformation(size, "AtariAge", info.str()) +
|
||||
ypos = addBaseInformation(size, "AtariAge", info.str(), 4) +
|
||||
myLineHeight;
|
||||
|
||||
VariantList items;
|
||||
|
@ -70,28 +70,57 @@ CartridgeBUSWidget::CartridgeBUSWidget(
|
|||
int lwidth = _font.getStringWidth("Datastream Increments "); // get width of the widest label
|
||||
|
||||
// Datastream Pointers
|
||||
xpos = 0; ypos += myLineHeight + 4;
|
||||
#define DS_X 30
|
||||
xpos = DS_X;
|
||||
ypos += myLineHeight + 4;
|
||||
new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
|
||||
myFontHeight, "Datastream Pointers ", kTextAlignLeft);
|
||||
myFontHeight, "Datastream Pointers", kTextAlignLeft);
|
||||
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->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
|
||||
xpos = 0 + myDatastreamPointers->getWidth();
|
||||
xpos = DS_X + myDatastreamPointers->getWidth() + 20;
|
||||
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->setTarget(this);
|
||||
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
|
||||
xpos = 0; ypos += myLineHeight*5 + 4;
|
||||
xpos = 0; ypos += myLineHeight*7 + 4;
|
||||
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->setTarget(this);
|
||||
|
@ -100,7 +129,7 @@ CartridgeBUSWidget::CartridgeBUSWidget(
|
|||
// Music counters
|
||||
xpos = 10; ypos += myLineHeight*6 + 4;
|
||||
new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
|
||||
myFontHeight, "Music Counters ", kTextAlignLeft);
|
||||
myFontHeight, "Music Counters", kTextAlignLeft);
|
||||
xpos += lwidth;
|
||||
|
||||
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
|
||||
xpos = 10; ypos += myLineHeight + 4;
|
||||
new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
|
||||
myFontHeight, "Music Frequencies ", kTextAlignLeft);
|
||||
myFontHeight, "Music Frequencies", kTextAlignLeft);
|
||||
xpos += lwidth;
|
||||
|
||||
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
|
||||
xpos = 10; ypos += myLineHeight + 4;
|
||||
new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
|
||||
myFontHeight, "Music Waveforms ", kTextAlignLeft);
|
||||
myFontHeight, "Music Waveforms", kTextAlignLeft);
|
||||
xpos += lwidth;
|
||||
|
||||
myMusicWaveforms = new DataGridWidget(boss, _nfont, xpos, ypos-2, 3, 1, 4, 16, Common::Base::F_16_2);
|
||||
myMusicWaveforms->setTarget(this);
|
||||
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
|
||||
xpos = 10; ypos += myLineHeight + 4;
|
||||
new StaticTextWidget(boss, _font, xpos, ypos, lwidth,
|
||||
myFontHeight, "Music Waveform Sizes ", kTextAlignLeft);
|
||||
myFontHeight, "Music Waveform Sizes", kTextAlignLeft);
|
||||
xpos += lwidth;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
// BUS stuff and ZP STY flags
|
||||
// BUS stuff and Digital Audio flags
|
||||
xpos = 10; ypos += myLineHeight + 4;
|
||||
myBusOverdrive = new CheckboxWidget(boss, _font, xpos, ypos, "BUS Overdrive enabled");
|
||||
myBusOverdrive->setTarget(this);
|
||||
myBusOverdrive->setEditable(false);
|
||||
xpos = _font.getStringWidth("CHECKBOX BUS Overdrive enabled");
|
||||
myZPSTY = new CheckboxWidget(boss, _font, xpos, ypos, "Zero Page STY");
|
||||
myZPSTY->setTarget(this);
|
||||
myZPSTY->setEditable(false);
|
||||
|
||||
myDigitalSample = new CheckboxWidget(boss, _font, xpossp, ypos, "Digital Sample mode");
|
||||
myDigitalSample->setTarget(this);
|
||||
myDigitalSample->setEditable(false);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -162,8 +200,9 @@ void CartridgeBUSWidget::saveOldState()
|
|||
myOldState.mwaves.clear();
|
||||
myOldState.mwavesizes.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:
|
||||
// PPPFF---
|
||||
|
@ -176,13 +215,21 @@ void CartridgeBUSWidget::saveOldState()
|
|||
// F = Fractional
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -198,6 +245,8 @@ void CartridgeBUSWidget::saveOldState()
|
|||
|
||||
for(uInt32 i = 0; i < internalRamSize(); ++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]);
|
||||
}
|
||||
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();
|
||||
for(int i = 0; i < 16; ++i)
|
||||
{
|
||||
|
@ -237,14 +295,29 @@ void CartridgeBUSWidget::loadConfig()
|
|||
changed.push_back(incrementvalue != myOldState.datastreamincrements[i]);
|
||||
}
|
||||
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();
|
||||
for(int i = 0; i < 40; ++i)
|
||||
for(int i = 0; i < 37; ++i) // only 37 map values
|
||||
{
|
||||
Int32 mapvalue = myCart.getAddressMap(i);
|
||||
alist.push_back(0); vlist.push_back(mapvalue);
|
||||
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);
|
||||
|
||||
alist.clear(); vlist.clear(); changed.clear();
|
||||
|
@ -279,8 +352,26 @@ void CartridgeBUSWidget::loadConfig()
|
|||
}
|
||||
myMusicWaveformSizes->setList(alist, vlist, changed);
|
||||
|
||||
// myBusOverdrive->setState(myCart.getBusStuffFlag());
|
||||
// myZPSTY->setState(myCart.mySTYZeroPage);
|
||||
alist.clear(); vlist.clear(); changed.clear();
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ class CartridgeBUSWidget : public CartDebugWidget
|
|||
IntArray mfreqs;
|
||||
IntArray mwaves;
|
||||
IntArray mwavesizes;
|
||||
IntArray samplepointer;
|
||||
uInt32 random;
|
||||
ByteArray internalram;
|
||||
};
|
||||
|
@ -54,13 +55,17 @@ class CartridgeBUSWidget : public CartDebugWidget
|
|||
|
||||
DataGridWidget* myDatastreamPointers;
|
||||
DataGridWidget* myDatastreamIncrements;
|
||||
DataGridWidget* myDatastreamPointers2;
|
||||
DataGridWidget* myDatastreamIncrements2;
|
||||
DataGridWidget* myAddressMaps;
|
||||
DataGridWidget* myMusicCounters;
|
||||
DataGridWidget* myMusicFrequencies;
|
||||
DataGridWidget* myMusicWaveforms;
|
||||
DataGridWidget* myMusicWaveformSizes;
|
||||
DataGridWidget* mySamplePointer;
|
||||
StaticTextWidget* myDatastreamLabels[6];
|
||||
CheckboxWidget* myBusOverdrive;
|
||||
CheckboxWidget* myZPSTY;
|
||||
CheckboxWidget* myDigitalSample;
|
||||
CartState myOldState;
|
||||
|
||||
enum { kBankChanged = 'bkCH' };
|
||||
|
|
|
@ -96,16 +96,14 @@ CartridgeCDFWidget::CartridgeCDFWidget(
|
|||
myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2));
|
||||
}
|
||||
lwidth = _font.getStringWidth("Write Data (stream 20)");
|
||||
myDatastreamLabels[row] =
|
||||
myDatastreamLabels[8] =
|
||||
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
|
||||
ypos+myLineHeight-2 + 8*myLineHeight + 2,
|
||||
lwidth, myFontHeight, "Write Data (stream 20)", kTextAlignLeft);
|
||||
// myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2));
|
||||
myDatastreamLabels[row] =
|
||||
myDatastreamLabels[9] =
|
||||
new StaticTextWidget(_boss, _font, DS_X - _font.getStringWidth("xx "),
|
||||
ypos+myLineHeight-2 + 9*myLineHeight + 2,
|
||||
lwidth, myFontHeight, "Jump Data (stream 21)", kTextAlignLeft);
|
||||
// myDatastreamLabels[row]->setLabel(Common::Base::toString(row * 4, Common::Base::F_16_2));
|
||||
|
||||
// Datastream Increments
|
||||
xpos = DS_X + myDatastreamPointers->getWidth() + 20;
|
||||
|
|
|
@ -65,7 +65,6 @@ class CartridgeCDFWidget : public CartDebugWidget
|
|||
DataGridWidget* mySamplePointer;
|
||||
StaticTextWidget* myDatastreamLabels[10];
|
||||
|
||||
// done differently than in DPC+, need to rethink debugger support
|
||||
CheckboxWidget* myFastFetch;
|
||||
CheckboxWidget* myDigitalSample;
|
||||
CartState myOldState;
|
||||
|
|
|
@ -27,12 +27,15 @@
|
|||
#include "CartBUS.hxx"
|
||||
|
||||
// Location of data within the RAM copy of the BUS Driver.
|
||||
#define DSxPTR 0x06E0
|
||||
#define DSxPTR 0x06D8
|
||||
#define DSxINC 0x0720
|
||||
#define DSMAPS 0x0760
|
||||
#define WAVEFORM 0x07F4
|
||||
#define DSRAM 0x0800
|
||||
|
||||
#define COMMSTREAM 0x10
|
||||
#define JUMPSTREAM 0x11
|
||||
|
||||
#define BUS_STUFF_ON ((myMode & 0x0F) == 0)
|
||||
#define DIGITAL_AUDIO_ON ((myMode & 0xF0) == 0)
|
||||
|
||||
|
@ -41,6 +44,7 @@ CartridgeBUS::CartridgeBUS(const uInt8* image, uInt32 size,
|
|||
const Settings& settings)
|
||||
: Cartridge(settings),
|
||||
mySystemCycles(0),
|
||||
myARMCycles(0),
|
||||
myFractionalClocks(0.0)
|
||||
{
|
||||
// Copy the ROM image into my buffer
|
||||
|
@ -78,6 +82,7 @@ void CartridgeBUS::reset()
|
|||
|
||||
// Update cycles to the current system cycles
|
||||
mySystemCycles = mySystem->cycles();
|
||||
myARMCycles = mySystem->cycles();
|
||||
myFractionalClocks = 0.0;
|
||||
|
||||
setInitialState();
|
||||
|
@ -116,6 +121,7 @@ void CartridgeBUS::systemCyclesReset()
|
|||
{
|
||||
// Adjust the cycle counter so that it reflects the new value
|
||||
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".
|
||||
case 255: // call without IRQ driven audio
|
||||
try {
|
||||
myThumbEmulator->run();
|
||||
Int32 cycles = mySystem->cycles() - myARMCycles;
|
||||
myARMCycles = mySystem->cycles();
|
||||
|
||||
myThumbEmulator->run(cycles);
|
||||
}
|
||||
catch(const runtime_error& e) {
|
||||
if(!mySystem->autodetectMode())
|
||||
|
@ -211,6 +220,32 @@ uInt8 CartridgeBUS::peek(uInt16 address)
|
|||
// anything that can change the internal state of the cart
|
||||
if(bankLocked())
|
||||
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
|
||||
if (BUS_STUFF_ON && mySTYZeroPageAddress == address)
|
||||
|
@ -218,120 +253,90 @@ uInt8 CartridgeBUS::peek(uInt16 address)
|
|||
|
||||
mySTYZeroPageAddress = 0;
|
||||
|
||||
if(address < 0x20)
|
||||
switch(address)
|
||||
{
|
||||
uInt8 result = 0;
|
||||
|
||||
// Get the index of the data fetcher that's being accessed
|
||||
uInt32 index = address & 0x0f;
|
||||
uInt32 function = (address >> 4) & 0x01;
|
||||
|
||||
switch(function)
|
||||
{
|
||||
case 0x00: // read from a datastream
|
||||
case 0xFEE: // AMPLITUDE
|
||||
|
||||
// Update the music data fetchers (counter & flag)
|
||||
updateMusicModeDataFetchers();
|
||||
|
||||
if DIGITAL_AUDIO_ON
|
||||
{
|
||||
result = readFromDatastream(index);
|
||||
break;
|
||||
// retrieve packed sample (max size is 2K, or 4K of unpacked data)
|
||||
peekvalue = myImage[getSample() + (myMusicCounters[0] >> 21)];
|
||||
|
||||
//
|
||||
if ((myMusicCounters[0] & (1<<20)) == 0)
|
||||
peekvalue >>= 4;
|
||||
peekvalue &= 0x0f;
|
||||
}
|
||||
case 0x01: // misc read registers
|
||||
else
|
||||
{
|
||||
switch(index)
|
||||
{
|
||||
// the following are POKE ONLY
|
||||
case 0x00: // 0x10 DF0WRITE
|
||||
case 0x01: // 0x11 DF1WRITE
|
||||
case 0x02: // 0x12 DF2WRITE
|
||||
case 0x03: // 0x13 DF3WRITE
|
||||
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;
|
||||
// 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])];
|
||||
|
||||
peekvalue = uInt8(i);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0xFF5:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// 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;
|
||||
}
|
||||
|
||||
// this might not work right for STY $84
|
||||
if (BUS_STUFF_ON && peekvalue == 0x84)
|
||||
mySTYZeroPageAddress = address + 1;
|
||||
|
||||
return peekvalue;
|
||||
break;
|
||||
|
||||
case 0xFEF: // DSREAD
|
||||
peekvalue = readFromDatastream(COMMSTREAM);
|
||||
break;
|
||||
|
||||
case 0xFF0: // DSWRITE
|
||||
case 0xFF1: // DSPTR
|
||||
case 0xFF2: // SETMODE
|
||||
case 0xFF3: // CALLFN
|
||||
// these are write-only
|
||||
break;
|
||||
|
||||
case 0xFF5:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// 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;
|
||||
}
|
||||
|
||||
// this might not work right for STY $84
|
||||
if (BUS_STUFF_ON && peekvalue == 0x84)
|
||||
mySTYZeroPageAddress = address + 1;
|
||||
|
||||
return peekvalue;
|
||||
}
|
||||
|
||||
return 0; // make compiler happy
|
||||
|
@ -353,102 +358,77 @@ bool CartridgeBUS::poke(uInt16 address, uInt8 value)
|
|||
}
|
||||
else
|
||||
{
|
||||
uInt32 pointer;
|
||||
|
||||
address &= 0x0FFF;
|
||||
|
||||
if ((address >= 0x10) && (address <= 0x1F))
|
||||
switch(address)
|
||||
{
|
||||
// Get the index of the data fetcher that's being accessed
|
||||
uInt32 index = address & 0x0f;
|
||||
uInt32 pointer;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 0x00: // DS0WRITE
|
||||
case 0x01: // DS1WRITE
|
||||
case 0x02: // DS2WRITE
|
||||
case 0x03: // DS3WRITE
|
||||
// Pointers are stored as:
|
||||
// PPPFF---
|
||||
//
|
||||
// P = Pointer
|
||||
// F = Fractional
|
||||
|
||||
pointer = getDatastreamPointer(index);
|
||||
myDisplayImage[ pointer >> 20 ] = value;
|
||||
pointer += 0x100000; // always increment by 1 when writing
|
||||
setDatastreamPointer(index, pointer);
|
||||
break;
|
||||
|
||||
case 0x04: // 0x14 DS0PTR
|
||||
case 0x05: // 0x15 DS1PTR
|
||||
case 0x06: // 0x16 DS2PTR
|
||||
case 0x07: // 0x17 DS3PTR
|
||||
// Pointers are stored as:
|
||||
// PPPFF---
|
||||
//
|
||||
// P = Pointer
|
||||
// F = Fractional
|
||||
|
||||
index &= 0x03;
|
||||
pointer = getDatastreamPointer(index);
|
||||
pointer <<=8;
|
||||
pointer &= 0xf0000000;
|
||||
pointer |= (value << 20);
|
||||
setDatastreamPointer(index, pointer);
|
||||
break;
|
||||
|
||||
case 0x09: // 0x19 SETMODE
|
||||
myMode = value;
|
||||
break;
|
||||
|
||||
case 0x0A: // 0x1A CALLFUNCTION
|
||||
callFunction(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0xFF5:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// 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;
|
||||
}
|
||||
case 0xFEE: // AMPLITUDE
|
||||
case 0xFEF: // DSREAD
|
||||
// these are read-only
|
||||
break;
|
||||
|
||||
case 0xFF0: // DSWRITE
|
||||
pointer = getDatastreamPointer(COMMSTREAM);
|
||||
myDisplayImage[ pointer >> 20 ] = value;
|
||||
pointer += 0x100000; // always increment by 1 when writing
|
||||
setDatastreamPointer(COMMSTREAM, pointer);
|
||||
break;
|
||||
|
||||
case 0xFF1: // DSPTR
|
||||
pointer = getDatastreamPointer(COMMSTREAM);
|
||||
pointer <<=8;
|
||||
pointer &= 0xf0000000;
|
||||
pointer |= (value << 20);
|
||||
setDatastreamPointer(COMMSTREAM, pointer);
|
||||
break;
|
||||
|
||||
case 0xFF2: // SETMODE
|
||||
myMode = value;
|
||||
break;
|
||||
|
||||
case 0xFF3: // CALLFN
|
||||
callFunction(value);
|
||||
break;
|
||||
|
||||
case 0xFF5:
|
||||
// Set the current bank to the first 4k bank
|
||||
bank(0);
|
||||
break;
|
||||
|
||||
case 0x0FF6:
|
||||
// Set the current bank to the second 4k bank
|
||||
bank(1);
|
||||
break;
|
||||
|
||||
case 0x0FF7:
|
||||
// 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;
|
||||
|
||||
// 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
|
||||
if (address == myBusOverdriveAddress)
|
||||
{
|
||||
|
@ -536,8 +510,6 @@ uInt8 CartridgeBUS::busOverdrive(uInt16 address)
|
|||
alldatastreams >>= 4;
|
||||
alldatastreams |= (datastream << 28);
|
||||
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
|
||||
out.putByteArray(myBUSRAM, 8192);
|
||||
|
||||
|
||||
// Addresses for bus override logic
|
||||
out.putShort(myBusOverdriveAddress);
|
||||
out.putShort(mySTYZeroPageAddress);
|
||||
|
||||
// Save cycles and clocks
|
||||
out.putInt(mySystemCycles);
|
||||
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(...)
|
||||
{
|
||||
|
@ -614,10 +603,26 @@ bool CartridgeBUS::load(Serializer& in)
|
|||
|
||||
// Harmony RAM
|
||||
in.getByteArray(myBUSRAM, 8192);
|
||||
|
||||
// Addresses for bus override logic
|
||||
myBusOverdriveAddress = in.getShort();
|
||||
mySTYZeroPageAddress = in.getShort();
|
||||
|
||||
// Get system cycles and fractional clocks
|
||||
mySystemCycles = (Int32)in.getInt();
|
||||
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(...)
|
||||
{
|
||||
|
|
|
@ -249,8 +249,9 @@ class CartridgeBUS : public Cartridge
|
|||
|
||||
// System cycle count when the last update to music data fetchers occurred
|
||||
Int32 mySystemCycles;
|
||||
|
||||
uInt8 mySetAddress;
|
||||
|
||||
// ARM cycle count from when the last callFunction() occurred
|
||||
Int32 myARMCycles;
|
||||
|
||||
// The music mode counters
|
||||
uInt32 myMusicCounters[3];
|
||||
|
@ -270,6 +271,8 @@ class CartridgeBUS : public Cartridge
|
|||
// 0- = Packed Digital Sample
|
||||
// F- = 3 Voice Music
|
||||
uInt8 myMode;
|
||||
|
||||
uInt8 myFastJumpActive;
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#define WAVEFORM 0x07F0
|
||||
#define DSRAM 0x0800
|
||||
|
||||
#define WRITESTREAM 0x20
|
||||
#define COMMSTREAM 0x20
|
||||
#define JUMPSTREAM 0x21
|
||||
#define AMPLITUDE 0x22
|
||||
|
||||
|
@ -228,11 +228,15 @@ uInt8 CartridgeCDF::peek(uInt16 address)
|
|||
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
|
||||
&& myLDAimmediateOperandAddress == address
|
||||
&& peekvalue <= AMPLITUDE)
|
||||
{
|
||||
myLDAimmediateOperandAddress = 0;
|
||||
if (peekvalue == AMPLITUDE)
|
||||
{
|
||||
updateMusicModeDataFetchers();
|
||||
|
@ -318,22 +322,21 @@ bool CartridgeCDF::poke(uInt16 address, uInt8 value)
|
|||
|
||||
address &= 0x0FFF;
|
||||
|
||||
// Switch banks if necessary
|
||||
switch(address)
|
||||
{
|
||||
case 0xFF0: // DSWRITE
|
||||
pointer = getDatastreamPointer(WRITESTREAM);
|
||||
pointer = getDatastreamPointer(COMMSTREAM);
|
||||
myDisplayImage[ pointer >> 20 ] = value;
|
||||
pointer += 0x100000; // always increment by 1 when writing
|
||||
setDatastreamPointer(WRITESTREAM, pointer);
|
||||
setDatastreamPointer(COMMSTREAM, pointer);
|
||||
break;
|
||||
|
||||
case 0xFF1: // DSPTR
|
||||
pointer = getDatastreamPointer(WRITESTREAM);
|
||||
pointer = getDatastreamPointer(COMMSTREAM);
|
||||
pointer <<=8;
|
||||
pointer &= 0xf0000000;
|
||||
pointer |= (value << 20);
|
||||
setDatastreamPointer(WRITESTREAM, pointer);
|
||||
setDatastreamPointer(COMMSTREAM, pointer);
|
||||
break;
|
||||
|
||||
case 0xFF2: // SETMODE
|
||||
|
|
|
@ -1076,29 +1076,28 @@ int Thumbulator::execute()
|
|||
switch(configuration)
|
||||
{
|
||||
case ConfigureFor::BUS:
|
||||
case ConfigureFor::CDF:
|
||||
// this subroutine interface is used in BUS and CDF drivers,
|
||||
// and starts at address 0x000006e0 in both.
|
||||
// this subroutine interface is used in the BUS driver,
|
||||
// it starts at address 0x000006d8
|
||||
// _SetNote:
|
||||
// ldr r4, =NoteStore
|
||||
// bx r4 // bx instruction at 0x000006e2
|
||||
// bx r4 // bx instruction at 0x000006da
|
||||
// _ResetWave:
|
||||
// ldr r4, =ResetWaveStore
|
||||
// bx r4 // bx instruction at 0x000006e6
|
||||
// bx r4 // bx instruction at 0x000006de
|
||||
// _GetWavePtr:
|
||||
// ldr r4, =WavePtrFetch
|
||||
// bx r4 // bx instruction at 0x000006ea
|
||||
// bx r4 // bx instruction at 0x000006e2
|
||||
// _SetWaveSize:
|
||||
// ldr r4, =WaveSizeStore
|
||||
// bx r4 // bx instruction at 0x000006ee
|
||||
|
||||
// bx r4 // bx instruction at 0x000006e6
|
||||
|
||||
// address to test for is + 4 due to pipelining
|
||||
|
||||
#define BUS_SetNote (0x000006e2 + 4)
|
||||
#define BUS_ResetWave (0x000006e6 + 4)
|
||||
#define BUS_GetWavePtr (0x000006ea + 4)
|
||||
#define BUS_SetWaveSize (0x000006ee + 4)
|
||||
|
||||
|
||||
#define BUS_SetNote (0x000006da + 4)
|
||||
#define BUS_ResetWave (0x000006de + 4)
|
||||
#define BUS_GetWavePtr (0x000006e2 + 4)
|
||||
#define BUS_SetWaveSize (0x000006e6 + 4)
|
||||
|
||||
if (pc == BUS_SetNote)
|
||||
{
|
||||
myCartridge->thumbCallback(0, read_register(2), read_register(3));
|
||||
|
@ -1125,6 +1124,67 @@ int Thumbulator::execute()
|
|||
}
|
||||
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
|
||||
uInt32 r0 = read_register(0);
|
||||
uInt32 r1 = read_register(1);
|
||||
|
|
Loading…
Reference in New Issue