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
This commit is contained in:
stephena 2010-09-06 23:29:05 +00:00
parent 2d08d4e459
commit 7f75957e11
7 changed files with 156 additions and 65 deletions

View File

@ -22,7 +22,7 @@
#include <cstdlib>
#define STELLA_VERSION "3.3_test2"
#define STELLA_VERSION "3.3_test3"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif

View File

@ -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<BankInfo>::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;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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;

View File

@ -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]

View File

@ -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, '\'');

View File

@ -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;

View File

@ -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);