From e0dd8b145183a44e9f6d23ba93c611d32f373813 Mon Sep 17 00:00:00 2001 From: stephena Date: Mon, 30 Aug 2010 12:04:56 +0000 Subject: [PATCH] First pass at extending the disassembler to support CODE/DATA/GFX commands from a Distella config file. For now, the commands are only accessible within the debugger prompt, and can only be added (no removal/editing). git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2120 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- src/debugger/CartDebug.cxx | 62 ++++++++----- src/debugger/CartDebug.hxx | 51 ++++++++--- src/debugger/DebuggerParser.cxx | 128 ++++++++++++++++++++++---- src/debugger/DebuggerParser.hxx | 5 +- src/debugger/DiStella.cxx | 141 +++++++++++++++++++++++------ src/debugger/DiStella.hxx | 9 +- src/debugger/gui/RomListWidget.cxx | 32 +++++-- src/debugger/gui/RomWidget.cxx | 2 + 8 files changed, 336 insertions(+), 94 deletions(-) diff --git a/src/debugger/CartDebug.cxx b/src/debugger/CartDebug.cxx index 138c5b0be..a05af9694 100644 --- a/src/debugger/CartDebug.cxx +++ b/src/debugger/CartDebug.cxx @@ -37,15 +37,15 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const RamAreaList& areas) for(RamAreaList::const_iterator i = areas.begin(); i != areas.end(); ++i) addRamArea(i->start, i->size, i->roffset, i->woffset); - // Create an addresslist for each potential bank, and an extra one for ZP RAM + // Create bank information for each potential bank, and an extra one for ZP RAM for(int i = 0; i < myConsole.cartridge().bankCount()+1; ++i) { - AddressList l; - myEntryAddresses.push_back(l); + BankInfo info; + myBankInfo.push_back(info); } // We know the address for the startup bank right now - myEntryAddresses[myConsole.cartridge().startBank()].push_back(myDebugger.dpeek(0xfffc)); + myBankInfo[myConsole.cartridge().startBank()].addressList.push_back(myDebugger.dpeek(0xfffc)); addLabel("START", myDebugger.dpeek(0xfffc)); // Add system equates @@ -64,9 +64,12 @@ CartDebug::~CartDebug() myUserAddresses.clear(); mySystemAddresses.clear(); - for(uInt32 i = 0; i < myEntryAddresses.size(); ++i) - myEntryAddresses[i].clear(); - myEntryAddresses.clear(); + for(uInt32 i = 0; i < myBankInfo.size(); ++i) + { + myBankInfo[i].addressList.clear(); + myBankInfo[i].directiveList.clear(); + } + myBankInfo.clear(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -206,14 +209,15 @@ bool CartDebug::disassemble(const string& resolvedata, bool force) if(changed) { // Are we disassembling from ROM or ZP RAM? - AddressList& addresses = (PC & 0x1000) ? myEntryAddresses[getBank()] : - myEntryAddresses[myEntryAddresses.size()-1]; + BankInfo& info = (PC & 0x1000) ? myBankInfo[getBank()] : + myBankInfo[myBankInfo.size()-1]; // If the offset has changed, all old addresses must be 'converted' // For example, if the list contains any $fxxx and the address space is now // $bxxx, it must be changed uInt16 offset = (PC - (PC % 0x1000)); - for(AddressList::iterator i = addresses.begin(); i != addresses.end(); ++i) + AddressList& addresses = info.addressList; + for(list::iterator i = addresses.begin(); i != addresses.end(); ++i) *i = (*i & 0xFFF) + offset; // Only add addresses when absolutely necessary, to cut down on the @@ -239,14 +243,14 @@ bool CartDebug::disassemble(const string& resolvedata, bool force) // Check whether to use the 'resolvedata' functionality from Distella if(resolvedata == "never") - fillDisassemblyList(addresses, false, PC); + fillDisassemblyList(info, false, PC); else if(resolvedata == "always") - fillDisassemblyList(addresses, true, PC); + fillDisassemblyList(info, true, PC); else // 'auto' { // First try with resolvedata on, then turn off if PC isn't found - if(!fillDisassemblyList(addresses, true, PC)) - fillDisassemblyList(addresses, false, PC); + if(!fillDisassemblyList(info, true, PC)) + fillDisassemblyList(info, false, PC); } } @@ -254,8 +258,7 @@ bool CartDebug::disassemble(const string& resolvedata, bool force) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CartDebug::fillDisassemblyList(AddressList& addresses, - bool resolvedata, uInt16 search) +bool CartDebug::fillDisassemblyList(BankInfo& info, bool resolvedata, uInt16 search) { bool found = false; @@ -263,7 +266,7 @@ bool CartDebug::fillDisassemblyList(AddressList& addresses, myDisassembly.fieldwidth = 10 + myLabelLength; uInt16 banksize = !BSPF_equalsIgnoreCase(myConsole.cartridge().name(), "Cartridge2K") ? 4 : 2; - DiStella distella(*this, myDisassembly.list, addresses, banksize, resolvedata); + DiStella distella(*this, myDisassembly.list, info, banksize, resolvedata); // Parts of the disassembly will be accessed later in different ways // We place those parts in separate maps, to speed up access @@ -272,8 +275,8 @@ bool CartDebug::fillDisassemblyList(AddressList& addresses, { const DisassemblyTag& tag = myDisassembly.list[i]; - // Only non-zero addresses are valid - if(tag.address != 0) + // Only addresses marked as 'CODE' can possibly be in the program counter + if(tag.type == CODE) { // Create a mapping from addresses to line numbers myAddrToLineList.insert(make_pair(tag.address, i)); @@ -297,11 +300,11 @@ int CartDebug::addressToLine(uInt16 address) const string CartDebug::disassemble(uInt16 start, uInt16 lines) const { Disassembly disasm; - AddressList addresses; - addresses.push_back(start); + BankInfo info; + info.addressList.push_back(start); uInt16 banksize = !BSPF_equalsIgnoreCase(myConsole.cartridge().name(), "Cartridge2K") ? 4 : 2; - DiStella distella(*this, disasm.list, addresses, banksize, false); + DiStella distella(*this, disasm.list, info, banksize, false); // Fill the string with disassembled data start &= 0xFFF; @@ -335,6 +338,21 @@ string CartDebug::disassemble(uInt16 start, uInt16 lines) const return buffer.str(); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void CartDebug::addDirective(CartDebug::DisasmType type, uInt16 start, uInt16 end) +{ + BankInfo& info = (myDebugger.cpuDebug().pc() & 0x1000) ? + myBankInfo[getBank()] : myBankInfo[myBankInfo.size()-1]; + + DirectiveTag tag; + tag.type = type; + tag.start = start; + tag.end = end; + info.directiveList.push_back(tag); + +// FIXME - process the request somehow; don't just automatically add it to the list +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - int CartDebug::getBank() { diff --git a/src/debugger/CartDebug.hxx b/src/debugger/CartDebug.hxx index 48309ac61..9848a37cb 100644 --- a/src/debugger/CartDebug.hxx +++ b/src/debugger/CartDebug.hxx @@ -32,9 +32,6 @@ class System; #include "StringList.hxx" #include "DebuggerSystem.hxx" -// Array of addresses -typedef list AddressList; - // pointer types for CartDebug instance methods typedef int (CartDebug::*CARTDEBUG_INT_METHOD)(); @@ -55,7 +52,14 @@ class CartDebug : public DebuggerSystem friend class DiStella; public: + enum DisasmType { + GFX = 1 << 0, + DATA = 1 << 1, + CODE = 1 << 2, + NONE = 1 << 3 + }; struct DisassemblyTag { + DisasmType type; uInt16 address; string label; string disasm; @@ -146,6 +150,20 @@ class CartDebug : public DebuggerSystem */ string disassemble(uInt16 start, uInt16 lines) const; + /** + Add a directive to the disassembler. Directives are basically overrides + for the automatic code determination algorithm in Distella, since some + things can't be automatically determined. For now, these directives + have exactly the same syntax as in a distella configuration file. + + @param type Currently, CODE/DATA/GFX are supported + @param start The start address (inclusive) to mark with the given type + @param end The end address (inclusive) to mark with the given type + + @return The disassembly represented as a string + */ + void addDirective(CartDebug::DisasmType type, uInt16 start, uInt16 end); + // The following are convenience methods that query the cartridge object // for the desired information. /** @@ -212,10 +230,25 @@ class CartDebug : public DebuggerSystem }; AddrType addressType(uInt16 addr) const; + typedef struct { + DisasmType type; + uInt16 start; + uInt16 end; + } DirectiveTag; + typedef list AddressList; + typedef list DirectiveList; + + typedef struct { + uInt16 start; // start of address space + uInt16 end; // end of address space + uInt16 offset; // ORG value + AddressList addressList; // addresses which PC has hit + DirectiveList directiveList; // overrides for automatic code determination + } BankInfo; + // Actually call DiStella to fill the DisassemblyList structure // Return whether the search address was actually in the list - bool fillDisassemblyList(AddressList& addresses, - bool resolvedata, uInt16 search); + bool fillDisassemblyList(BankInfo& bankinfo, bool resolvedata, uInt16 search); // Extract labels and values from the given character stream string extractLabel(const char* c) const; @@ -225,12 +258,8 @@ class CartDebug : public DebuggerSystem CartState myState; CartState myOldState; - // A list of 'entry' addresses for each bank in a cart - // An entry address is the one at which time the debugger 'enters' the - // disassembler - // The startup bank will normally be 0xfffc, while the others are - // determined when the debugger is first opened - Common::Array myEntryAddresses; + // A complete record of relevant diassembly information for each bank + Common::Array myBankInfo; // Used for the disassembly display, and mapping from addresses // to corresponding lines of text in that display diff --git a/src/debugger/DebuggerParser.cxx b/src/debugger/DebuggerParser.cxx index 17d1ceab2..e76cc3446 100644 --- a/src/debugger/DebuggerParser.cxx +++ b/src/debugger/DebuggerParser.cxx @@ -790,6 +790,27 @@ void DebuggerParser::executeCls() commandResult << ""; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "code" +void DebuggerParser::executeCode() +{ + if(argCount != 2) + { + commandResult << red("Specify start and end of range only"); + return; + } + else if(args[1] < args[0]) + { + commandResult << red("Start address must be <= end address"); + return; + } + + debugger->cartDebug().addDirective(CartDebug::CODE, args[0], args[1]); + commandResult << "added CODE directive on range $" << hex << args[0] + << " $" << hex << args[1]; + debugger->myRom->invalidate(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "colortest" void DebuggerParser::executeColortest() @@ -809,6 +830,27 @@ void DebuggerParser::executeD() debugger->cpuDebug().setD(args[0]); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "data" +void DebuggerParser::executeData() +{ + if(argCount != 2) + { + commandResult << red("Specify start and end of range only"); + return; + } + else if(args[1] < args[0]) + { + commandResult << red("Start address must be <= end address"); + return; + } + + debugger->cartDebug().addDirective(CartDebug::DATA, args[0], args[1]); + commandResult << "added DATA directive on range $" << hex << args[0] + << " $" << hex << args[1]; + debugger->myRom->invalidate(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "define" void DebuggerParser::executeDefine() @@ -895,25 +937,6 @@ void DebuggerParser::executeExec() commandResult << exec(file); } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// "help" -void DebuggerParser::executeHelp() -{ - // Find length of longest command - uInt16 clen = 0; - for(int i = 0; i < kNumCommands; ++i) - { - uInt16 len = commands[i].cmdString.length(); - if(len > clen) clen = len; - } - - for(int i = 0; i < kNumCommands; ++i) - commandResult << setw(clen) << right << commands[i].cmdString - << " - " << commands[i].description << endl; - - commandResult << debugger->builtinHelp(); -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "frame" void DebuggerParser::executeFrame() @@ -945,6 +968,46 @@ void DebuggerParser::executeFunction() commandResult << red("invalid expression"); } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "gfx" +void DebuggerParser::executeGfx() +{ + if(argCount != 2) + { + commandResult << red("Specify start and end of range only"); + return; + } + else if(args[1] < args[0]) + { + commandResult << red("Start address must be <= end address"); + return; + } + + debugger->cartDebug().addDirective(CartDebug::GFX, args[0], args[1]); + commandResult << "added GFX directive on range $" << hex << args[0] + << " $" << hex << args[1]; + debugger->myRom->invalidate(); +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// "help" +void DebuggerParser::executeHelp() +{ + // Find length of longest command + uInt16 clen = 0; + for(int i = 0; i < kNumCommands; ++i) + { + uInt16 len = commands[i].cmdString.length(); + if(len > clen) clen = len; + } + + for(int i = 0; i < kNumCommands; ++i) + commandResult << setw(clen) << right << commands[i].cmdString + << " - " << commands[i].description << endl; + + commandResult << debugger->builtinHelp(); +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // "listbreaks" void DebuggerParser::executeListbreaks() @@ -1475,6 +1538,15 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { &DebuggerParser::executeCls }, + { + "code", + "Mark 'CODE' range in disassembly", + true, + true, + { kARG_WORD, kARG_MULTI_BYTE }, + &DebuggerParser::executeCode + }, + { "colortest", "Show value xx as TIA color", @@ -1493,6 +1565,15 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { &DebuggerParser::executeD }, + { + "data", + "Mark 'DATA' range in disassembly", + true, + true, + { kARG_WORD, kARG_MULTI_BYTE }, + &DebuggerParser::executeData + }, + { "define", "Define label xx for address yy", @@ -1574,6 +1655,15 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = { &DebuggerParser::executeFunction }, + { + "gfx", + "Mark 'CFX' range in disassembly", + true, + true, + { kARG_WORD, kARG_MULTI_BYTE }, + &DebuggerParser::executeGfx + }, + { "help", "This cruft", diff --git a/src/debugger/DebuggerParser.hxx b/src/debugger/DebuggerParser.hxx index 9a8134d4f..f45ee3043 100644 --- a/src/debugger/DebuggerParser.hxx +++ b/src/debugger/DebuggerParser.hxx @@ -83,7 +83,7 @@ class DebuggerParser private: enum { - kNumCommands = 57, + kNumCommands = 60, kMAX_ARG_TYPES = 10 }; @@ -145,8 +145,10 @@ class DebuggerParser void executeCleartraps(); void executeClearwatches(); void executeCls(); + void executeCode(); void executeColortest(); void executeD(); + void executeData(); void executeDefine(); void executeDelbreakif(); void executeDelfunction(); @@ -156,6 +158,7 @@ class DebuggerParser void executeExec(); void executeFrame(); void executeFunction(); + void executeGfx(); void executeHelp(); void executeListbreaks(); void executeListfunctions(); diff --git a/src/debugger/DiStella.cxx b/src/debugger/DiStella.cxx index b9bbd0ba5..4c4826ba3 100644 --- a/src/debugger/DiStella.cxx +++ b/src/debugger/DiStella.cxx @@ -23,17 +23,18 @@ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, - AddressList& addresses, uInt16 banksize, bool resolvedata) + CartDebug::BankInfo& info, uInt16 banksize, bool resolvedata) : myDbg(dbg), myList(list) { + CartDebug::AddressList addresses = info.addressList; if(addresses.size() == 0) return; while(!myAddressQueue.empty()) myAddressQueue.pop(); - AddressList::iterator it = addresses.begin(); + CartDebug::AddressList::iterator it = addresses.begin(); uInt16 start = *it++; if(start & 0x1000) @@ -79,6 +80,10 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, myOffset = 0; } + info.start = myAppData.start; + info.end = myAppData.end; + info.offset = myOffset; + memset(labels, 0, 0x1000); myAddressQueue.push(start); @@ -129,6 +134,9 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, } } + // Process any directives later, as they override automatic code determination + processDirectives(info.directiveList); + // Second pass disasm(myOffset, 2); @@ -174,10 +182,10 @@ void DiStella::disasm(uInt32 distart, int pass) else myDisasmBuf << HEX4 << myPC+myOffset << "' '"; - myDisasmBuf << ".byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset) << " ; "; + myDisasmBuf << ".byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset) << " "; showgfx(Debugger::debugger().peek(myPC+myOffset)); - myDisasmBuf << " $" << HEX4 << myPC+myOffset; - addEntry(); + myDisasmBuf << " $" << HEX4 << myPC+myOffset << "'" << HEX2 << Debugger::debugger().peek(myPC+myOffset); + addEntry(CartDebug::GFX); } myPC++; } @@ -201,7 +209,7 @@ void DiStella::disasm(uInt32 distart, int pass) bytes++; if (bytes == 17) { - addEntry(); + addEntry(CartDebug::DATA); myDisasmBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset); bytes = 1; } @@ -213,9 +221,9 @@ void DiStella::disasm(uInt32 distart, int pass) if (pass == 3) { - addEntry(); + addEntry(CartDebug::DATA); myDisasmBuf << " ' ' "; - addEntry(); + addEntry(CartDebug::NONE); } } else @@ -275,7 +283,7 @@ void DiStella::disasm(uInt32 distart, int pass) /* Line information is already printed; append .byte since last instruction will put recompilable object larger that original binary file */ myDisasmBuf << ".byte $" << HEX2 << (int)op; - addEntry(); + addEntry(CartDebug::DATA); if (myPC == myAppData.end) { @@ -286,7 +294,7 @@ void DiStella::disasm(uInt32 distart, int pass) op = Debugger::debugger().peek(myPC+myOffset); myPC++; myDisasmBuf << ".byte $" << HEX2 << (int)op; - addEntry(); + addEntry(CartDebug::DATA); } } myPCEnd = myAppData.end + myOffset; @@ -306,7 +314,7 @@ void DiStella::disasm(uInt32 distart, int pass) /* Line information is already printed, but we can remove the Instruction (i.e. BMI) by simply clearing the buffer to print */ myDisasmBuf << ".byte $" << HEX2 << (int)op; - addEntry(); + addEntry(CartDebug::DATA); nextline.str(""); nextlinebytes.str(""); } @@ -615,11 +623,11 @@ void DiStella::disasm(uInt32 distart, int pass) myDisasmBuf << nextline.str() << "'" << ";" << dec << (int)ourLookup[op].cycles << "'" << nextlinebytes.str(); - addEntry(); + addEntry(CartDebug::CODE); if (op == 0x40 || op == 0x60) { myDisasmBuf << " ' ' "; - addEntry(); + addEntry(CartDebug::NONE); } nextline.str(""); @@ -646,8 +654,8 @@ int DiStella::mark(uInt32 address, MarkType bit) We sweep for hardware/system equates, which are valid addresses, outside the scope of the code/data range. For these, we mark its corresponding hardware/system array element, and return "2" or "3" - (depending on which system/hardware element was accessed), or "5" - for zero-page RAM. If this was not the case... + (depending on which system/hardware element was accessed). + If this was not the case... Next we check if it is a code "mirror". For the 2600, address ranges are limited with 13 bits, so other addresses can exist outside of the @@ -708,28 +716,44 @@ int DiStella::mark(uInt32 address, MarkType bit) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void DiStella::showgfx(uInt8 c) { -#if 0 - int i; - myDisasmBuf << "|"; - for(i = 0;i < 8; i++) - { - if (c > 127) - myDisasmBuf << "X"; - else - myDisasmBuf << " "; - - c = c << 1; - } + for(int i = 0; i < 8; ++i, c <<= 1) + myDisasmBuf << ((c > 127) ? "X" : " "); myDisasmBuf << "|"; -#endif } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DiStella::addEntry() +bool DiStella::check_range(uInt32 beg, uInt32 end) +{ + if(beg > end) + { + cerr << "Beginning of range greater than end: start = " << hex << beg + << ", end = " << hex << endl; + return false; + } + else if(beg > myAppData.end + myOffset) + { + cerr << "Beginning of range out of range: start = " << hex << beg + << ", range = " << hex << (myAppData.end + myOffset) << endl; + return false; + } + else if(beg < myOffset) + { + cerr << "Beginning of range out of range: start = " << hex << beg + << ", offset = " << hex << myOffset << endl; + return false; + } + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DiStella::addEntry(CartDebug::DisasmType type) { CartDebug::DisassemblyTag tag; + // Type + tag.type = type; + // Address myDisasmBuf.seekg(0, ios::beg); if(myDisasmBuf.peek() == ' ') @@ -766,6 +790,25 @@ void DiStella::addEntry() // Up to this point the field sizes are fixed, until we get to // variable length labels, cycle counts, etc myDisasmBuf.seekg(11, ios::beg); + switch(tag.type) + { + case CartDebug::CODE: + getline(myDisasmBuf, tag.disasm, '\''); + getline(myDisasmBuf, tag.ccount, '\''); + getline(myDisasmBuf, tag.bytes); + break; + case CartDebug::DATA: + getline(myDisasmBuf, tag.disasm); + break; + case CartDebug::GFX: + getline(myDisasmBuf, tag.disasm, '\''); + getline(myDisasmBuf, tag.bytes); + break; + case CartDebug::NONE: + tag.disasm = " "; + break; + } +/* switch(myDisasmBuf.peek()) { case ' ': @@ -780,11 +823,51 @@ void DiStella::addEntry() getline(myDisasmBuf, tag.bytes); break; } +*/ myList.push_back(tag); DONE_WITH_ADD: myDisasmBuf.clear(); myDisasmBuf.str(""); + +#if 0 + // debugging output + cerr << (tag.type == CartDebug::CODE ? "CODE" : (tag.type == CartDebug::DATA ? "DATA" : + (tag.type == CartDebug::GFX ? "GFX " : "NONE"))) << "|" + << hex << setw(4) << setfill('0') << tag.address << "|" + << tag.label << "|" << tag.disasm << "|" << tag.ccount << "|" << "|" + << tag.bytes << endl; +#endif +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +void DiStella::processDirectives(const CartDebug::DirectiveList& directives) +{ + for(CartDebug::DirectiveList::const_iterator i = directives.begin(); + i != directives.end(); ++i) + { + const CartDebug::DirectiveTag tag = *i; + if(check_range(tag.start, tag.end)) + { + MarkType type; + switch(tag.type) + { + case CartDebug::DATA : + type = DATA; + break; + case CartDebug::GFX : + type = GFX; + break; + case CartDebug::CODE : + type = REACHABLE; + break; + default: + continue; // skip this tag + } + for(uInt32 k = tag.start; k <= tag.end; ++k) + mark(k, type); + } + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/debugger/DiStella.hxx b/src/debugger/DiStella.hxx index 2cb5d937c..694de061c 100644 --- a/src/debugger/DiStella.hxx +++ b/src/debugger/DiStella.hxx @@ -53,7 +53,7 @@ class DiStella @param resolvedata If enabled, try to determine code vs. data sections */ DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list, - AddressList& addresses, uInt16 banksize = 4, bool resolvedata = true); + CartDebug::BankInfo& info, uInt16 banksize = 4, bool resolvedata = true); ~DiStella(); @@ -74,12 +74,17 @@ class DiStella // Indicate that a new line of disassembly has been completed // In the original Distella code, this indicated a new line to be printed // Here, we add a new entry to the DisassemblyList - void addEntry(); + void addEntry(CartDebug::DisasmType type); + + // Process directives given in the list + // Directives are basically the contents of a distella configuration file + void processDirectives(const CartDebug::DirectiveList& directives); // These functions are part of the original Distella code void disasm(uInt32 distart, int pass); int mark(uInt32 address, MarkType bit); void showgfx(uInt8 c); + bool check_range(uInt32 start, uInt32 end); inline int check_bit(uInt8 bitflags, int i) const { return (bitflags & i); } private: diff --git a/src/debugger/gui/RomListWidget.cxx b/src/debugger/gui/RomListWidget.cxx index 7e847a559..957b65a8f 100644 --- a/src/debugger/gui/RomListWidget.cxx +++ b/src/debugger/gui/RomListWidget.cxx @@ -64,6 +64,7 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& font, l.push_back("Save ROM", "saverom"); l.push_back("Set PC", "setpc"); l.push_back("RunTo PC", "runtopc"); + l.push_back("Re-disassemble", "disasm"); myMenu = new ContextMenu(this, font, l); // Take advantage of a wide debugger window when possible @@ -121,6 +122,8 @@ void RomListWidget::setList(const CartDebug::Disassembly& disasm, myCheckList[i]->clearFlags(WIDGET_ENABLED); recalc(); + + setDirty(); draw(); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -425,7 +428,8 @@ void RomListWidget::drawWidget(bool hilite) // Draw the list items int ccountw = _fontWidth << 1, large_disasmw = _w - l.x() - _labelWidth, - small_disasmw = large_disasmw - r.width() - (ccountw << 1), + medium_disasmw = large_disasmw - r.width(), + small_disasmw = medium_disasmw - (ccountw << 1), actualwidth = myDisasm->fieldwidth * _fontWidth; if(actualwidth < small_disasmw) small_disasmw = actualwidth; @@ -454,16 +458,24 @@ void RomListWidget::drawWidget(bool hilite) // Draw labels s.drawString(_font, dlist[pos].label, xpos, ypos, _labelWidth, kTextColor); - // Sometimes there aren't any bytes to display, in which case the disassembly - // should get all remaining space - if(dlist[pos].bytes != "") + // Bytes are only editable if they represent code or graphics + // Otherwise, the disassembly should get all remaining space + if(dlist[pos].type & (CartDebug::CODE | CartDebug::GFX)) { - // Draw disassembly and cycle count - // TODO - cycle count should be aligned as close as possible to the disassembly - s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos, - small_disasmw, kTextColor); - s.drawString(_font, dlist[pos].ccount, xpos + _labelWidth + small_disasmw, ypos, - ccountw, kTextColor); + if(dlist[pos].type == CartDebug::CODE) + { + // Draw disassembly and cycle count + s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos, + small_disasmw, kTextColor); + s.drawString(_font, dlist[pos].ccount, xpos + _labelWidth + small_disasmw, ypos, + ccountw, kTextColor); + } + else + { + // Draw disassembly only + s.drawString(_font, dlist[pos].disasm, xpos + _labelWidth, ypos, + medium_disasmw, kTextColor); + } // Draw separator s.vLine(_x + r.x() - 7, ypos, ypos + _fontHeight - 1, kColor); diff --git a/src/debugger/gui/RomWidget.cxx b/src/debugger/gui/RomWidget.cxx index 53aad6b7e..dc69b3769 100644 --- a/src/debugger/gui/RomWidget.cxx +++ b/src/debugger/gui/RomWidget.cxx @@ -172,6 +172,8 @@ void RomWidget::handleCommand(CommandSender* sender, int cmd, int data, int id) setPC(myRomList->getSelected()); else if(rmb == "runtopc") runtoPC(myRomList->getSelected()); + else if(rmb == "disasm") + invalidate(); break; }