mirror of https://github.com/stella-emu/stella.git
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:
parent
1103f1dfbb
commit
a94c579fec
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue