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"
<< "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();
}

View File

@ -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' };

View File

@ -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;

View File

@ -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;

View File

@ -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(...)
{

View File

@ -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

View File

@ -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

View File

@ -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);