First pass at getting function parsing working again in the debugger.

Added latest DPC+ code from Spiceware.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1986 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-04-03 12:45:20 +00:00
parent 0d367461a4
commit 7bd307ebc8
14 changed files with 323 additions and 194 deletions

View File

@ -43,11 +43,23 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const RamAreaList& areas)
// We know the address for the startup bank right now
myStartAddresses[myConsole.cartridge().startBank()] = myDebugger.dpeek(0xfffc);
// Add system equates
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
mySystemAddresses.insert(make_pair(ourTIAMnemonicR[addr], addr));
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
mySystemAddresses.insert(make_pair(ourTIAMnemonicW[addr], addr));
for(uInt16 addr = 0x280; addr <= 0x297; ++addr)
mySystemAddresses.insert(make_pair(ourIOMnemonic[addr-0x280], addr));
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartDebug::~CartDebug()
{
myUserLabels.clear();
myUserAddresses.clear();
mySystemAddresses.clear();
delete[] myStartAddresses;
}
@ -211,15 +223,6 @@ bool CartDebug::disassemble(const string& autocode, bool force)
if(!(start & 0x1000))
return false;
#if 0
cerr << "start addresses: ";
for(int i = 0; i < myConsole.cartridge().bankCount(); ++i) cerr << " " << setw(4) << hex << myStartAddresses[i];
cerr << endl;
cerr << "current bank = " << getBank() << ", start bank = " << myConsole.cartridge().startBank() << endl
<< "reset = " << hex << 0xfffc << ", pc = " << hex << PC << endl
<< "start = " << hex << start << endl << endl;
#endif
// Check whether to use the 'autocode' functionality from Distella
if(autocode == "0") // 'never'
fillDisassemblyList(start, false, PC);
@ -319,20 +322,20 @@ string CartDebug::getCartType()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartDebug::addLabel(const string& label, uInt16 address)
bool CartDebug::addLabel(const string& label, uInt16 address)
{
// Only user-defined labels can be added
// Only user-defined labels can be added or redefined
switch(addressType(address))
{
case ADDR_TIA:
case ADDR_RIOT:
return;
return false;
default:
cerr << "addLabel: label = " << label << ", address = " << hex << address << endl;
removeLabel(label);
myUserAddresses.insert(make_pair(label, address));
myUserLabels.insert(make_pair(address, label));
break;
return true;
}
}
@ -395,17 +398,14 @@ const string& CartDebug::getLabel(uInt16 addr, bool isRead, int places) const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CartDebug::getAddress(const string& label) const
{
/* FIXME
LabelToAddr::const_iterator iter;
if((iter = mySystemAddresses.find(label)) != mySystemAddresses.end())
return iter->second.address;
return iter->second;
else if((iter = myUserAddresses.find(label)) != myUserAddresses.end())
return iter->second.address;
return iter->second;
else
return -1;
*/
return -1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -69,12 +69,12 @@ class CartDebug : public DebuggerSystem
// The following assume that the given addresses are using the
// correct read/write port ranges; no checking will be done to
// confirm this.
uInt8 read(uInt16 addr);
void write(uInt16 addr, uInt8 value);
uInt8 read(uInt16 address);
void write(uInt16 address, uInt8 value);
// Indicate that a read from write port has occurred at the specified
// address.
void triggerReadFromWritePort(uInt16 addr);
void triggerReadFromWritePort(uInt16 address);
// Return the address at which an invalid read was performed in a
// write port area.
@ -114,20 +114,40 @@ class CartDebug : public DebuggerSystem
const DisassemblyList& disassemblyList() const { return myDisassembly; }
/**
Determine the line in the disassembly that corresponds to the given
address. A value of -1 indicates that no such address exists.
Determine the line in the disassembly that corresponds to the given address.
@param address The address to search for
@return Line number of the address, else -1 if no such address exists
*/
int addressToLine(uInt16 address) const;
/**
Disassemble from the starting address the specified number of lines.
Note that automatic code determination is turned off for this method;
it will treat all address contents as instructions.
@param start The start address for disassembly
@param lines The number of disassembled lines to generate
@return The disassembly represented as a string
*/
string disassemble(uInt16 start, uInt16 lines) const;
// The following are convenience methods that query the cartridge object
// for the desired information.
/**
Get the current bank in use by the cartridge.
*/
int getBank();
/**
Get the total number of banks supported by the cartridge.
*/
int bankCount();
/**
Get the name/type of the cartridge.
*/
string getCartType();
////////////////////////////////////////
@ -135,7 +155,7 @@ class CartDebug : public DebuggerSystem
Add a label and associated address.
Labels that reference either TIA or RIOT spaces will not be processed.
*/
void addLabel(const string& label, uInt16 address);
bool addLabel(const string& label, uInt16 address);
/**
Remove the given label and its associated address.
@ -215,6 +235,13 @@ class CartDebug : public DebuggerSystem
AddrToLabel myUserLabels;
LabelToAddr myUserAddresses;
// Mappings for labels to addresses for system-defined equates
// Because system equate addresses can have different names
// (depending on access in read vs. write mode), we can only create
// a mapping from labels to addresses; addresses to labels are
// handled differently
LabelToAddr mySystemAddresses;
string myCompletions;
string myCompPrefix;

View File

@ -333,17 +333,18 @@ void Debugger::autoExec()
myPrompt->print("autoExec():\n" + myParser->exec(file) + "\n");
myPrompt->printPrompt();
/* FIXME - get these working again
// Init builtins
for(int i = 0; builtin_functions[i][0] != ""; i++)
{
// TODO - check this for memory leaks
int res = YaccParser::parse(builtin_functions[i][1].c_str());
if(res != 0) cerr << "ERROR in builtin function!" << endl;
Expression* exp = YaccParser::getResult();
addFunction(builtin_functions[i][0], builtin_functions[i][1], exp, true);
if(res != 0)
{
cerr << "ERROR in builtin function!" << endl;
Expression* exp = YaccParser::getResult();
addFunction(builtin_functions[i][0], builtin_functions[i][1], exp, true);
}
}
*/
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -340,16 +340,12 @@ string Cartridge::autodetectType(const uInt8* image, uInt32 size)
else
type = "F8";
}
else if((size == 10495) || (size == 10496) || (size == 10240)) // 10K - Pitfall2
else if(size >= 10240 && size <= 10496) // ~10K - Pitfall2
{
type = "DPC";
}
else if(size == 12*1024) // 12K
{
// TODO - this should really be in a method that checks the first
// 512 bytes of ROM and finds if either the lower 256 bytes or
// higher 256 bytes are all the same. For now, we assume that
// all carts of 12K are CBS RAM Plus/FA.
type = "FA";
}
else if(size == 16*1024) // 16K

View File

@ -1,8 +1,8 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
@ -27,6 +27,8 @@
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size)
: myFastFetch(false),
myLDAimmediate(false),
mySelectByte(0),
mySystemCycles(0),
myFractionalClocks(0.0)
{
@ -39,7 +41,7 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size)
// Copy the display ROM image into my buffer
memcpy(myDisplayImage, image + 4096 * 6, 4096);
// Copy the Frequency ROM image into my buffer
memcpy(myFrequencyImage, image + 4096 * 6 + 4096, 1024);
@ -48,7 +50,10 @@ CartridgeDPCPlus::CartridgeDPCPlus(const uInt8* image, uInt32 size)
myTops[i] = myBottoms[i] = myCounters[i] = myFlags[i] = myFractionalIncrements[i] = 0;
// None of the data fetchers are in music mode
myMusicMode[0] = myMusicMode[1] = myMusicMode[2] = false;
myMusicVolumes[0] = myMusicVolumes[1] = myMusicVolumes[2] = 0;
// Set waveforms to square waves
myMusicWaveforms[0] = myMusicWaveforms[1] = myMusicWaveforms[2] = 0xAAAAAAAA;
// Initialize the DPC's random number generator register (must be non-zero)
myRandomNumber = 0x2B435044; // "DPC+"
@ -89,10 +94,10 @@ void CartridgeDPCPlus::install(System& system)
mySystem = &system;
uInt16 shift = mySystem->pageShift();
uInt16 mask = mySystem->pageMask();
// Make sure the system we're being installed in has a page size that'll work
assert(((0x1080 & mask) == 0) && ((0x1100 & mask) == 0));
// Map all of the accesses to call peek and poke
System::PageAccess access;
access.directPeekBase = 0;
@ -100,7 +105,7 @@ void CartridgeDPCPlus::install(System& system)
access.device = this;
for(uInt32 i = 0x1000; i < 0x2000; i += (1 << shift))
mySystem->setPageAccess(i >> shift, access);
// Install pages for the startup bank
bank(myStartBank);
}
@ -140,9 +145,9 @@ inline void CartridgeDPCPlus::updateMusicModeDataFetchers()
for(int x = 5; x <= 7; ++x)
{
// Update only if the data fetcher is in music mode
if(myMusicMode[x - 5])
if(myMusicVolumes[x - 5])
{
myMusicCounter[x - 5] += myMusicFrequency[x - 5];
myMusicCounters[x - 5] += myMusicFrequencies[x - 5];
}
}
}
@ -153,28 +158,29 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
address &= 0x0FFF;
uInt8 peekvalue = myProgramImage[(myCurrentBank << 12) + address];
// In debugger/bank-locked mode, we ignore all hotspots and in general
// anything that can change the internal state of the cart
if(bankLocked())
return peekvalue;
// Check if we're in Fast Fetch mode and the prior byte was an A9 (LDA #value)
if(myFastFetch && myLDAimmediate)
{
peekvalue = myProgramImage[(myCurrentBank << 12) + address];
// if #value is a read-register then we want to use that as the address
if(peekvalue < 0x0028)
address = peekvalue;
}
myLDAimmediate = false;
if(address < 0x0028)
{
uInt8 result = 0;
// Get the index of the data fetcher that's being accessed
uInt32 index = address & 0x07;
uInt32 function = (address >> 3) & 0x07;
// Update flag register for selected data fetcher
if((myCounters[index] & 0x00ff) == ((myTops[index]+1) & 0xff))
{
@ -184,7 +190,7 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
{
myFlags[index] = 0x00;
}
switch(function)
{
case 0x00:
@ -195,49 +201,49 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
clockRandomNumberGenerator();
result = myRandomNumber & 0xFF;
break;
case 0x01: // return to prior and return byte 0 of random
priorClockRandomNumberGenerator();
result = myRandomNumber & 0xFF;
break;
case 0x02:
result = (myRandomNumber>>8) & 0xFF;
break;
case 0x03:
result = (myRandomNumber>>16) & 0xFF;
break;
case 0x04:
result = (myRandomNumber>>24) & 0xFF;
break;
case 0x05: // No, it's a music read
{
static const uInt8 musicAmplitudes[8] = {
0x00, 0x04, 0x05, 0x09, 0x06, 0x0a, 0x0b, 0x0f
};
// Update the music data fetchers (counter & flag)
updateMusicModeDataFetchers();
uInt8 i = 0;
if(myMusicMode[0] && (myMusicCounter[0]>>31))
if(myMusicVolumes[0] && (myMusicCounters[0]>>31))
{
i |= 0x01;
}
if(myMusicMode[1] && (myMusicCounter[1]>>31))
if(myMusicVolumes[1] && (myMusicCounters[1]>>31))
{
i |= 0x02;
}
if(myMusicMode[2] && (myMusicCounter[2]>>31))
if(myMusicVolumes[2] && (myMusicCounters[2]>>31))
{
i |= 0x04;
}
result = musicAmplitudes[i];
break;
break;
}
case 0x06: // reserved
@ -246,30 +252,30 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
}
break;
}
// DFx display data read
case 0x01:
{
result = myDisplayImage[myCounters[index]];
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
break;
}
// DFx display data read AND'd w/flag
case 0x02:
{
result = myDisplayImage[myCounters[index]] & myFlags[index];
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
break;
}
}
// DFx display data read w/fractional increment
case 0x03:
{
result = myDisplayImage[myFractionalCounters[index] >> 8];
myFractionalCounters[index] = (myFractionalCounters[index] + myFractionalIncrements[index]) & 0x0fffff;
myFractionalCounters[index] = (myFractionalCounters[index] + myFractionalIncrements[index]) & 0x0fffff;
break;
}
}
case 0x04:
{
@ -289,15 +295,15 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
case 0x07: // reserved
break;
}
break;
break;
}
default:
{
result = 0;
}
}
return result;
}
else
@ -309,37 +315,36 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
// Set the current bank to the first 4k bank
bank(0);
break;
case 0x0FF7:
// Set the current bank to the second 4k bank
bank(1);
break;
case 0x0FF8:
// Set the current bank to the third 4k bank
bank(2);
break;
case 0x0FF9:
// Set the current bank to the fourth 4k bank
bank(3);
break;
case 0x0FFA:
// Set the current bank to the fifth 4k bank
bank(4);
break;
case 0x0FFB:
// Set the current bank to the last 4k bank
bank(5);
break;
default:
break;
}
peekvalue = myProgramImage[(myCurrentBank << 12) + address];
if(myFastFetch)
myLDAimmediate = (peekvalue == 0xA9);
@ -351,13 +356,13 @@ uInt8 CartridgeDPCPlus::peek(uInt16 address)
bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
{
address &= 0x0FFF;
if((address >= 0x0028) && (address < 0x0080))
if((address >= 0x0028) && (address < 0x0080))
{
// 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;
switch(function)
{
//DFxFrac counter low
@ -366,14 +371,15 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
myFractionalCounters[index] = (myFractionalCounters[index] & 0x0F0000) | ((uInt16)value << 8);
break;
}
// DFxFrac counter high
case 0x01:
{
myFractionalCounters[index] = (((uInt16)value & 0x0F) << 16) | (myFractionalCounters[index] & 0x00ffff);
break;
}
//DFx Fraction Increment amount
case 0x02:
{
myFractionalIncrements[index] = value;
@ -388,34 +394,106 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
myFlags[index] = 0x00;
break;
}
// DFx bottom count
case 0x04:
{
myBottoms[index] = value;
break;
}
// DFx counter low
case 0x05:
{
myCounters[index] = (myCounters[index] & 0x0F00) | value ;
break;
}
// Control registers
case 0x06:
{
switch (index)
{
// FastFetch control
// FastFetch control
case 0x00:
{
myFastFetch = (value == 0);
break;
}
case 0x01: // reserved
case 0x02: // reserved
// SelectByte
case 0x01:
{
mySelectByte = value;
break;
}
// Write Byte
case 0x02:
{
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;
}
case 0x03: // reserved
case 0x04: // reserved
break;
@ -423,7 +501,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
case 0x06:
case 0x07:
{
myMusicMode[index - 5] = (value & 0x10);
myMusicVolumes[index - 5] = (value & 0x0F);
break;
}
break;
@ -438,14 +516,14 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
myDisplayImage[myCounters[index]] = value;
break;
}
// DFx counter hi, same as counter high, but w/out music mode
case 0x08:
{
myCounters[index] = (((uInt16)value & 0x0F) << 8) | (myCounters[index] & 0x00ff);
break;
}
}
// Random Number Generator Reset
case 0x09:
{
@ -478,9 +556,9 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
}
case 0x05:
case 0x06:
case 0x07:
{
myMusicFrequency[index-5] = myFrequencyImage[(value<<2)] +
case 0x07:
{
myMusicFrequencies[index-5] = myFrequencyImage[(value<<2)] +
(myFrequencyImage[(value<<2)+1]<<8) +
(myFrequencyImage[(value<<2)+2]<<16) +
(myFrequencyImage[(value<<2)+3]<<24);
@ -491,7 +569,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
}
break;
}
// DF Write
case 0x0a:
{
@ -499,12 +577,12 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
myCounters[index] = (myCounters[index] + 0x1) & 0x0fff;
break;
}
default:
{
break;
}
}
}
}
else
{
@ -515,32 +593,32 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
// Set the current bank to the first 4k bank
bank(0);
break;
case 0x0FF7:
// Set the current bank to the second 4k bank
bank(1);
break;
case 0x0FF8:
// Set the current bank to the third 4k bank
bank(2);
break;
case 0x0FF9:
// Set the current bank to the fourth 4k bank
bank(3);
break;
case 0x0FFA:
// Set the current bank to the fifth 4k bank
bank(4);
break;
case 0x0FFB:
// Set the current bank to the last 4k bank
bank(5);
break;
default:
break;
}
@ -550,7 +628,7 @@ bool CartridgeDPCPlus::poke(uInt16 address, uInt8 value)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartridgeDPCPlus::bank(uInt16 bank)
{
{
if(bankLocked()) return;
// Remember what bank we're in
@ -584,7 +662,7 @@ bool CartridgeDPCPlus::patch(uInt16 address, uInt8 value)
}
else
return false;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt8* CartridgeDPCPlus::getImage(int& size) const
@ -621,7 +699,7 @@ bool CartridgeDPCPlus::save(Serializer& out) const
out.putInt(8);
for(i = 0; i < 8; ++i)
out.putInt(myCounters[i]);
// The counter registers for the fractional data fetchers
out.putInt(8);
for(i = 0; i < 8; ++i)
@ -639,23 +717,33 @@ bool CartridgeDPCPlus::save(Serializer& out) const
// The Fast Fetcher Enabled flag
out.putBool(myFastFetch);
// Last immediate byte peeked
out.putBool(myLDAimmediate);
// The music mode flags for the data fetchers
// Control byte
out.putByte((char)mySelectByte);
// The music volumes for the data fetchers
out.putInt(3);
for(i = 0; i < 3; ++i)
out.putBool(myMusicMode[i]);
out.putByte((char)myMusicVolumes[i]);
// The music mode counters for the data fetchers
out.putInt(3);
for(i = 0; i < 3; ++i)
out.putInt(myMusicCounter[i]);
out.putInt(myMusicCounters[i]);
// The music mode frequency addends for the data fetchers
out.putInt(3);
for(i = 0; i < 3; ++i)
out.putInt(myMusicFrequency[i]);
out.putInt(myMusicFrequencies[i]);
// The music waveforms
out.putInt(3);
for(i = 0; i < 3; ++i)
out.putInt(myMusicWaveforms[i]);
// The random number generator register
out.putInt(myRandomNumber);
@ -718,22 +806,32 @@ bool CartridgeDPCPlus::load(Serializer& in)
// The Fast Fetcher Enabled flag
myFastFetch = in.getBool();
// Last immediate byte peeked
myLDAimmediate = in.getBool();
// Control byte
mySelectByte = (uInt8) in.getByte();
// The music mode flags for the data fetchers
limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i)
myMusicMode[i] = in.getBool();
myMusicVolumes[i] = (uInt8) in.getByte();
// The music mode counters for the data fetchers
limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i)
myMusicCounter[i] = (uInt32) in.getInt();
myMusicCounters[i] = (uInt32) in.getInt();
// The music mode frequency addends for the data fetchers
limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i)
myMusicFrequency[i] = (uInt32) in.getInt();
myMusicFrequencies[i] = (uInt32) in.getInt();
// The music waveforms
limit = (uInt32) in.getInt();
for(i = 0; i < limit; ++i)
myMusicWaveforms[i] = (uInt32) in.getInt();
// The random number generator register
myRandomNumber = (uInt32) in.getInt();

View File

@ -1,8 +1,8 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
@ -195,16 +195,24 @@ class CartridgeDPCPlus : public Cartridge
// The Fast Fetcher Enabled flag
bool myFastFetch;
// Flags that last byte peeked was A9 (LDA #)
bool myLDAimmediate;
// The music mode DF5, DF6, & DF7 enabled flags
bool myMusicMode[3];
// Control Byte to update
uInt8 mySelectByte;
// The music volumes
uInt8 myMusicVolumes[3];
// The music mode counters
uInt32 myMusicCounter[3];
uInt32 myMusicCounters[3];
// The music frequency addends
uInt32 myMusicFrequency[3];
uInt32 myMusicFrequencies[3];
// The music waveforms
uInt32 myMusicWaveforms[3];
// The random number generator register
uInt32 myRandomNumber;

View File

@ -1080,14 +1080,12 @@ uInt32 Console::ourUserSECAMPalette[256] = { 0 }; // filled from external file
Console::Console(const Console& console)
: myOSystem(console.myOSystem)
{
// TODO: Write this method
assert(false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Console& Console::operator = (const Console&)
{
// TODO: Write this method
assert(false);
return *this;

View File

@ -192,11 +192,10 @@ class M6502 : public Serializable
*/
void attach(Debugger& debugger);
// TODO - document these methods
void setBreakPoints(PackedBitArray *bp);
void setTraps(PackedBitArray *read, PackedBitArray *write);
void setBreakPoints(PackedBitArray* bp);
void setTraps(PackedBitArray* read, PackedBitArray* write);
unsigned int addCondBreak(Expression *e, const string& name);
unsigned int addCondBreak(Expression* e, const string& name);
void delCondBreak(unsigned int brk);
void clearCondBreaks();
const StringList& getCondBreakNames() const;

View File

@ -9,12 +9,12 @@ y.tab.c, y.tab.h - Generated parser. NOT BUILT AUTOMATICALLY!
I've only tested stella.y with GNU bison 1.35 and (once) with Berkeley
Yacc 1.9. Hopefully your favorite version will work, too :)
Even though they're generated, y.tab.c and .h are in CVS. This is so that
Even though they're generated, y.tab.c and .h are in SVN. This is so that
people who don't have a local copy of bison or yacc can still compile
Stella.
If you modify stella.y, you MUST run "make -f Makefile.yacc" in this directory.
This will regenerate y.tab.c and y.tab.h. Do this before "cvs commit".
This will regenerate y.tab.c and y.tab.h. Do this before "svn commit".
If you're hacking the parser, you can test it without the rest of Stella
by running "make -f Makefile.yacc calctest" in this directory, then running

View File

@ -41,16 +41,17 @@ yystype result;
string errMsg;
#include "y.tab.c"
const string& errorMessage() {
const string& errorMessage()
{
return errMsg;
}
Expression *getResult() {
return result.exp;
Expression* getResult()
{
lastExp = 0;
return result.exp;
}
const char *input, *c;
enum {
@ -64,15 +65,18 @@ int state = ST_DEFAULT;
//extern int yylval; // bison provides this
void setInput(const char *in) {
void setInput(const char *in)
{
input = c = in;
state = ST_DEFAULT;
}
int parse(const char *in) {
int parse(const char *in)
{
lastExp = 0;
errMsg = "(no error)";
setInput(in);
cerr << "PARSE: " << in << endl;
return yyparse();
}

View File

@ -30,7 +30,7 @@
namespace YaccParser {
int parse(const char *);
Expression *getResult();
Expression* getResult();
const string& errorMessage();
}

View File

@ -7,7 +7,6 @@ Expression* lastExp = 0;
/* dump Expression stack during parsing? */
#define DEBUG_EXP 1
/* #define DEBUG_EXP 1 */
int yylex();
char *yytext;

View File

@ -78,7 +78,6 @@ Expression* lastExp = 0;
/* dump Expression stack during parsing? */
#define DEBUG_EXP 1
/* #define DEBUG_EXP 1 */
int yylex();
char *yytext;
@ -98,7 +97,7 @@ void yyerror(const char *e) {
/* Line 189 of yacc.c */
#line 102 "y.tab.c"
#line 101 "y.tab.c"
/* Enabling traces. */
#ifndef YYDEBUG
@ -173,7 +172,7 @@ typedef union YYSTYPE
{
/* Line 214 of yacc.c */
#line 29 "stella.y"
#line 28 "stella.y"
int val;
char *equate;
@ -186,7 +185,7 @@ typedef union YYSTYPE
/* Line 214 of yacc.c */
#line 190 "y.tab.c"
#line 189 "y.tab.c"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
@ -198,7 +197,7 @@ typedef union YYSTYPE
/* Line 264 of yacc.c */
#line 202 "y.tab.c"
#line 201 "y.tab.c"
#ifdef short
# undef short
@ -496,10 +495,10 @@ static const yytype_int8 yyrhs[] =
/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
0, 67, 67, 70, 71, 72, 73, 74, 75, 76,
77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
97, 98, 99, 100, 101, 102, 103
0, 66, 66, 69, 70, 71, 72, 73, 74, 75,
76, 77, 78, 79, 80, 81, 82, 83, 84, 85,
86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
96, 97, 98, 99, 100, 101, 102
};
#endif
@ -1469,252 +1468,252 @@ yyreduce:
case 2:
/* Line 1455 of yacc.c */
#line 67 "stella.y"
#line 66 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, "\ndone\n"); result.exp = (yyvsp[(1) - (1)].exp); }
break;
case 3:
/* Line 1455 of yacc.c */
#line 70 "stella.y"
#line 69 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " +"); (yyval.exp) = new PlusExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 4:
/* Line 1455 of yacc.c */
#line 71 "stella.y"
#line 70 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " -"); (yyval.exp) = new MinusExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 5:
/* Line 1455 of yacc.c */
#line 72 "stella.y"
#line 71 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " *"); (yyval.exp) = new MultExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 6:
/* Line 1455 of yacc.c */
#line 73 "stella.y"
#line 72 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " /"); (yyval.exp) = new DivExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 7:
/* Line 1455 of yacc.c */
#line 74 "stella.y"
#line 73 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " %%"); (yyval.exp) = new ModExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 8:
/* Line 1455 of yacc.c */
#line 75 "stella.y"
#line 74 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " &"); (yyval.exp) = new BinAndExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 9:
/* Line 1455 of yacc.c */
#line 76 "stella.y"
#line 75 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " |"); (yyval.exp) = new BinOrExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 10:
/* Line 1455 of yacc.c */
#line 77 "stella.y"
#line 76 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " ^"); (yyval.exp) = new BinXorExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 11:
/* Line 1455 of yacc.c */
#line 78 "stella.y"
#line 77 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " <"); (yyval.exp) = new LessExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 12:
/* Line 1455 of yacc.c */
#line 79 "stella.y"
#line 78 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " >"); (yyval.exp) = new GreaterExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 13:
/* Line 1455 of yacc.c */
#line 80 "stella.y"
#line 79 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " >="); (yyval.exp) = new GreaterEqualsExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 14:
/* Line 1455 of yacc.c */
#line 81 "stella.y"
#line 80 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " <="); (yyval.exp) = new LessEqualsExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 15:
/* Line 1455 of yacc.c */
#line 82 "stella.y"
#line 81 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " !="); (yyval.exp) = new NotEqualsExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 16:
/* Line 1455 of yacc.c */
#line 83 "stella.y"
#line 82 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " =="); (yyval.exp) = new EqualsExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 17:
/* Line 1455 of yacc.c */
#line 84 "stella.y"
#line 83 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " >>"); (yyval.exp) = new ShiftRightExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 18:
/* Line 1455 of yacc.c */
#line 85 "stella.y"
#line 84 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " <<"); (yyval.exp) = new ShiftLeftExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 19:
/* Line 1455 of yacc.c */
#line 86 "stella.y"
#line 85 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " ||"); (yyval.exp) = new LogOrExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 20:
/* Line 1455 of yacc.c */
#line 87 "stella.y"
#line 86 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " &&"); (yyval.exp) = new LogAndExpression((yyvsp[(1) - (3)].exp), (yyvsp[(3) - (3)].exp)); lastExp = (yyval.exp); }
break;
case 21:
/* Line 1455 of yacc.c */
#line 88 "stella.y"
#line 87 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " U-"); (yyval.exp) = new UnaryMinusExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 22:
/* Line 1455 of yacc.c */
#line 89 "stella.y"
#line 88 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " ~"); (yyval.exp) = new BinNotExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 23:
/* Line 1455 of yacc.c */
#line 90 "stella.y"
#line 89 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " !"); (yyval.exp) = new LogNotExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 24:
/* Line 1455 of yacc.c */
#line 91 "stella.y"
#line 90 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " U*"); (yyval.exp) = new ByteDerefExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 25:
/* Line 1455 of yacc.c */
#line 92 "stella.y"
#line 91 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " U@"); (yyval.exp) = new WordDerefExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 26:
/* Line 1455 of yacc.c */
#line 93 "stella.y"
#line 92 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " U<"); (yyval.exp) = new LoByteExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 27:
/* Line 1455 of yacc.c */
#line 94 "stella.y"
#line 93 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " U>"); (yyval.exp) = new HiByteExpression((yyvsp[(2) - (2)].exp)); lastExp = (yyval.exp); }
break;
case 28:
/* Line 1455 of yacc.c */
#line 95 "stella.y"
#line 94 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " ()"); (yyval.exp) = (yyvsp[(2) - (3)].exp); lastExp = (yyval.exp); }
break;
case 29:
/* Line 1455 of yacc.c */
#line 96 "stella.y"
#line 95 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " []"); (yyval.exp) = new ByteDerefOffsetExpression((yyvsp[(1) - (4)].exp), (yyvsp[(3) - (4)].exp)); lastExp = (yyval.exp); }
break;
case 30:
/* Line 1455 of yacc.c */
#line 97 "stella.y"
#line 96 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " %d", (yyvsp[(1) - (1)].val)); (yyval.exp) = new ConstExpression((yyvsp[(1) - (1)].val)); lastExp = (yyval.exp); }
break;
case 31:
/* Line 1455 of yacc.c */
#line 98 "stella.y"
#line 97 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " %s", (yyvsp[(1) - (1)].equate)); (yyval.exp) = new EquateExpression((yyvsp[(1) - (1)].equate)); lastExp = (yyval.exp); }
break;
case 32:
/* Line 1455 of yacc.c */
#line 99 "stella.y"
#line 98 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " (CpuMethod)"); (yyval.exp) = new CpuMethodExpression((yyvsp[(1) - (1)].cpuMethod)); lastExp = (yyval.exp); }
break;
case 33:
/* Line 1455 of yacc.c */
#line 100 "stella.y"
#line 99 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " (CartMethod)"); (yyval.exp) = new CartMethodExpression((yyvsp[(1) - (1)].cartMethod)); lastExp = (yyval.exp); }
break;
case 34:
/* Line 1455 of yacc.c */
#line 101 "stella.y"
#line 100 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " (TiaMethod)"); (yyval.exp) = new TiaMethodExpression((yyvsp[(1) - (1)].tiaMethod)); lastExp = (yyval.exp); }
break;
case 35:
/* Line 1455 of yacc.c */
#line 102 "stella.y"
#line 101 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " (function)"); (yyval.exp) = new FunctionExpression((yyvsp[(1) - (1)].function)); lastExp = (yyval.exp); }
break;
case 36:
/* Line 1455 of yacc.c */
#line 103 "stella.y"
#line 102 "stella.y"
{ if(DEBUG_EXP) fprintf(stderr, " ERR: "); yyerror((char*)"Invalid label or constant"); return 1; }
break;
/* Line 1455 of yacc.c */
#line 1718 "y.tab.c"
#line 1717 "y.tab.c"
default: break;
}
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@ -1926,6 +1925,6 @@ yyreturn:
/* Line 1675 of yacc.c */
#line 105 "stella.y"
#line 104 "stella.y"

View File

@ -87,7 +87,7 @@ typedef union YYSTYPE
{
/* Line 1676 of yacc.c */
#line 29 "stella.y"
#line 28 "stella.y"
int val;
char *equate;