From 7f75957e11ceff297c8c20d6ef5f548cfa6ba49c Mon Sep 17 00:00:00 2001 From: stephena Date: Mon, 6 Sep 2010 23:29:05 +0000 Subject: [PATCH] When a ROM doesn't exist and is temporarily inserted into the properties database, it now has its extension removed (.bin, .a26, etc). Symbol and config files are now loaded when the debugger is first entered, not when the ROM is actually loaded. This speeds up ROM loading, since the user may never need to access these file (ie, they may never enter the debugger). The debugger 'loadconfig' and 'saveconfig' commands are now implemented. Bumped version # for next test release. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2126 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- src/common/Version.hxx | 2 +- src/debugger/CartDebug.cxx | 178 ++++++++++++++++++++++-------- src/debugger/CartDebug.hxx | 18 +-- src/debugger/Debugger.cxx | 6 +- src/debugger/DiStella.cxx | 7 +- src/debugger/gui/PromptWidget.cxx | 2 + src/emucore/OSystem.cxx | 8 +- 7 files changed, 156 insertions(+), 65 deletions(-) diff --git a/src/common/Version.hxx b/src/common/Version.hxx index 8d6c0c8c8..1ad2b976a 100644 --- a/src/common/Version.hxx +++ b/src/common/Version.hxx @@ -22,7 +22,7 @@ #include -#define STELLA_VERSION "3.3_test2" +#define STELLA_VERSION "3.3_test3" #define STELLA_BUILD atoi("$Rev$" + 6) #endif diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 6efb95407..a59b28563 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -46,10 +46,10 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem) BankInfo info; for(int i = 0; i < myConsole.cartridge().bankCount(); ++i) { - info.banksize = banksize; // TODO - get this from Cart class + info.size = banksize; // TODO - get this from Cart class myBankInfo.push_back(info); } - info.banksize = 128; // ZP RAM + info.size = 128; // ZP RAM myBankInfo.push_back(info); // We know the address for the startup bank right now @@ -362,10 +362,13 @@ bool CartDebug::addDirective(CartDebug::DisasmType type, PRINT_TAG((*d)); \ cerr << endl; + if(end < start || start == 0 || end == 0) + return false; + if(bank < 0) // Do we want the current bank or ZP RAM? bank = (myDebugger.cpuDebug().pc() & 0x1000) ? getBank() : myBankInfo.size()-1; - bank = BSPF_min(bank, bankCount() - 1); + bank = BSPF_min(bank, bankCount()); BankInfo& info = myBankInfo[bank]; DirectiveList& list = info.directiveList; @@ -595,15 +598,20 @@ int CartDebug::getAddress(const string& label) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string CartDebug::loadSymbolFile(const string& f) +string CartDebug::loadSymbolFile(string file) { - string file = f; + // TODO - use similar load logic as loadconfig command + if(file == "") + file = myOSystem.romFile(); + string::size_type spos; if( (spos = file.find_last_of('.')) != string::npos ) file.replace(spos, file.size(), ".sym"); else file += ".sym"; + // TODO - rewrite this to use C++ streams + int pos = 0, lines = 0, curVal; string curLabel; char line[1024]; @@ -651,26 +659,43 @@ string CartDebug::loadConfigFile(string file) { FilesystemNode node(file); - if(file == "") // Use config file based on ROM name + if(file == "") { - file = myOSystem.romFile(); - string::size_type spos; - if((spos = file.find_last_of('.')) != string::npos ) - file.replace(spos, file.size(), ".cfg"); - else - file += ".cfg"; - FilesystemNode usercfg(file); - if(usercfg.exists()) + // There are three possible locations for loading config files + // (in order of decreasing relevance): + // 1) ROM dir based on properties entry name + // 2) ROM dir based on actual ROM name + // 3) CFG dir based on properties entry name + + const string& propsname = + myConsole.properties().get(Cartridge_Name) + ".cfg"; + + // Case 1 + FilesystemNode case1(FilesystemNode(myOSystem.romFile()).getParent().getPath() + + propsname); + if(case1.exists()) { - node = usercfg; + node = case1; } - else // Use global config file based on properties cart name + else { - const string& globalfile = myOSystem.cfgDir() + - myConsole.properties().get(Cartridge_Name) + ".cfg"; - FilesystemNode globalcfg(globalfile); - if(globalcfg.exists()) - node = globalcfg; + file = myOSystem.romFile(); + string::size_type spos; + if((spos = file.find_last_of('.')) != string::npos ) + file.replace(spos, file.size(), ".cfg"); + else + file += ".cfg"; + FilesystemNode case2(file); + if(case2.exists()) + { + node = case2; + } + else // Use global config file based on properties cart name + { + FilesystemNode case3(myOSystem.cfgDir() + propsname); + if(case3.exists()) + node = case3; + } } } @@ -678,7 +703,14 @@ string CartDebug::loadConfigFile(string file) { ifstream in(node.getPath().c_str()); if(!in.is_open()) - return "Unable to read directives from " + node.getPath(); + return "Unable to load directives from " + node.getPath(); + + // Erase all previous directives + for(Common::Array::iterator bi = myBankInfo.begin(); + bi != myBankInfo.end(); ++bi) + { + bi->directiveList.clear(); + } int currentbank = 0; while(!in.eof()) @@ -718,33 +750,26 @@ string CartDebug::loadConfigFile(string file) { buf >> hex >> start; // TODO - figure out what to do with this - cerr << "ignoring directive: " - << directive << " " << HEX4 << start << endl; } else if(BSPF_startsWithIgnoreCase(directive, "BLOCK")) { buf >> hex >> start; buf >> hex >> end; -// TODO - add directive for this - cerr << "ignoring directive: " << directive << " " - << HEX4 << start << " " << HEX4 << end << endl; +// addDirective(CartDebug::BLOCK, start, end, currentbank); } else if(BSPF_startsWithIgnoreCase(directive, "CODE")) { - buf >> hex >> start; - buf >> hex >> end; + buf >> hex >> start >> hex >> end; addDirective(CartDebug::CODE, start, end, currentbank); } else if(BSPF_startsWithIgnoreCase(directive, "DATA")) { - buf >> hex >> start; - buf >> hex >> end; + buf >> hex >> start >> hex >> end; addDirective(CartDebug::DATA, start, end, currentbank); } else if(BSPF_startsWithIgnoreCase(directive, "GFX")) { - buf >> hex >> start; - buf >> hex >> end; + buf >> hex >> start >> hex >> end; addDirective(CartDebug::GFX, start, end, currentbank); } } @@ -760,7 +785,44 @@ string CartDebug::loadConfigFile(string file) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - string CartDebug::saveConfigFile(string file) { -return "NOT YET IMPLEMENTED"; + FilesystemNode node(file); + + const string& name = myConsole.properties().get(Cartridge_Name); + const string& md5 = myConsole.properties().get(Cartridge_MD5); + + if(file == "") + { + // There are two possible locations for saving config files + // (in order of decreasing relevance): + // 1) ROM dir based on properties entry name + // 2) ROM dir based on actual ROM name + // + // In either case, we're using the properties entry, since even ROMs that + // don't have a proper entry have a temporary one inserted by OSystem + node = FilesystemNode(name + ".cfg"); + } + + if(!node.isDirectory()) + { + ofstream out(node.getPath().c_str()); + if(!out.is_open()) + return "Unable to save directives to " + node.getPath(); + + // Store all bank information + out << "//Stella.pro: \"" << name << "\"" << endl + << "//MD5: " << md5 << endl + << endl; + for(uInt32 b = 0; b < myConsole.cartridge().bankCount(); ++b) + { + out << "[" << b << "]" << endl; + getBankDirectives(out, myBankInfo[b]); + } + out.close(); + + return "saved " + node.getRelativePath() + " OK"; + } + else + return DebuggerParser::red("config file not found"); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -782,11 +844,12 @@ string CartDebug::listConfig(int bank) for(DirectiveList::const_iterator i = info.directiveList.begin(); i != info.directiveList.end(); ++i) { - buf << "(*) " - << (i->type == CartDebug::CODE ? "CODE" : - i->type == CartDebug::DATA ? "DATA" : - "GFX") - << " " << HEX4 << i->start << " " << HEX4 << i->end << endl; + if(i->type != CartDebug::NONE) + { + buf << "(*) "; + disasmTypeAsString(buf, i->type); + buf << " " << HEX4 << i->start << " " << HEX4 << i->end << endl; + } } getBankDirectives(buf, info); } @@ -861,7 +924,7 @@ CartDebug::AddrType CartDebug::addressType(uInt16 addr) const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CartDebug::getBankDirectives(ostringstream& buf, BankInfo& info) const +void CartDebug::getBankDirectives(ostream& buf, BankInfo& info) const { // Disassemble the bank, then scan it for an up-to-date description DisassemblyList list; @@ -890,10 +953,9 @@ void CartDebug::getBankDirectives(ostringstream& buf, BankInfo& info) const if(type == CartDebug::DATA) last = tag.address - 1; - buf << (type == CartDebug::CODE ? "CODE" : - type == CartDebug::DATA ? "DATA" : - "GFX") - << " " << HEX4 << start << " " << HEX4 << last << endl; + disasmTypeAsString(buf, type); + buf << " " << HEX4 << start << " " << HEX4 << last << endl; + type = tag.type; start = last = tag.address; } @@ -901,10 +963,30 @@ void CartDebug::getBankDirectives(ostringstream& buf, BankInfo& info) const last = tag.address; } // Grab the last directive, making sure it accounts for all remaining space - buf << (type == CartDebug::CODE ? "CODE" : - type == CartDebug::DATA ? "DATA" : - "GFX") - << " " << HEX4 << start << " " << HEX4 << (info.offset+info.end) << endl; + disasmTypeAsString(buf, type); + buf << " " << HEX4 << start << " " << HEX4 << (info.offset+info.end) << endl; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartDebug::disasmTypeAsString(ostream& buf, DisasmType type) const +{ + switch(type) + { + case CartDebug::BLOCK: + buf << "BLOCK"; + break; + case CartDebug::CODE: + buf << "CODE"; + break; + case CartDebug::DATA: + buf << "DATA"; + break; + case CartDebug::GFX: + buf << "GFX"; + break; + default: + break; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 19275e9f7..fd4b17534 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -54,10 +54,11 @@ class CartDebug : public DebuggerSystem public: enum DisasmType { - GFX = 1 << 0, - DATA = 1 << 1, - CODE = 1 << 2, - NONE = 1 << 3 + GFX = 1 << 0, + DATA = 1 << 1, + CODE = 1 << 2, + BLOCK = 1 << 3, + NONE = 1 << 4 }; struct DisassemblyTag { DisasmType type; @@ -212,7 +213,7 @@ class CartDebug : public DebuggerSystem /** Load user equates from the given symbol file (as generated by DASM). */ - string loadSymbolFile(const string& file = ""); + string loadSymbolFile(string file = ""); /** Load/save Distella config file (Distella directives) @@ -257,7 +258,7 @@ class CartDebug : public DebuggerSystem uInt16 start; // start of address space uInt16 end; // end of address space uInt16 offset; // ORG value - uInt16 banksize; // size of a bank (in bytes) + uInt16 size; // size of a bank (in bytes) AddressList addressList; // addresses which PC has hit DirectiveList directiveList; // overrides for automatic code determination } BankInfo; @@ -268,7 +269,10 @@ class CartDebug : public DebuggerSystem // Analyze of bank of ROM, generating a list of Distella directives // based on its disassembly - void getBankDirectives(ostringstream& buf, BankInfo& info) const; + void getBankDirectives(ostream& buf, BankInfo& info) const; + + // Convert disassembly enum type to corresponding string and append to buf + void disasmTypeAsString(ostream& buf, DisasmType type) const; // Extract labels and values from the given character stream string extractLabel(const char* c) const; diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index 3b8d54b10..575799001 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -209,11 +209,7 @@ void Debugger::setConsole(Console* console) myCpuDebug = new CpuDebug(*this, *myConsole); delete myCartDebug; - // Register any RAM areas in the Cartridge - // Zero-page RAM is automatically recognized by CartDebug myCartDebug = new CartDebug(*this, *myConsole, *myOSystem); - myCartDebug->loadSymbolFile(myOSystem->romFile()); - myCartDebug->loadConfigFile(); delete myRiotDebug; myRiotDebug = new RiotDebug(*this, *myConsole); @@ -770,7 +766,7 @@ string Debugger::builtinHelp() const if(len > i_maxlen) i_maxlen = len; } - buf << endl << "Built-in functions:" << endl; + buf << setfill(' ') << endl << "Built-in functions:" << endl; for(int i = 0; builtin_functions[i][0] != 0; ++i) { buf << setw(c_maxlen) << left << builtin_functions[i][0] diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index 4aa524eae..f6024e388 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -39,7 +39,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, if(start & 0x1000) { - if(info.banksize == 4096) // 4K ROM space + if(info.size == 4096) // 4K ROM space { /*============================================ The offset is the address where the code segment @@ -76,7 +76,7 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, myOffset = 0; } - myAppData.length = info.banksize; + myAppData.length = info.size; info.start = myAppData.start; info.end = myAppData.end; @@ -785,6 +785,9 @@ void DiStella::addEntry(CartDebug::DisasmType type) myDisasmBuf.seekg(11, ios::beg); switch(tag.type) { + case CartDebug::BLOCK: + // TODO - handle this + break; case CartDebug::CODE: getline(myDisasmBuf, tag.disasm, '\''); getline(myDisasmBuf, tag.ccount, '\''); diff --git a/src/debugger/gui/PromptWidget.cxx b/src/debugger/gui/PromptWidget.cxx index 4062ff0ef..a5a446595 100644 --- a/src/debugger/gui/PromptWidget.cxx +++ b/src/debugger/gui/PromptWidget.cxx @@ -497,6 +497,8 @@ void PromptWidget::loadConfig() // Take care of one-time debugger stuff print(instance().debugger().autoExec().c_str()); + print(instance().debugger().cartDebug().loadConfigFile() + "\n"); + print(instance().debugger().cartDebug().loadSymbolFile() + "\n"); print(PROMPT); _promptStartPos = _promptEndPos = _currentPos; diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index b171850fb..7a6e52d84 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -817,8 +817,12 @@ uInt8* OSystem::openROM(string file, string& md5, uInt32& size) if(!myPropSet->getMD5(md5, props)) { // Get the filename from the rom pathname - string::size_type pos = file.find_last_of("/\\"); - if(pos != string::npos) file = file.substr(pos+1); + FilesystemNode node(file); + file = node.getDisplayName(); + + // Remove extension + string::size_type pos = file.find_last_of("."); + if(pos != string::npos) file = file.substr(0, pos); props.set(Cartridge_MD5, md5); props.set(Cartridge_Name, file);