Fixed bug in debugger 'runto' command; it now looks at the generated

disassembly instead of re-disassembling again.  Still TODO is make the
search case in-sensitive.

Added latest DPC+ code from Spiceware.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1988 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-04-04 13:15:35 +00:00
parent 1103f1dfbb
commit a94c579fec
4 changed files with 234 additions and 255 deletions

View File

@ -1168,21 +1168,31 @@ void DebuggerParser::executeRun()
void DebuggerParser::executeRunTo() void DebuggerParser::executeRunTo()
{ {
ostringstream buf; ostringstream buf;
bool done = false; const CartDebug& cartdbg = debugger->cartDebug();
int cycles = 0, count = 0; const CartDebug::DisassemblyList& list = cartdbg.disassemblyList();
uInt32 count = 0;
bool done = false;
do { do {
cycles += debugger->step(); debugger->step();
string next = debugger->cartDebug().disassemble(debugger->cpuDebug().pc(), 1);
done = (next.find(argStrings[0]) != string::npos); // Update romlist to point to current PC
int pcline = cartdbg.addressToLine(debugger->cpuDebug().pc());
if(pcline >= 0)
{
const string& next = list[pcline].disasm;
done = (next.find(argStrings[0]) != string::npos);
}
++count; ++count;
} while(!done && count < 10000); } while(!done && count < list.size());
if(done) if(done)
buf << "found " << argStrings[0] << " in " << debugger->valueToString(cycles) buf << "found " << argStrings[0] << " in "
<< " cycles"; << debugger->valueToString(count, kBASE_10)
<< " disassembled instructions";
else else
buf << argStrings[0] << " not found in " << debugger->valueToString(count) buf << argStrings[0] << " not found in "
<< debugger->valueToString(count, kBASE_10)
<< " disassembled instructions"; << " disassembled instructions";
commandResult = buf.str(); commandResult = buf.str();

View File

@ -47,7 +47,7 @@ class DebuggerParser
string exec(const string& file, bool verbose = true); string exec(const string& file, bool verbose = true);
/** Given a substring, determine matching substrings from the list /** Given a substring, determine matching substrings from the list
of available commands. Used in the debugger prompt for tab-completion */ of available commands. Used in the debugger prompt for tab-completion */
int countCompletions(const char *in); int countCompletions(const char *in);
const char *getCompletions(); const char *getCompletions();
const char *getCompletionPrefix(); const char *getCompletionPrefix();

View File

@ -1,8 +1,8 @@
//============================================================================ //============================================================================
// //
// SSSS tt lll lll // SSSS tt lll lll
// SS SS tt ll ll // SS SS tt ll ll
// SS tttttt eeee ll ll aaaa // SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa // SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator" // SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa // SS SS tt ee ll ll aa aa
@ -22,13 +22,12 @@
#include "System.hxx" #include "System.hxx"
#include "CartDPCPlus.hxx" #include "CartDPCPlus.hxx"
// TODO - INC AUDV0+$40 music support
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size) CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size)
: myFastFetch(false), : myFastFetch(false),
myLDAimmediate(false), myLDAimmediate(false),
mySelectByte(0), mySelectByte(0),
myMusicVolume(0),
mySystemCycles(0), mySystemCycles(0),
myFractionalClocks(0.0) myFractionalClocks(0.0)
{ {
@ -41,7 +40,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size)
// Copy the display ROM image into my buffer // Copy the display ROM image into my buffer
memcpy(myDisplayImage, image + 4096 * 6, 4096); memcpy(myDisplayImage, image + 4096 * 6, 4096);
// Copy the Frequency ROM image into my buffer // Copy the Frequency ROM image into my buffer
memcpy(myFrequencyImage, image + 4096 * 6 + 4096, 1024); memcpy(myFrequencyImage, image + 4096 * 6 + 4096, 1024);
@ -49,9 +48,6 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size)
for(uInt16 i = 0; i < 8; ++i) for(uInt16 i = 0; i < 8; ++i)
myTops[i] = myBottoms[i] = myCounters[i] = myFlags[i] = myFractionalIncrements[i] = 0; myTops[i] = myBottoms[i] = myCounters[i] = myFlags[i] = myFractionalIncrements[i] = 0;
// None of the data fetchers are in music mode
myMusicVolumes[0] = myMusicVolumes[1] = myMusicVolumes[2] = 0;
// Set waveforms to square waves // Set waveforms to square waves
myMusicWaveforms[0] = myMusicWaveforms[1] = myMusicWaveforms[2] = 0xAAAAAAAA; myMusicWaveforms[0] = myMusicWaveforms[1] = myMusicWaveforms[2] = 0xAAAAAAAA;
@ -94,10 +90,10 @@ void CartridgeDPCPlus::install(System& system)
mySystem = &system; mySystem = &system;
uInt16 shift = mySystem->pageShift(); uInt16 shift = mySystem->pageShift();
uInt16 mask = mySystem->pageMask(); uInt16 mask = mySystem->pageMask();
// Make sure the system we're being installed in has a page size that'll work // Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0)); assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
// Map all of the accesses to call peek and poke // Map all of the accesses to call peek and poke
System::PageAccess access; System::PageAccess access;
access.directPeekBase = 0; access.directPeekBase = 0;
@ -105,7 +101,7 @@ void CartridgeDPCPlus::install(System& system)
access.device = this; access.device = this;
for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift)) for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access); mySystem->setPageAccess(i >> shift, access);
// Install pages for the startup bank // Install pages for the startup bank
bank(myStartBank); bank(myStartBank);
} }
@ -130,25 +126,91 @@ inline void CartridgeDPCPlus::updateMusicModeDataFetchers()
// Calculate the number of cycles since the last update // Calculate the number of cycles since the last update
Int32 cycles = mySystem->cycles() - mySystemCycles; Int32 cycles = mySystem->cycles() - mySystemCycles;
mySystemCycles = mySystem->cycles(); mySystemCycles = mySystem->cycles();
// Calculate the number of DPC OSC clocks since the last update // Calculate the number of DPC OSC clocks since the last update
double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks; double clocks = ((20000.0 * cycles) / 1193191.66666667) + myFractionalClocks;
Int32 wholeClocks = (Int32)clocks; Int32 wholeClocks = (Int32)clocks;
myFractionalClocks = clocks - (double)wholeClocks; myFractionalClocks = clocks - (double)wholeClocks;
if(wholeClocks <= 0) if(wholeClocks <= 0)
{ {
return; return;
} }
// Let's update counters and flags of the music mode data fetchers // Let's update counters and flags of the music mode data fetchers
for(int x = 5; x <= 7; ++x) for(int x = 5; x <= 7; ++x)
{ {
// Update only if the data fetcher is in music mode myMusicCounters[x - 5] += myMusicFrequencies[x - 5];
if(myMusicVolumes[x - 5]) if (myMusicFrequencies[x-5]>myMusicCounters[x-5])
myMusicWaveforms[x-5] = (myMusicWaveforms[x-5]>>1)|(myMusicWaveforms[x-5]<<31);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void CartridgeDPCPlus::writeByte(uInt8 value)
{
switch (mySelectByte)
{
case 0x00:
{ {
myMusicCounters[x - 5] += myMusicFrequencies[x - 5]; myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFFFFFF00) | value;
break;
} }
case 0x01:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFFFF00FF) | (value<<8);
break;
}
case 0x02:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFF00FFFF) | (value<<16);
break;
}
case 0x03:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0x00FFFFFF) | (value<<24);
break;
}
case 0x04:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFFFFFF00) | value;
break;
}
case 0x05:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFFFF00FF) | (value<<8);
break;
}
case 0x06:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFF00FFFF) | (value<<16);
break;
}
case 0x07:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0x00FFFFFF) | (value<<24);
break;
}
case 0x08:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFFFFFF00) | value;
break;
}
case 0x09:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFFFF00FF) | (value<<8);
break;
}
case 0x0A:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFF00FFFF) | (value<<16);
break;
}
case 0x0B:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0x00FFFFFF) | (value<<24);
break;
}
} }
} }
@ -158,7 +220,7 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
address &= 0x0FFF; address &= 0x0FFF;
uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address]; uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address];
// In debugger/bank-locked mode, we ignore all hotspots and in general // In debugger/bank-locked mode, we ignore all hotspots and in general
// anything that can change the internal state of the cart // anything that can change the internal state of the cart
if(bankLocked()) if(bankLocked())
@ -167,20 +229,20 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
// Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value) // Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value)
if(myFastFetch && myLDAimmediate) if(myFastFetch && myLDAimmediate)
{ {
// if #value is a read-register then we want to use that as the address
if(peekvalue < 0x0028) if(peekvalue < 0x0028)
// if #value is a read-register then we want to use that as the address
address = peekvalue; address = peekvalue;
} }
myLDAimmediate = false; myLDAimmediate = false;
if(address < 0x0028) if(address < 0x0028)
{ {
uInt8 result = 0; uInt8 result = 0;
// Get the index of the data fetcher that's being accessed // Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x07; uInt32 index = address & 0x07;
uInt32 function = (address >> 3) & 0x07; uInt32 function = (address >> 3) & 0x07;
// Update flag register for selected data fetcher // Update flag register for selected data fetcher
if((myCounters[index] & 0x00ff) == ((myTops[index]+1) & 0xff)) if((myCounters[index] & 0x00ff) == ((myTops[index]+1) & 0xff))
{ {
@ -190,60 +252,48 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
{ {
myFlags[index] = 0x00; myFlags[index] = 0x00;
} }
switch(function) switch(function)
{ {
case 0x00: case 0x00:
{ {
switch(index) switch(index)
{ {
case 0x00: // advance and return byte 0 of random case 0x00: // RANDOM0NEXT - advance and return byte 0 of random
clockRandomNumberGenerator(); clockRandomNumberGenerator();
result = myRandomNumber & 0xFF; result = myRandomNumber & 0xFF;
break; break;
case 0x01: // return to prior and return byte 0 of random case 0x01: // RANDOM0PRIOR - return to prior and return byte 0 of random
priorClockRandomNumberGenerator(); priorClockRandomNumberGenerator();
result = myRandomNumber & 0xFF; result = myRandomNumber & 0xFF;
break; break;
case 0x02: case 0x02: // RANDOM1
result = (myRandomNumber>>8) & 0xFF; result = (myRandomNumber>>8) & 0xFF;
break; break;
case 0x03: case 0x03: // RANDOM2
result = (myRandomNumber>>16) & 0xFF; result = (myRandomNumber>>16) & 0xFF;
break; break;
case 0x04: case 0x04: // RANDOM3
result = (myRandomNumber>>24) & 0xFF; result = (myRandomNumber>>24) & 0xFF;
break; break;
case 0x05: // No, it's a music read case 0x05: // AMPLITUDE
{ {
static const uInt8 musicAmplitudes[8] = {
0x00, 0x04, 0x05, 0x09, 0x06, 0x0a, 0x0b, 0x0f
};
// Update the music data fetchers (counter & flag) // Update the music data fetchers (counter & flag)
updateMusicModeDataFetchers(); updateMusicModeDataFetchers();
uInt8 i = 0; uInt32 i = 0;
if(myMusicVolumes[0] && (myMusicCounters[0]>>31))
{ i = myMusicVolume + ((myMusicVolume >> 12) * (uInt8) (myMusicWaveforms[0] >> 31)) +
i |= 0x01; ((myMusicVolume >> 16) * (uInt8) (myMusicWaveforms[1] >> 31)) +
} ((myMusicVolume >> 24) * (uInt8) (myMusicWaveforms[2] >> 31));
if(myMusicVolumes[1] && (myMusicCounters[1]>>31))
{ result = (uInt8)i;
i |= 0x02; break;
}
if(myMusicVolumes[2] && (myMusicCounters[2]>>31))
{
i |= 0x04;
}
result = musicAmplitudes[i];
break;
} }
case 0x06: // reserved case 0x06: // reserved
@ -252,39 +302,39 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
} }
break; break;
} }
// DFx display data read // DFxDATA - display data read
case 0x01: case 0x01:
{ {
result = myDisplayImage[myCounters[index]]; result = myDisplayImage[myCounters[index]];
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
break; break;
} }
// DFx display data read AND'd w/flag // DFxDATAW - display data read AND'd w/flag ("windowed")
case 0x02: case 0x02:
{ {
result = myDisplayImage[myCounters[index]] & myFlags[index]; result = myDisplayImage[myCounters[index]] & myFlags[index];
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
break; break;
} }
// DFx display data read w/fractional increment // DFxFRACDATA - display data read w/fractional increment
case 0x03: case 0x03:
{ {
result = myDisplayImage[myFractionalCounters[index] >> 8]; result = myDisplayImage[myFractionalCounters[index] >> 8];
myFractionalCounters[index] = (myFractionalCounters[index] + myFractionalIncrements[index]) & 0x0fffff; myFractionalCounters[index] = (myFractionalCounters[index] + myFractionalIncrements[index]) & 0x0fffff;
break; break;
} }
case 0x04: case 0x04:
{ {
switch (index) switch (index)
{ {
case 0x00: case 0x00: // DF0FLAG
case 0x01: case 0x01: // DF1FLAG
case 0x02: case 0x02: // DF2FLAG
case 0x03: case 0x03: // DF3FLAG
{ {
result = myFlags[index]; result = myFlags[index];
break; break;
@ -295,15 +345,15 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
case 0x07: // reserved case 0x07: // reserved
break; break;
} }
break; break;
} }
default: default:
{ {
result = 0; result = 0;
} }
} }
return result; return result;
} }
else else
@ -315,36 +365,36 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
// Set the current bank to the first 4k bank // Set the current bank to the first 4k bank
bank(0); bank(0);
break; break;
case 0x0FF7: case 0x0FF7:
// Set the current bank to the second 4k bank // Set the current bank to the second 4k bank
bank(1); bank(1);
break; break;
case 0x0FF8: case 0x0FF8:
// Set the current bank to the third 4k bank // Set the current bank to the third 4k bank
bank(2); bank(2);
break; break;
case 0x0FF9: case 0x0FF9:
// Set the current bank to the fourth 4k bank // Set the current bank to the fourth 4k bank
bank(3); bank(3);
break; break;
case 0x0FFA: case 0x0FFA:
// Set the current bank to the fifth 4k bank // Set the current bank to the fifth 4k bank
bank(4); bank(4);
break; break;
case 0x0FFB: case 0x0FFB:
// Set the current bank to the last 4k bank // Set the current bank to the last 4k bank
bank(5); bank(5);
break; break;
default: default:
break; break;
} }
if(myFastFetch) if(myFastFetch)
myLDAimmediate = (peekvalue == 0xA9); myLDAimmediate = (peekvalue == 0xA9);
@ -356,208 +406,130 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value) bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
{ {
address &= 0x0FFF; address &= 0x0FFF;
if((address >= 0x0028) && (address < 0x0080)) if((address >= 0x0028) && (address < 0x0080))
{ {
// Get the index of the data fetcher that's being accessed // Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x07; uInt32 index = address & 0x07;
uInt32 function = ((address - 0x28) >> 3) & 0x0f; uInt32 function = ((address - 0x28) >> 3) & 0x0f;
switch(function) switch(function)
{ {
//DFxFrac counter low //DFxFRACLOW - fractional data pointer low byte
case 0x00: case 0x00:
{
myFractionalCounters[index] = (myFractionalCounters[index] & 0x0F0000) | ((uInt16)value << 8); myFractionalCounters[index] = (myFractionalCounters[index] & 0x0F0000) | ((uInt16)value << 8);
break; break;
}
// DFxFRACHI - fractional data pointer high byte
// DFxFrac counter high
case 0x01: case 0x01:
{
myFractionalCounters[index] = (((uInt16)value & 0x0F) << 16) | (myFractionalCounters[index] & 0x00ffff); myFractionalCounters[index] = (((uInt16)value & 0x0F) << 16) | (myFractionalCounters[index] & 0x00ffff);
break; break;
}
//DFxFRACINC - Fractional Increment amount
//DFx Fraction Increment amount
case 0x02: case 0x02:
{
myFractionalIncrements[index] = value; myFractionalIncrements[index] = value;
myFractionalCounters[index] = myFractionalCounters[index] & 0x0FFF00; myFractionalCounters[index] = myFractionalCounters[index] & 0x0FFF00;
break; break;
}
// DFx top count // DFxTOP - set top of window (for reads of DFxDATAW)
case 0x03: case 0x03:
{
myTops[index] = value; myTops[index] = value;
myFlags[index] = 0x00; myFlags[index] = 0x00;
break; break;
}
// DFxBOT - set bottom of window (for reads of DFxDATAW)
// DFx bottom count
case 0x04: case 0x04:
{
myBottoms[index] = value; myBottoms[index] = value;
break; break;
}
// DFxLOW - data pointer low byte
// DFx counter low
case 0x05: case 0x05:
{
myCounters[index] = (myCounters[index] & 0x0F00) | value ; myCounters[index] = (myCounters[index] & 0x0F00) | value ;
break; break;
}
// Control registers // Control registers
case 0x06: case 0x06:
{
switch (index) switch (index)
{ {
// FastFetch control case 0x00: // FASTFETCH - turns on LDA #<DFxDATA mode of value is 0
case 0x00:
{
myFastFetch = (value == 0); myFastFetch = (value == 0);
break; break;
}
// SelectByte case 0x01: // SELECTBYTE - set byte to update in writeByte()
case 0x01:
{
mySelectByte = value; mySelectByte = value;
break; break;
}
// Write Byte case 0x02: // WRITEBYTE
case 0x02: writeByte(value);
{
switch (mySelectByte)
{
case 0x00:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFFFFFF00) | value;
break;
}
case 0x01:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFFFF00FF) | (value<<8);
break;
}
case 0x02:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0xFF00FFFF) | (value<<16);
break;
}
case 0x03:
{
myMusicWaveforms[0] = (myMusicWaveforms[0] & 0x00FFFFFF) | (value<<24);
break;
}
case 0x04:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFFFFFF00) | value;
break;
}
case 0x05:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFFFF00FF) | (value<<8);
break;
}
case 0x06:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0xFF00FFFF) | (value<<16);
break;
}
case 0x07:
{
myMusicWaveforms[1] = (myMusicWaveforms[1] & 0x00FFFFFF) | (value<<24);
break;
}
case 0x08:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFFFFFF00) | value;
break;
}
case 0x09:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFFFF00FF) | (value<<8);
break;
}
case 0x0A:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0xFF00FFFF) | (value<<16);
break;
}
case 0x0B:
{
myMusicWaveforms[2] = (myMusicWaveforms[2] & 0x00FFFFFF) | (value<<24);
break;
}
}
break; break;
}
case 0x03: // reserved case 0x03: // reserved
case 0x04: // reserved case 0x04: // reserved
break; break;
case 0x05:
case 0x06: case 0x05: // VOLUME0
case 0x07: myMusicVolume = (myMusicVolume & 0xFFFF00FF) | ((value & 0x0F)<<12);
{
myMusicVolumes[index - 5] = (value & 0x0F);
break; break;
}
break; case 0x06: // VOLUME1
myMusicVolume = (myMusicVolume & 0xFF00FFFF) | ((value & 0x0F)<<16);
break;
case 0x07: // VOLUME2
myMusicVolume = (myMusicVolume & 0x00FFFFFF) | ((value & 0x0F)<<24);
break;
} }
break; break;
}
// DF Push // DFxPUSH - Push value into data bank
case 0x07: case 0x07:
{ {
myCounters[index] = (myCounters[index] - 0x1) & 0x0fff; myCounters[index] = (myCounters[index] - 0x1) & 0x0fff;
myDisplayImage[myCounters[index]] = value; myDisplayImage[myCounters[index]] = value;
break; break;
} }
// DFx counter hi, same as counter high, but w/out music mode // DFxHI - data pointer high byte
case 0x08: case 0x08:
{ {
myCounters[index] = (((uInt16)value & 0x0F) << 8) | (myCounters[index] & 0x00ff); myCounters[index] = (((uInt16)value & 0x0F) << 8) | (myCounters[index] & 0x00ff);
break; break;
} }
// Random Number Generator Reset
case 0x09: case 0x09:
{ {
switch (index) switch (index)
{ {
case 0x00: case 0x00: // RRESET - Random Number Generator Reset
{ {
myRandomNumber = 0x2B435044; // "DPC+" myRandomNumber = 0x2B435044; // "DPC+"
break; break;
} }
case 0x01: case 0x01: // RWRITE0 - update byte 0 of random number
{ {
myRandomNumber = (myRandomNumber & 0xFFFFFF00) | value; myRandomNumber = (myRandomNumber & 0xFFFFFF00) | value;
break; break;
} }
case 0x02: case 0x02: // RWRITE1 - update byte 1 of random number
{ {
myRandomNumber = (myRandomNumber & 0xFFFF00FF) | (value<<8); myRandomNumber = (myRandomNumber & 0xFFFF00FF) | (value<<8);
break; break;
} }
case 0x03: case 0x03: // RWRITE2 - update byte 2 of random number
{ {
myRandomNumber = (myRandomNumber & 0xFF00FFFF) | (value<<16); myRandomNumber = (myRandomNumber & 0xFF00FFFF) | (value<<16);
break; break;
} }
case 0x04: case 0x04: // RWRITE3 - update byte 3 of random number
{ {
myRandomNumber = (myRandomNumber & 0x00FFFFFF) | (value<<24); myRandomNumber = (myRandomNumber & 0x00FFFFFF) | (value<<24);
break; break;
} }
case 0x05: case 0x05: // NOTE0
case 0x06: case 0x06: // NOTE1
case 0x07: case 0x07: // NOTE2
{ {
myMusicFrequencies[index-5] = myFrequencyImage[(value<<2)] + myMusicFrequencies[index-5] = myFrequencyImage[(value<<2)] +
(myFrequencyImage[(value<<2)+1]<<8) + (myFrequencyImage[(value<<2)+1]<<8) +
(myFrequencyImage[(value<<2)+2]<<16) + (myFrequencyImage[(value<<2)+2]<<16) +
@ -569,20 +541,20 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
} }
break; break;
} }
// DF Write // DFxWRITE - write into data bank
case 0x0a: case 0x0a:
{ {
myDisplayImage[myCounters[index]] = value; myDisplayImage[myCounters[index]] = value;
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff; myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
break; break;
} }
default: default:
{ {
break; break;
} }
} }
} }
else else
{ {
@ -593,32 +565,32 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
// Set the current bank to the first 4k bank // Set the current bank to the first 4k bank
bank(0); bank(0);
break; break;
case 0x0FF7: case 0x0FF7:
// Set the current bank to the second 4k bank // Set the current bank to the second 4k bank
bank(1); bank(1);
break; break;
case 0x0FF8: case 0x0FF8:
// Set the current bank to the third 4k bank // Set the current bank to the third 4k bank
bank(2); bank(2);
break; break;
case 0x0FF9: case 0x0FF9:
// Set the current bank to the fourth 4k bank // Set the current bank to the fourth 4k bank
bank(3); bank(3);
break; break;
case 0x0FFA: case 0x0FFA:
// Set the current bank to the fifth 4k bank // Set the current bank to the fifth 4k bank
bank(4); bank(4);
break; break;
case 0x0FFB: case 0x0FFB:
// Set the current bank to the last 4k bank // Set the current bank to the last 4k bank
bank(5); bank(5);
break; break;
default: default:
break; break;
} }
@ -628,7 +600,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDPCPlus::bank(uInt16 bank) void CartridgeDPCPlus::bank(uInt16 bank)
{ {
if(bankLocked()) return; if(bankLocked()) return;
// Remember what bank we're in // Remember what bank we're in
@ -662,7 +634,7 @@ bool CartridgeDPCPlus::patch(uInt16 address, uInt8 value)
} }
else else
return false; return false;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeDPCPlus::getImage(int& size) const const uInt8* CartridgeDPCPlus::getImage(int& size) const
@ -699,7 +671,7 @@ bool CartridgeDPCPlus::save(Serializer& out) const
out.putInt(8); out.putInt(8);
for(i = 0; i < 8; ++i) for(i = 0; i < 8; ++i)
out.putInt(myCounters[i]); out.putInt(myCounters[i]);
// The counter registers for the fractional data fetchers // The counter registers for the fractional data fetchers
out.putInt(8); out.putInt(8);
for(i = 0; i < 8; ++i) for(i = 0; i < 8; ++i)
@ -717,24 +689,20 @@ bool CartridgeDPCPlus::save(Serializer& out) const
// The Fast Fetcher Enabled flag // The Fast Fetcher Enabled flag
out.putBool(myFastFetch); out.putBool(myFastFetch);
// Last immediate byte peeked
out.putBool(myLDAimmediate); out.putBool(myLDAimmediate);
// Control byte // Control Byte to update
out.putByte((char)mySelectByte); out.putByte((char) mySelectByte);
// The music volumes for the data fetchers // The music volume
out.putInt(myMusicVolume);
// The music counters
out.putInt(3); out.putInt(3);
for(i = 0; i < 3; ++i) for(i = 0; i < 3; ++i)
out.putByte((char)myMusicVolumes[i]); out.putInt(myMusicCounters[i]);
// The music mode counters for the data fetchers // The music frequencies
out.putInt(3);
for(i = 0; i < 3; ++i)
out.putInt(myMusicCounters[i]);
// The music mode frequency addends for the data fetchers
out.putInt(3); out.putInt(3);
for(i = 0; i < 3; ++i) for(i = 0; i < 3; ++i)
out.putInt(myMusicFrequencies[i]); out.putInt(myMusicFrequencies[i]);
@ -806,32 +774,28 @@ bool CartridgeDPCPlus::load(Serializer& in)
// The Fast Fetcher Enabled flag // The Fast Fetcher Enabled flag
myFastFetch = in.getBool(); myFastFetch = in.getBool();
// Last immediate byte peeked
myLDAimmediate = in.getBool(); myLDAimmediate = in.getBool();
// Control byte // Control Byte to update
mySelectByte = (uInt8) in.getByte(); mySelectByte = (uInt8) in.getByte();
// The music mode flags for the data fetchers // The music volume
limit = (uInt32) in.getInt(); myMusicVolume = (uInt32) in.getInt();
for(i = 0; i < limit; ++i)
myMusicVolumes[i] = (uInt8) in.getByte();
// The music mode counters for the data fetchers // The music mode counters for the data fetchers
limit = (uInt32) in.getInt(); limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i) for(i = 0; i < limit; ++i)
myMusicCounters[i] = (uInt32) in.getInt(); myMusicCounters[i] = (uInt32) in.getInt();
// The music mode frequency addends for the data fetchers // The music mode frequency addends for the data fetchers
limit = (uInt32) in.getInt(); limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i) for(i = 0; i < limit; ++i)
myMusicFrequencies[i] = (uInt32) in.getInt(); myMusicFrequencies[i] = (uInt32) in.getInt();
// The music waveforms // The music waveforms
limit = (uInt32) in.getInt(); limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i) for(i = 0; i < limit; ++i)
myMusicWaveforms[i] = (uInt32) in.getInt(); myMusicWaveforms[i] = (uInt32) in.getInt();
// The random number generator register // The random number generator register
myRandomNumber = (uInt32) in.getInt(); myRandomNumber = (uInt32) in.getInt();

View File

@ -159,6 +159,11 @@ class CartridgeDPCPlus : public Cartridge
*/ */
inline void updateMusicModeDataFetchers(); inline void updateMusicModeDataFetchers();
/**
Writes a control byte
*/
inline void writeByte(uInt8 value);
private: private:
// Indicates which bank is currently active // Indicates which bank is currently active
uInt16 myCurrentBank; uInt16 myCurrentBank;
@ -202,13 +207,13 @@ class CartridgeDPCPlus : public Cartridge
// Control Byte to update // Control Byte to update
uInt8 mySelectByte; uInt8 mySelectByte;
// The music volumes // The music volume
uInt8 myMusicVolumes[3]; uInt32 myMusicVolume;
// The music mode counters // The music mode counters
uInt32 myMusicCounters[3]; uInt32 myMusicCounters[3];
// The music frequency addends // The music frequency
uInt32 myMusicFrequencies[3]; uInt32 myMusicFrequencies[3];
// The music waveforms // The music waveforms