diff --git a/stella/src/debugger/CpuDebug.cxx b/stella/src/debugger/CpuDebug.cxx index edb59a1dd..21ab32dfd 100644 --- a/stella/src/debugger/CpuDebug.cxx +++ b/stella/src/debugger/CpuDebug.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: CpuDebug.cxx,v 1.11 2008-04-19 21:11:52 stephena Exp $ +// $Id: CpuDebug.cxx,v 1.12 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include @@ -118,31 +118,35 @@ string CpuDebug::toString() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int CpuDebug::disassemble(int address, string& result, EquateList* equateList) +int CpuDebug::disassemble(int address, string& result, EquateList& list) { ostringstream buf; int count = 0; int opcode = mySystem.peek(address); + // Are we looking at a read or write operation? + // It will determine what type of label to use + bool isRead = (M6502::ourAccessModeTable[opcode] == M6502::Read); + switch(M6502::ourAddressingModeTable[opcode]) { case M6502::Absolute: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(dpeek(mySystem, address + 1), 4) << " ; " + << list.getFormatted(dpeek(mySystem, address + 1), 4, isRead) << " ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 3; break; case M6502::AbsoluteX: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(dpeek(mySystem, address + 1), 4) << ",x ; " + << list.getFormatted(dpeek(mySystem, address + 1), 4, isRead) << ",x ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 3; break; case M6502::AbsoluteY: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(dpeek(mySystem, address + 1), 4) << ",y ; " + << list.getFormatted(dpeek(mySystem, address + 1), 4, isRead) << ",y ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 3; break; @@ -162,49 +166,49 @@ int CpuDebug::disassemble(int address, string& result, EquateList* equateList) case M6502::Indirect: buf << M6502::ourInstructionMnemonicTable[opcode] << " (" - << equateList->getFormatted(dpeek(mySystem, address + 1), 4) << ") ; " + << list.getFormatted(dpeek(mySystem, address + 1), 4, isRead) << ") ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 3; break; case M6502::IndirectX: buf << M6502::ourInstructionMnemonicTable[opcode] << " (" - << equateList->getFormatted(mySystem.peek(address + 1), 2) << ",x) ; " + << list.getFormatted(mySystem.peek(address + 1), 2, isRead) << ",x) ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::IndirectY: buf << M6502::ourInstructionMnemonicTable[opcode] << " (" - << equateList->getFormatted(mySystem.peek(address + 1), 2) << "),y ; " + << list.getFormatted(mySystem.peek(address + 1), 2, isRead) << "),y ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::Relative: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(address + 2 + ((Int16)(Int8)mySystem.peek(address + 1)), 4) + << list.getFormatted(address + 2 + ((Int16)(Int8)mySystem.peek(address + 1)), 4, isRead) << " ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::Zero: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(mySystem.peek(address + 1), 2) << " ; " + << list.getFormatted(mySystem.peek(address + 1), 2, isRead) << " ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::ZeroX: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(mySystem.peek(address + 1), 2) << ",x ; " + << list.getFormatted(mySystem.peek(address + 1), 2, isRead) << ",x ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; case M6502::ZeroY: buf << M6502::ourInstructionMnemonicTable[opcode] << " " - << equateList->getFormatted(mySystem.peek(address + 1), 2) << ",y ; " + << list.getFormatted(mySystem.peek(address + 1), 2, isRead) << ",y ; " << M6502::ourInstructionProcessorCycleTable[opcode]; count = 2; break; diff --git a/stella/src/debugger/CpuDebug.hxx b/stella/src/debugger/CpuDebug.hxx index 6f840e3d4..2b0460f7d 100644 --- a/stella/src/debugger/CpuDebug.hxx +++ b/stella/src/debugger/CpuDebug.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: CpuDebug.hxx,v 1.13 2008-04-19 21:11:52 stephena Exp $ +// $Id: CpuDebug.hxx,v 1.14 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #ifndef CPU_DEBUG_HXX @@ -50,9 +50,9 @@ class CpuDebug : public DebuggerSystem string toString(); // I know, we ain't supposed to do this... - M6502 &m6502() { return mySystem.m6502(); } + M6502& m6502() { return mySystem.m6502(); } - int disassemble(int address, string& result, EquateList* equateList); + int disassemble(int address, string& result, EquateList& list); int dPeek(int address); int getBank(); diff --git a/stella/src/debugger/Debugger.cxx b/stella/src/debugger/Debugger.cxx index 4cecf037a..8eeb139e6 100644 --- a/stella/src/debugger/Debugger.cxx +++ b/stella/src/debugger/Debugger.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: Debugger.cxx,v 1.125 2008-05-02 01:19:48 stephena Exp $ +// $Id: Debugger.cxx,v 1.126 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include "bspf.hxx" @@ -120,7 +120,6 @@ Debugger::Debugger(OSystem* osystem) // Init parser myParser = new DebuggerParser(this); - myEquateList = new EquateList(); myBreakPoints = new PackedBitArray(0x10000); myReadTraps = new PackedBitArray(0x10000); myWriteTraps = new PackedBitArray(0x10000); @@ -575,9 +574,9 @@ const string& Debugger::disassemble(int start, int lines) string cpubuf; do { - buffer << myEquateList->getFormatted(start, 4) << ": "; + buffer << myEquateList->getFormatted(start, 4, true) << ": "; - int count = myCpuDebug->disassemble(start, cpubuf, myEquateList); + int count = myCpuDebug->disassemble(start, cpubuf, *myEquateList); for(int i = 0; i < count; i++) buffer << hex << setw(2) << setfill('0') << peek(start++) << dec; @@ -592,7 +591,7 @@ const string& Debugger::disassemble(int start, int lines) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Debugger::disassemble(IntArray& addr, StringList& addrLabel, +void Debugger::disassemble(IntArray& addr, StringList& addrLabel, StringList& bytes, StringList& data, int start, int lines) { @@ -601,11 +600,11 @@ void Debugger::disassemble(IntArray& addr, StringList& addrLabel, do { - addrLabel.push_back(myEquateList->getFormatted(start, 4) + ":"); + addrLabel.push_back(myEquateList->getFormatted(start, 4, true) + ":"); addr.push_back(start); cpubuf = ""; - int count = myCpuDebug->disassemble(start, cpubuf, myEquateList); + int count = myCpuDebug->disassemble(start, cpubuf, *myEquateList); tmp = ""; for(int i=0; i @@ -562,7 +562,8 @@ string DebuggerParser::eval() char buf[50]; string ret; for(int i=0; iequates().getLabel(args[i]); + // TODO - technically, we should determine if the label is read or write + string label = debugger->equates().getLabel(args[i], true); if(label != "") { ret += label; ret += ": "; @@ -601,7 +602,8 @@ string DebuggerParser::trapStatus(int addr) else result += " none "; - string l = debugger->equates().getLabel(addr); + // TODO - technically, we should determine if the label is read or write + const string& l = debugger->equates().getLabel(addr, true); if(l != "") { result += " ("; result += l; @@ -984,7 +986,7 @@ void DebuggerParser::executeListbreaks() { if(debugger->breakpoints().isSet(i)) { - buf << debugger->equates().getFormatted(i, 4) << " "; + buf << debugger->equates().getFormatted(i, 4, true) << " "; if(! (++count % 8) ) buf << "\n"; } } diff --git a/stella/src/debugger/Equate.hxx b/stella/src/debugger/Equate.hxx deleted file mode 100644 index 173520373..000000000 --- a/stella/src/debugger/Equate.hxx +++ /dev/null @@ -1,44 +0,0 @@ -//============================================================================ -// -// 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 -// SSSS ttt eeeee llll llll aaaaa -// -// Copyright (c) 1995-2008 by Bradford W. Mott and the Stella team -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: Equate.hxx,v 1.8 2008-02-24 16:51:52 stephena Exp $ -//============================================================================ - -#ifndef EQUATE_HXX -#define EQUATE_HXX - -#include "bspf.hxx" - -enum { - EQF_ANY = 1 << 0, // matches any type of label - EQF_READ = 1 << 1, // address can be read from - EQF_WRITE = 1 << 2, // address can be written to - EQF_USER = 1 << 3, // equate is user-defined, not built-in - -// When used in a search, EQF_ROM matches only ROM addresses, -// and EQF_RAM only matches RAM addresses. Both RAM and ROM addresses -// are by definition user-defined, since the built-in equates are -// for the TIA and RIOT only. - EQF_ROM = EQF_READ | EQF_USER, - EQF_RAM = EQF_WRITE | EQF_READ | EQF_USER -}; - -struct Equate { - string label; - int address; - int flags; -}; - -#endif diff --git a/stella/src/debugger/EquateList.cxx b/stella/src/debugger/EquateList.cxx index 85e017b54..2ba77ee2e 100644 --- a/stella/src/debugger/EquateList.cxx +++ b/stella/src/debugger/EquateList.cxx @@ -13,19 +13,307 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EquateList.cxx,v 1.30 2008-05-02 01:19:48 stephena Exp $ +// $Id: EquateList.cxx,v 1.31 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include #include "bspf.hxx" -#include "Equate.hxx" -#include "EquateList.hxx" #include "Debugger.hxx" -// built in labels -static Equate hardCodedEquates[] = { +#include "EquateList.hxx" +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EquateList::EquateList() +{ + for(int i = 0; i < kSystemEquateSize; i++) + { + const Equate& e = ourSystemEquates[i]; + mySystemAddresses.insert(make_pair(e.label, e)); + + // Certain hardcoded addresses have different labels in read and write + // mode; we use separate lists for those + if(e.flags & EQF_READ) + mySystemReadLabels.insert(make_pair(e.address, e)); + if(e.flags & EQF_WRITE) + mySystemWriteLabels.insert(make_pair(e.address, e)); + } +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +EquateList::~EquateList() +{ + mySystemAddresses.clear(); + mySystemReadLabels.clear(); + mySystemWriteLabels.clear(); + + myUserAddresses.clear(); + myUserLabels.clear(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void EquateList::addEquate(const string& label, int address) +{ + // First check if this already exists as a hard-coded equate + LabelToAddr::const_iterator iter = mySystemAddresses.find(label); + if(iter != mySystemAddresses.end() && iter->second.address == address) + return; + + // Create a new user equate, and determine if its RAM or ROM + // For now, these are the only types we care about + // Technically, addresses above 0x1000 are ROM and are read-only + // However, somes ROMs have dedicated RAM mapped to those addresses + // as well, and we don't yet have an infrastructure to determine that, + // so the entire region is marked as read-write + equate_t flags = EQF_READ; + if(address >= 0x80 && address <= 0xff) + flags = EQF_RW; + else if((address & 0x1000) == 0x1000) + flags = EQF_RW; + else +{ cerr << "label = " << label << ", address = " << hex << address << " discarded\n"; + return; // don't know what else to do for now +} + + removeEquate(label); + + Equate e; + e.label = label; + e.address = address; + e.flags = flags; + + myUserAddresses.insert(make_pair(label, e)); + myUserLabels.insert(make_pair(address, e)); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool EquateList::removeEquate(const string& label) +{ + // Note that only user-defined equates can be removed + LabelToAddr::iterator iter = myUserAddresses.find(label); + if(iter != myUserAddresses.end()) + { + // Erase the label + myUserAddresses.erase(iter); + + // And also erase the address assigned to it + AddrToLabel::iterator iter2 = myUserLabels.find(iter->second.address); + if(iter2 != myUserLabels.end()) + myUserLabels.erase(iter2); + + return true; + } + return false; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const string& EquateList::getLabel(int addr, bool isRead) const +{ + AddrToLabel::const_iterator iter; + + // Is this a read or write? + // For now, there aren't separate read & write lists for user labels + if(isRead) + { + if((iter = mySystemReadLabels.find(addr)) != mySystemReadLabels.end()) + return iter->second.label; + else if((iter = myUserLabels.find(addr)) != myUserLabels.end()) + return iter->second.label; + } + else + { + if((iter = mySystemWriteLabels.find(addr)) != mySystemWriteLabels.end()) + return iter->second.label; + else if((iter = myUserLabels.find(addr)) != myUserLabels.end()) + return iter->second.label; + } + return EmptyString; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string EquateList::getFormatted(int addr, int places, bool isRead) const +{ + char fmt[10], buf[255]; + const string& label = getLabel(addr, isRead); + + if(label != "") + return label; + + sprintf(fmt, "$%%0%dx", places); + sprintf(buf, fmt, addr); + + return buf; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int EquateList::getAddress(const string& label) const +{ + LabelToAddr::const_iterator iter; + + if((iter = mySystemAddresses.find(label)) != mySystemAddresses.end()) + return iter->second.address; + else if((iter = myUserAddresses.find(label)) != myUserAddresses.end()) + return iter->second.address; + else + return -1; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string EquateList::loadFile(const string& file) +{ + int pos = 0, lines = 0, curVal; + string curLabel; + char line[1024]; + + ifstream in(file.c_str()); + if(!in.is_open()) + return "Unable to read symbols from " + file; + + myUserAddresses.clear(); + myUserLabels.clear(); + + while( !in.eof() ) + { + curVal = 0; + curLabel = ""; + + int got = in.get(); + + if(got == -1 || got == '\r' || got == '\n' || pos == 1023) { + line[pos] = '\0'; + pos = 0; + + if(strlen(line) > 0 && line[0] != '-') + { + curLabel = extractLabel(line); + if((curVal = extractValue(line)) < 0) + return "invalid symbol file"; + + addEquate(curLabel, curVal); + + lines++; + } + } + else + { + line[pos++] = got; + } + } + in.close(); + + return "loaded " + file + " OK"; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool EquateList::saveFile(const string& file) +{ + // Only user-defined equates are saved; system equates are always + // available, so there's no need to save them + char buf[256]; + + ofstream out(file.c_str()); + if(!out.is_open()) + return false; + + out << "--- Symbol List (sorted by symbol)" << endl; + + LabelToAddr::const_iterator iter; + for(iter = myUserAddresses.begin(); iter != myUserAddresses.end(); iter++) + { + sprintf(buf, "%-24s %04x \n", iter->second.label.c_str(), iter->second.address); + out << buf; + } + + out << "--- End of Symbol List." << endl; + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int EquateList::countCompletions(const char *in) +{ + myCompletions = myCompPrefix = ""; + return countCompletions(in, mySystemAddresses) + + countCompletions(in, myUserAddresses); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int EquateList::countCompletions(const char *in, LabelToAddr& addresses) +{ + int count = 0; + + LabelToAddr::iterator iter; + for(iter = addresses.begin(); iter != addresses.end(); iter++) + { + const char *l = iter->first.c_str(); + + if(BSPF_strncasecmp(l, in, strlen(in)) == 0) + { + if(myCompPrefix == "") + myCompPrefix += l; + else + { + int nonMatch = 0; + const char *c = myCompPrefix.c_str(); + while(*c != '\0' && tolower(*c) == tolower(l[nonMatch])) + { + c++; + nonMatch++; + } + myCompPrefix.erase(nonMatch, myCompPrefix.length()); + } + + if(count++) myCompletions += " "; + myCompletions += l; + } + } + + return count; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +string EquateList::extractLabel(char *c) +{ + string l = ""; + while(*c != ' ') + l += *c++; + + return l; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +int EquateList::extractValue(char *c) +{ + while(*c != ' ') + { + if(*c == '\0') + return -1; + c++; + } + + while(*c == ' ') + { + if(*c == '\0') + return -1; + c++; + } + + int ret = 0; + for(int i=0; i<4; i++) + { + if(*c >= '0' && *c <= '9') + ret = (ret << 4) + (*c) - '0'; + else if(*c >= 'a' && *c <= 'f') + ret = (ret << 4) + (*c) - 'a' + 10; + else + return -1; + c++; + } + return ret; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +const EquateList::Equate EquateList::ourSystemEquates[kSystemEquateSize] = { // Standard $00-based TIA write locations: { "VSYNC", 0x00, EQF_WRITE }, { "VBLANK", 0x01, EQF_WRITE }, @@ -187,271 +475,14 @@ static Equate hardCodedEquates[] = { { "INPT5.30", 0x3D, EQF_READ }, // Standard RIOT locations (read, write, or both): - { "SWCHA", 0x280, EQF_READ | EQF_WRITE }, - { "SWCHB", 0x282, EQF_READ | EQF_WRITE }, + { "SWCHA", 0x280, EQF_RW }, + { "SWCHB", 0x282, EQF_RW }, { "SWACNT", 0x281, EQF_WRITE }, { "SWBCNT", 0x283, EQF_WRITE }, { "INTIM", 0x284, EQF_READ }, + { "TIMINT", 0x285, EQF_READ }, { "TIM1T", 0x294, EQF_WRITE }, { "TIM8T", 0x295, EQF_WRITE }, { "TIM64T", 0x296, EQF_WRITE }, - { "TIM1024T", 0x297, EQF_WRITE } + { "T1024T", 0x297, EQF_WRITE } }; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EquateList::EquateList() -{ - int size = sizeof(hardCodedEquates)/sizeof(struct Equate); - - for(int i = 0; i < size; i++) - { - Equate e = hardCodedEquates[i]; - - myHardcodedFwdMap.insert(make_pair(e.label, e)); - myHardcodedRevMap.insert(make_pair(e.address, e)); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -EquateList::~EquateList() -{ - myHardcodedFwdMap.clear(); - myHardcodedRevMap.clear(); - - myUserFwdMap.clear(); - myUserRevMap.clear(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void EquateList::addEquate(const string& label, int address) -{ - // First check if this already exists as a hard-coded equate - LabelToAddr::const_iterator iter = myHardcodedFwdMap.find(label); - if(iter != myHardcodedFwdMap.end() && iter->second.address == address) - { - cerr << "skipping " << label << endl; - return; - } - removeEquate(label); - -cerr << "add: label = " << label << ", address = " << hex << address << endl; - - // Create a new user equate, and analyze the address to determine its - // probable type (ie, what flags?) - Equate e; - e.label = label; - e.address = address; - e.flags = EQF_USER; - - if(address >= 0x80 && address <= 0xff) - e.flags |= EQF_RAM; - else if(address & 0xf000 == 0xf000) - e.flags |= EQF_ROM; - - myUserFwdMap.insert(make_pair(label, e)); - myUserRevMap.insert(make_pair(address, e)); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EquateList::removeEquate(const string& label) -{ - LabelToAddr::iterator iter = myUserFwdMap.find(label); - if(iter == myUserFwdMap.end()) - { - return false; - } - else - { - // FIXME: error check? - // FIXME: memory leak! - myUserRevMap.erase( myUserRevMap.find(iter->second.address) ); - myUserFwdMap.erase(iter); - return true; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string& EquateList::getLabel(int addr, const int flags) -{ - AddrToLabel::const_iterator iter = myHardcodedRevMap.find(addr); - - if(iter != myHardcodedRevMap.end()) - { - // FIXME - until we fix the issue of correctly setting the equate - // flags to something other than 'EQF_ANY' by default, - // this comparison will almost always fail - if(1)//flags == EQF_ANY || iter->second.flags & flags) - return iter->second.label; - } - return EmptyString; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string EquateList::getFormatted(int addr, int places, const int flags) -{ - char fmt[10], buf[255]; - const string& label = getLabel(addr, flags); - - if(label != "") - return label; - - sprintf(fmt, "$%%0%dx", places); - sprintf(buf, fmt, addr); - - return buf; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int EquateList::getAddress(const string& label, const int flags) -{ - LabelToAddr::const_iterator iter = myHardcodedFwdMap.find(label); - if(iter == myHardcodedFwdMap.end()) - return -1; - else - return iter->second.address; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string EquateList::loadFile(const string& file) -{ - int pos = 0, lines = 0, curVal; - string curLabel; - char line[1024]; - - ifstream in(file.c_str()); - if(!in.is_open()) - return "Unable to read symbols from " + file; - - myUserFwdMap.clear(); - myUserRevMap.clear(); - - while( !in.eof() ) - { - curVal = 0; - curLabel = ""; - - int got = in.get(); - - if(got == -1 || got == '\r' || got == '\n' || pos == 1023) { - line[pos] = '\0'; - pos = 0; - - if(strlen(line) > 0 && line[0] != '-') - { - curLabel = extractLabel(line); - if((curVal = extractValue(line)) < 0) - return "invalid symbol file"; - - addEquate(curLabel, curVal); - - lines++; - } - } - else - { - line[pos++] = got; - } - } - in.close(); - - return "loaded " + file + " OK"; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool EquateList::saveFile(const string& file) -{ - char buf[256]; - - ofstream out(file.c_str()); - if(!out.is_open()) - return false; - - out << "--- Symbol List (sorted by symbol)" << endl; - - LabelToAddr::iterator iter; - for(iter = myHardcodedFwdMap.begin(); iter != myHardcodedFwdMap.end(); iter++) - { - sprintf(buf, "%-24s %04x \n", iter->second.label.c_str(), iter->second.address); - out << buf; - } - - out << "--- End of Symbol List." << endl; - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int EquateList::countCompletions(const char *in) -{ - int count = 0; - myCompletions = myCompPrefix = ""; - - LabelToAddr::iterator iter; - for(iter = myHardcodedFwdMap.begin(); iter != myHardcodedFwdMap.end(); iter++) - { - const char *l = iter->first.c_str(); - - if(BSPF_strncasecmp(l, in, strlen(in)) == 0) - { - if(myCompPrefix == "") - myCompPrefix += l; - else - { - int nonMatch = 0; - const char *c = myCompPrefix.c_str(); - while(*c != '\0' && tolower(*c) == tolower(l[nonMatch])) - { - c++; - nonMatch++; - } - myCompPrefix.erase(nonMatch, myCompPrefix.length()); - } - - if(count++) myCompletions += " "; - myCompletions += l; - } - } - - return count; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string EquateList::extractLabel(char *c) -{ - string l = ""; - while(*c != ' ') - l += *c++; - - return l; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int EquateList::extractValue(char *c) -{ - while(*c != ' ') - { - if(*c == '\0') - return -1; - c++; - } - - while(*c == ' ') - { - if(*c == '\0') - return -1; - c++; - } - - int ret = 0; - for(int i=0; i<4; i++) - { - if(*c >= '0' && *c <= '9') - ret = (ret << 4) + (*c) - '0'; - else if(*c >= 'a' && *c <= 'f') - ret = (ret << 4) + (*c) - 'a' + 10; - else - return -1; - c++; - } - return ret; -} diff --git a/stella/src/debugger/EquateList.hxx b/stella/src/debugger/EquateList.hxx index 854255dcc..9e1a49eb8 100644 --- a/stella/src/debugger/EquateList.hxx +++ b/stella/src/debugger/EquateList.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: EquateList.hxx,v 1.20 2008-05-02 01:19:48 stephena Exp $ +// $Id: EquateList.hxx,v 1.21 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #ifndef EQUATELIST_HXX @@ -22,7 +22,6 @@ #include #include "bspf.hxx" -#include "Equate.hxx" class EquateList { @@ -42,10 +41,15 @@ class EquateList /** Accessor methods for labels and addresses + + The mapping from address to label can be one-to-many (ie, an + address can have different labels depending on its context, and + whether its being read or written; if isRead is true, the context + is a read, else it's a write */ - const string& getLabel(int addr, const int flags = EQF_ANY); - string getFormatted(int addr, int places, const int flags = EQF_ANY); - int getAddress(const string& label, const int flags = EQF_ANY); + const string& getLabel(int addr, bool isRead) const; + string getFormatted(int addr, int places, bool isRead) const; + int getAddress(const string& label) const; /** Load user equates from the given symbol file (generated by DASM) @@ -61,26 +65,46 @@ class EquateList Methods used by the command parser for tab-completion */ int countCompletions(const char *in); - const string& getCompletions() { return myCompletions; } - const string& getCompletionPrefix() { return myCompPrefix; } + const string& getCompletions() const { return myCompletions; } + const string& getCompletionPrefix() const { return myCompPrefix; } + + private: + enum equate_t { + EQF_READ = 1 << 0, // address can be read from + EQF_WRITE = 1 << 1, // address can be written to + EQF_RW = EQF_READ | EQF_WRITE // address can be both read and written + }; + + struct Equate { + string label; + int address; + equate_t flags; + }; + + typedef map AddrToLabel; + typedef map LabelToAddr; private: // Extract labels and values from the given character stream string extractLabel(char *c); int extractValue(char *c); + // Count completions for the given mapping + int countCompletions(const char *in, LabelToAddr& addresses); + private: - typedef map AddrToLabel; - typedef map LabelToAddr; + enum { kSystemEquateSize = 158 }; + static const Equate ourSystemEquates[kSystemEquateSize]; string myCompletions; string myCompPrefix; - LabelToAddr myHardcodedFwdMap; - AddrToLabel myHardcodedRevMap; + LabelToAddr mySystemAddresses; + AddrToLabel mySystemReadLabels; // labels used in a read context + AddrToLabel mySystemWriteLabels; // labels used in a write context - LabelToAddr myUserFwdMap; - AddrToLabel myUserRevMap; + LabelToAddr myUserAddresses; + AddrToLabel myUserLabels; }; #endif diff --git a/stella/src/debugger/RiotDebug.cxx b/stella/src/debugger/RiotDebug.cxx index 866669d4c..14ff58c92 100644 --- a/stella/src/debugger/RiotDebug.cxx +++ b/stella/src/debugger/RiotDebug.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: RiotDebug.cxx,v 1.2 2008-04-29 15:13:15 stephena Exp $ +// $Id: RiotDebug.cxx,v 1.3 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include @@ -228,17 +228,13 @@ string RiotDebug::toString() const RiotState& oldstate = (RiotState&) getOldState(); string ret; - ret += myDebugger.valueToString(0x280) + "/" + - myDebugger.equates().getFormatted(0x280, 2) + "=" + + ret += myDebugger.valueToString(0x280) + "/SWCHA" + myDebugger.invIfChanged(state.SWCHA, oldstate.SWCHA) + " "; - ret += myDebugger.valueToString(0x281) + "/" + - myDebugger.equates().getFormatted(0x281, 2) + "=" + + ret += myDebugger.valueToString(0x281) + "/SWACNT" + myDebugger.invIfChanged(state.SWACNT, oldstate.SWACNT) + " "; - ret += myDebugger.valueToString(0x282) + "/" + - myDebugger.equates().getFormatted(0x282, 2) + "=" + + ret += myDebugger.valueToString(0x282) + "/SWCHB" + myDebugger.invIfChanged(state.SWCHB, oldstate.SWCHB) + " "; - ret += myDebugger.valueToString(0x283) + "/" + - myDebugger.equates().getFormatted(0x283, 2) + "=" + + ret += myDebugger.valueToString(0x283) + "/SWBCNT" + myDebugger.invIfChanged(state.SWBCNT, oldstate.SWBCNT) + " "; ret += "\n"; diff --git a/stella/src/debugger/gui/CpuWidget.cxx b/stella/src/debugger/gui/CpuWidget.cxx index 2696f274d..cc56c440b 100644 --- a/stella/src/debugger/gui/CpuWidget.cxx +++ b/stella/src/debugger/gui/CpuWidget.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: CpuWidget.cxx,v 1.11 2008-03-23 17:43:22 stephena Exp $ +// $Id: CpuWidget.cxx,v 1.12 2008-05-04 17:16:39 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -281,5 +281,5 @@ void CpuWidget::fillGrid() changed.push_back(state.PSbits[i] != oldstate.PSbits[i]); myPSRegister->setState(state.PSbits, changed); - myPCLabel->setEditString(dbg.equates().getLabel(state.PC, EQF_ROM)); + myPCLabel->setEditString(dbg.equates().getLabel(state.PC, true)); } diff --git a/stella/src/debugger/gui/RamWidget.cxx b/stella/src/debugger/gui/RamWidget.cxx index ec1286ed2..bfa62c96b 100644 --- a/stella/src/debugger/gui/RamWidget.cxx +++ b/stella/src/debugger/gui/RamWidget.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: RamWidget.cxx,v 1.16 2008-03-23 17:43:22 stephena Exp $ +// $Id: RamWidget.cxx,v 1.17 2008-05-04 17:16:39 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -177,7 +177,7 @@ void RamWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) value = myRamGrid->getSelectedValue(); myLabel->setEditString( - instance()->debugger().equates().getLabel(addr+kRamStart, EQF_RAM)); + instance()->debugger().equates().getLabel(addr+kRamStart, true)); myDecValue->setEditString(instance()->debugger().valueToString(value, kBASE_10)); myBinValue->setEditString(instance()->debugger().valueToString(value, kBASE_2)); break; diff --git a/stella/src/debugger/gui/TiaWidget.cxx b/stella/src/debugger/gui/TiaWidget.cxx index 2e703bb43..187fac6d6 100644 --- a/stella/src/debugger/gui/TiaWidget.cxx +++ b/stella/src/debugger/gui/TiaWidget.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: TiaWidget.cxx,v 1.11 2008-04-19 21:11:52 stephena Exp $ +// $Id: TiaWidget.cxx,v 1.12 2008-05-04 17:16:39 stephena Exp $ // // Based on code from ScummVM - Scumm Interpreter // Copyright (C) 2002-2004 The ScummVM project @@ -789,7 +789,9 @@ void TiaWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) addr = myRamGrid->getSelectedAddr(); value = myRamGrid->getSelectedValue(); - myLabel->setEditString(dbg.equates().getLabel(addr)); + // We're using the read-addresses here + // Should we also add write-addresses, or remove this entirely? + myLabel->setEditString(dbg.equates().getLabel(addr, true)); myDecValue->setEditString(dbg.valueToString(value, kBASE_10)); myBinValue->setEditString(dbg.valueToString(value, kBASE_2)); diff --git a/stella/src/emucore/m6502/src/M6502.cxx b/stella/src/emucore/m6502/src/M6502.cxx index f3f1559c0..68383b91a 100644 --- a/stella/src/emucore/m6502/src/M6502.cxx +++ b/stella/src/emucore/m6502/src/M6502.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: M6502.cxx,v 1.22 2008-02-06 13:45:22 stephena Exp $ +// $Id: M6502.cxx,v 1.23 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include "M6502.hxx" @@ -24,9 +24,11 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - M6502::M6502(uInt32 systemCyclesPerProcessorCycle) - : myExecutionStatus(0), - mySystem(0), - mySystemCyclesPerProcessorCycle(systemCyclesPerProcessorCycle) + : myExecutionStatus(0), + mySystem(0), + mySystemCyclesPerProcessorCycle(systemCyclesPerProcessorCycle), + myLastAccessWasRead(true), + myTotalInstructionCount(0) { #ifdef DEBUGGER_SUPPORT myDebugger = NULL; @@ -49,8 +51,6 @@ M6502::M6502(uInt32 systemCyclesPerProcessorCycle) myInstructionSystemCycleTable[t] = ourInstructionProcessorCycleTable[t] * mySystemCyclesPerProcessorCycle; } - - myTotalInstructionCount = 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -85,6 +85,8 @@ void M6502::reset() // Load PC from the reset vector PC = (uInt16)mySystem->peek(0xfffc) | ((uInt16)mySystem->peek(0xfffd) << 8); + + myTotalInstructionCount = 0; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -105,12 +107,6 @@ void M6502::stop() myExecutionStatus |= StopExecutionBit; } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -M6502::AddressingMode M6502::addressingMode(uInt8 opcode) const -{ - return ourAddressingModeTable[opcode]; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 M6502::PS() const { @@ -199,86 +195,169 @@ uInt8 M6502::ourBCDTable[2][256]; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - M6502::AddressingMode M6502::ourAddressingModeTable[256] = { - Implied, IndirectX, Invalid, IndirectX, // 0x0? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Implied, IndirectX, Invalid, IndirectX, // 0x0? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0x1? - ZeroX, ZeroX, ZeroX, ZeroX, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, + Relative, IndirectY, Invalid, IndirectY, // 0x1? + ZeroX, ZeroX, ZeroX, ZeroX, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, - Absolute, IndirectX, Invalid, IndirectX, // 0x2? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Absolute, IndirectX, Invalid, IndirectX, // 0x2? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0x3? - ZeroX, ZeroX, ZeroX, ZeroX, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, + Relative, IndirectY, Invalid, IndirectY, // 0x3? + ZeroX, ZeroX, ZeroX, ZeroX, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, - Implied, IndirectX, Invalid, IndirectX, // 0x4? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Implied, IndirectX, Invalid, IndirectX, // 0x4? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0x5? - ZeroX, ZeroX, ZeroX, ZeroX, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, + Relative, IndirectY, Invalid, IndirectY, // 0x5? + ZeroX, ZeroX, ZeroX, ZeroX, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, - Implied, IndirectX, Invalid, IndirectX, // 0x6? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Indirect, Absolute, Absolute, Absolute, + Implied, IndirectX, Invalid, IndirectX, // 0x6? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Indirect, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0x7? - ZeroX, ZeroX, ZeroX, ZeroX, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, + Relative, IndirectY, Invalid, IndirectY, // 0x7? + ZeroX, ZeroX, ZeroX, ZeroX, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, - Immediate, IndirectX, Immediate, IndirectX, // 0x8? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Immediate, IndirectX, Immediate, IndirectX, // 0x8? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0x9? - ZeroX, ZeroX, ZeroY, ZeroY, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY, + Relative, IndirectY, Invalid, IndirectY, // 0x9? + ZeroX, ZeroX, ZeroY, ZeroY, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY, - Immediate, IndirectX, Immediate, IndirectX, // 0xA? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Immediate, IndirectX, Immediate, IndirectX, // 0xA? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0xB? - ZeroX, ZeroX, ZeroY, ZeroY, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY, + Relative, IndirectY, Invalid, IndirectY, // 0xB? + ZeroX, ZeroX, ZeroY, ZeroY, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY, - Immediate, IndirectX, Immediate, IndirectX, // 0xC? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Immediate, IndirectX, Immediate, IndirectX, // 0xC? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0xD? - ZeroX, ZeroX, ZeroX, ZeroX, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, + Relative, IndirectY, Invalid, IndirectY, // 0xD? + ZeroX, ZeroX, ZeroX, ZeroX, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX, - Immediate, IndirectX, Immediate, IndirectX, // 0xE? - Zero, Zero, Zero, Zero, - Implied, Immediate, Implied, Immediate, - Absolute, Absolute, Absolute, Absolute, + Immediate, IndirectX, Immediate, IndirectX, // 0xE? + Zero, Zero, Zero, Zero, + Implied, Immediate, Implied, Immediate, + Absolute, Absolute, Absolute, Absolute, - Relative, IndirectY, Invalid, IndirectY, // 0xF? - ZeroX, ZeroX, ZeroX, ZeroX, - Implied, AbsoluteY, Implied, AbsoluteY, - AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX - }; + Relative, IndirectY, Invalid, IndirectY, // 0xF? + ZeroX, ZeroX, ZeroX, ZeroX, + Implied, AbsoluteY, Implied, AbsoluteY, + AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX +}; + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +M6502::AccessMode M6502::ourAccessModeTable[256] = { + None, Read, None, Write, // 0x0? + None, Read, Write, Write, + None, Read, Write, Read, + None, Read, Write, Write, + + Read, Read, None, Write, // 0x1? + None, Read, Write, Write, + None, Read, None, Write, + None, Read, Write, Write, + + Read, Read, None, Write, // 0x2? + Read, Read, Write, Write, + None, Read, Write, Read, + Read, Read, Write, Write, + + Read, Read, None, Write, // 0x3? + None, Read, Write, Write, + None, Read, None, Write, + None, Read, Write, Write, + + None, Read, None, Write, // 0x4? + None, Read, Write, Write, + None, Read, Write, Read, + Read, Read, Write, Write, + + Read, Read, None, Write, // 0x5? + None, Read, Write, Write, + None, Read, None, Write, + None, Read, Write, Write, + + None, Read, None, Write, // 0x6? + None, Read, Write, Write, + None, Read, Write, Read, + Read, Read, Write, Write, + + Read, Read, None, Write, // 0x7? + None, Read, Write, Write, + None, Read, None, Write, + None, Read, Write, Write, + + None, Write, None, Write, // 0x8? + Write, Write, Write, Write, + None, None, None, Read, + Write, Write, Write, Write, + + Read, Write, None, Write, // 0x9? + Write, Write, Write, Write, + None, Write, None, Write, + Write, Write, Write, Write, + + Read, Read, Read, Read, // 0xA? + Read, Read, Read, Read, + None, Read, None, Read, + Read, Read, Read, Read, + + Read, Read, None, Read, // 0xB? + Read, Read, Read, Read, + None, Read, None, Read, + Read, Read, Read, Read, + + Read, Read, None, Write, // 0xC? + Read, Read, Write, Write, + None, Read, None, Read, + Read, Read, Write, Write, + + Read, Read, None, Write, // 0xD? + None, Read, Write, Write, + None, Read, None, Write, + None, Read, Write, Write, + + Read, Read, None, Write, // 0xE? + Read, Read, Write, Write, + None, Read, None, Read, + Read, Read, Write, Write, + + Read, Read, None, Write, // 0xF? + None, Read, Write, Write, + None, Read, None, Write, + None, Read, Write, Write +}; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt32 M6502::ourInstructionProcessorCycleTable[256] = { @@ -353,60 +432,6 @@ const char* M6502::ourInstructionMnemonicTable[256] = { }; #ifdef DEBUGGER_SUPPORT -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// This needs to be a list of all 256 opcodes and the type of memory -// access they do (read, write, read/modify/write, or none). The -// disassemble() method will use this to figure out what kind of label -// to use in the disassembly. -//// const char* M6502::ourLabelTypeTable[256] = { -//// }; -//// -//// // disassemble() will use isXXX methods to determine what type of -//// // label to show to the user (e.g. isTIA == true means to show a -//// // non-user label; isRAM == true means to show a user r/w label, etc) -//// -//// // These methods were based on (and checked against) Kroko's -//// // 2600 memory map, found at -//// // http://www.qotile.net/minidig/docs/2600_mem_map.txt -//// -//// // is the address in RIOT RAM? -//// bool isRAM(int addr) { -//// int y = addr & 0xf00; -//// int z = addr & 0xff; -//// -//// return !isROM(addr) -//// && -//// z >= 0x80 -//// && -//// (y == 0 || y == 0x100 || y == 0x400 || y == 0x500 || -//// y == 0x800 || y == 0x900 || y == 0xc00 || y == 0xd00); -//// } -//// -//// // is the address one of the non-RAM RIOT areas? -//// bool isRIOT(int addr) { -//// int y = addr & 0xf00; -//// int z = addr & 0xff; -//// -//// return !isROM(addr) -//// && -//// z >= 0x80 -//// && -//// (y == 0x200 || y == 0x300 || y == 0x600 || y == 0x700 || -//// y == 0xa00 || y == 0xb00 || y == 0xe00 || y == 0xf00); -//// } -//// -//// // is the address in one of the TIA mirrors? -//// bool isTIA(int addr) { -//// int z = addr & 0xff; -//// return !isROM(addr) && (z < 0x80); -//// } -//// -//// // is the address in ROM? -//// bool isROM(int addr) { -//// // ROM addresses are $xnnn where x is odd -//// return addr % 8192 > 4095; -//// } - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void M6502::attach(Debugger& debugger) { @@ -415,7 +440,7 @@ void M6502::attach(Debugger& debugger) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -unsigned int M6502::addCondBreak(Expression *e, string name) +unsigned int M6502::addCondBreak(Expression *e, const string& name) { myBreakConds.push_back(e); myBreakCondNames.push_back(name); @@ -443,7 +468,7 @@ void M6502::clearCondBreaks() } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const StringList& M6502::getCondBreakNames() +const StringList& M6502::getCondBreakNames() const { return myBreakCondNames; } @@ -452,11 +477,8 @@ const StringList& M6502::getCondBreakNames() int M6502::evalCondBreaks() { for(unsigned int i=0; ievaluate()) + if(myBreakConds[i]->evaluate()) return i; - } return -1; // no break hit } diff --git a/stella/src/emucore/m6502/src/M6502.hxx b/stella/src/emucore/m6502/src/M6502.hxx index 7172ad57a..a82417c90 100644 --- a/stella/src/emucore/m6502/src/M6502.hxx +++ b/stella/src/emucore/m6502/src/M6502.hxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: M6502.hxx,v 1.21 2008-02-06 13:45:22 stephena Exp $ +// $Id: M6502.hxx,v 1.22 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #ifndef M6502_HXX @@ -41,7 +41,7 @@ typedef Common::Array ExpressionList; has a 64K addressing space. @author Bradford W. Mott - @version $Id: M6502.hxx,v 1.21 2008-02-06 13:45:22 stephena Exp $ + @version $Id: M6502.hxx,v 1.22 2008-05-04 17:16:39 stephena Exp $ */ class M6502 { @@ -55,13 +55,21 @@ class M6502 /** Enumeration of the 6502 addressing modes */ - enum AddressingMode + enum AddressingMode { Absolute, AbsoluteX, AbsoluteY, Immediate, Implied, Indirect, IndirectX, IndirectY, Invalid, Relative, Zero, ZeroX, ZeroY }; + /** + Enumeration of the 6502 access modes + */ + enum AccessMode + { + Read, Write, None + }; + public: /** Create a new 6502 microprocessor with the specified cycle @@ -133,7 +141,17 @@ class M6502 @param opcode The opcode of the instruction @return The addressing mode of the instruction */ - AddressingMode addressingMode(uInt8 opcode) const; + AddressingMode addressingMode(uInt8 opcode) const + { return ourAddressingModeTable[opcode]; } + + /** + Get the access mode of the specified instruction + + @param opcode The opcode of the instruction + @return The access mode of the instruction + */ + AccessMode accessMode(uInt8 opcode) const + { return ourAccessModeTable[opcode]; } public: /** @@ -174,10 +192,17 @@ class M6502 /** Answer true iff the last memory access was a read. - @return true iff last access was a read. + @return true iff last access was a read */ bool lastAccessWasRead() const { return myLastAccessWasRead; } + /** + Get the total number of instructions executed so far. + + @return The number of executed instructions + */ + int totalInstructionCount() const { return myTotalInstructionCount; } + public: /** Overload the ostream output operator for addressing modes. @@ -199,12 +224,11 @@ class M6502 // TODO - document these methods void setBreakPoints(PackedBitArray *bp); void setTraps(PackedBitArray *read, PackedBitArray *write); - int totalInstructionCount() { return myTotalInstructionCount; } - unsigned int addCondBreak(Expression *e, string name); + unsigned int addCondBreak(Expression *e, const string& name); void delCondBreak(unsigned int brk); void clearCondBreaks(); - const StringList& getCondBreakNames(); + const StringList& getCondBreakNames() const; int evalCondBreaks(); #endif @@ -239,26 +263,6 @@ class M6502 bool notZ; // Z flag complement for processor status register bool C; // C flag for processor status register -#ifdef DEBUGGER_SUPPORT - /// Pointer to the debugger for this processor or the null pointer - Debugger* myDebugger; - - PackedBitArray* myBreakPoints; - PackedBitArray* myReadTraps; - PackedBitArray* myWriteTraps; - - // Did we just now hit a trap? - bool myJustHitTrapFlag; - struct HitTrapInfo { - string message; - int address; - }; - HitTrapInfo myHitTrapInfo; - - StringList myBreakCondNames; - ExpressionList myBreakConds; -#endif - /** Bit fields used to indicate that certain conditions need to be handled such as stopping execution, fatal errors, maskable interrupts @@ -289,10 +293,38 @@ class M6502 /// Indicates if the last memory access was a read or not bool myLastAccessWasRead; + /// The total number of instructions executed so far + int myTotalInstructionCount; + +#ifdef DEBUGGER_SUPPORT + /// Pointer to the debugger for this processor or the null pointer + Debugger* myDebugger; + + PackedBitArray* myBreakPoints; + PackedBitArray* myReadTraps; + PackedBitArray* myWriteTraps; + + // Did we just now hit a trap? + bool myJustHitTrapFlag; + struct HitTrapInfo { + string message; + int address; + }; + HitTrapInfo myHitTrapInfo; + + StringList myBreakCondNames; + ExpressionList myBreakConds; +#endif + protected: /// Addressing mode for each of the 256 opcodes + /// This specifies how the opcode argument is addressed static AddressingMode ourAddressingModeTable[256]; + /// Access mode for each of the 256 opcodes + /// This specifies how the opcode will access its argument + static AccessMode ourAccessModeTable[256]; + /// Lookup table used for binary-code-decimal math static uInt8 ourBCDTable[2][256]; @@ -304,8 +336,6 @@ class M6502 /// Table of instruction mnemonics static const char* ourInstructionMnemonicTable[256]; - - int myTotalInstructionCount; }; #endif diff --git a/stella/src/emucore/m6502/src/M6502Low.cxx b/stella/src/emucore/m6502/src/M6502Low.cxx index 425dfac4b..2a1be726d 100644 --- a/stella/src/emucore/m6502/src/M6502Low.cxx +++ b/stella/src/emucore/m6502/src/M6502Low.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: M6502Low.cxx,v 1.14 2008-02-06 13:45:22 stephena Exp $ +// $Id: M6502Low.cxx,v 1.15 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include "M6502Low.hxx" @@ -142,6 +142,8 @@ bool M6502Low::execute(uInt32 number) cerr << "Illegal Instruction! " << hex << (int) IR << endl; } + myTotalInstructionCount++; + #ifdef DEBUG debugStream << hex << setw(4) << operandAddress << " "; debugStream << setw(4) << ourInstructionMnemonicTable[IR]; diff --git a/stella/src/win32/SettingsWin32.cxx b/stella/src/win32/SettingsWin32.cxx index 98ac5f3e3..63bdfd01c 100644 --- a/stella/src/win32/SettingsWin32.cxx +++ b/stella/src/win32/SettingsWin32.cxx @@ -13,7 +13,7 @@ // See the file "license" for information on usage and redistribution of // this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// $Id: SettingsWin32.cxx,v 1.28 2008-03-08 23:34:24 stephena Exp $ +// $Id: SettingsWin32.cxx,v 1.29 2008-05-04 17:16:39 stephena Exp $ //============================================================================ #include "bspf.hxx" @@ -24,6 +24,7 @@ SettingsWin32::SettingsWin32(OSystem* osystem) : Settings(osystem) { + setInternal("gl_lib", "opengl32.dll"); // Anything less than this usually causes sound skipping setInternal("fragsize", "2048"); // Most Windows systems work better without this