*Many* improvements to the debugger disassembly, both in-GUI and in saving

to an external file.

  - RIOT/TIA mirrors are now used whenever possible.  This includes *all*
    possible mirrors in the entire 64K address space.  This was needed to
    make the disassembly byte-exact when recompiling the ROM.

  - Disassembly to a file now includes all required defined constants
    (RIOT/TIA, non-locatable labels, user-defined, etc).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2737 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2013-05-19 20:55:25 +00:00
parent 640927b1c6
commit 09d7ec7eb9
7 changed files with 317 additions and 199 deletions

View File

@ -12,7 +12,7 @@
Release History
===========================================================================
3.8.1 to 3.9: (XXXXX xxx, 2013)
3.8.1 to 3.9: (June xx, 2013)
* Greatly extended functionality of the debugger disassembly:
- There is now a new tab which lists information specific to the
@ -28,9 +28,9 @@
only differentiates between CODE/GFX/ROW. For now, only
single-bank (4K and smaller) ROMs are supported.
- The disassembly now recognizes various TIA read/write mirrors,
and marks them as such (for example, INPT4.30 instead of INPT4
for address $3C).
- The disassembly now recognizes various TIA/RIOT read/write
mirrors, and marks them as such (for example, INPT4|$30 instead
of INPT4 for address $3C).
- ROMS less than 2K in size (so called 'Sub2K' ROMs) now show only
the actual data in the binary. This means, for example, that a

View File

@ -22,7 +22,7 @@
#include <cstdlib>
#define STELLA_VERSION "3.9_alpha2"
#define STELLA_VERSION "3.9_beta1"
#define STELLA_BUILD atoi("$Rev$" + 6)
#endif

View File

@ -68,21 +68,29 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
addLabel("START", myDebugger.dpeek(0xfffc));
// Add system equates
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
{
mySystemAddresses.insert(make_pair(ourTIAMnemonicR[addr], addr));
if(ourTIAMnemonicR[addr])
mySystemAddresses.insert(make_pair(ourTIAMnemonicR[addr], addr));
myReserved.TIARead[addr] = false;
}
for(uInt16 addr = 0x00; addr <= 0x7F; ++addr)
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
{
mySystemAddresses.insert(make_pair(ourTIAMnemonicW[addr], addr));
if(ourTIAMnemonicW[addr])
mySystemAddresses.insert(make_pair(ourTIAMnemonicW[addr], addr));
myReserved.TIAWrite[addr] = false;
}
for(uInt16 addr = 0x280; addr <= 0x297; ++addr)
{
mySystemAddresses.insert(make_pair(ourIOMnemonic[addr-0x280], addr));
if(ourIOMnemonic[addr-0x280])
mySystemAddresses.insert(make_pair(ourIOMnemonic[addr-0x280], addr));
myReserved.IOReadWrite[addr-0x280] = false;
}
for(uInt16 addr = 0x80; addr <= 0xFF; ++addr)
{
mySystemAddresses.insert(make_pair(ourZPMnemonic[addr-0x80], addr));
myReserved.ZPRAM[addr-0x80] = false;
}
myReserved.Label.clear();
@ -303,7 +311,7 @@ bool CartDebug::fillDisassemblyList(BankInfo& info, bool resolvedata, uInt16 sea
{
myDisassembly.list.clear();
myDisassembly.list.reserve(2048);
myDisassembly.fieldwidth = 10 + myLabelLength;
myDisassembly.fieldwidth = 14 + myLabelLength;
DiStella distella(*this, myDisassembly.list, info, DiStella::settings,
myDisLabels, myDisDirectives, myReserved, resolvedata);
@ -543,7 +551,7 @@ bool CartDebug::addLabel(const string& label, uInt16 address)
switch(addressType(address))
{
case ADDR_TIA:
case ADDR_RIOT:
case ADDR_IO:
return false;
default:
removeLabel(label);
@ -576,43 +584,110 @@ bool CartDebug::removeLabel(const string& label)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& CartDebug::getLabel(uInt16 addr, bool isRead, int places) const
bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead, int places) const
{
static string result;
switch(addressType(addr))
{
case ADDR_TIA:
return result =
(isRead ? ourTIAMnemonicR[addr&0x3f] : ourTIAMnemonicW[addr&0x7f]);
case ADDR_RIOT:
{
uInt16 idx = (addr&0xff) - 0x80;
if(idx < 24)
return result = ourIOMnemonic[idx];
break;
if(isRead)
{
uInt16 a = addr & 0x0F, offset = addr & 0xFFF0;
if(ourTIAMnemonicR[a])
{
buf << ourTIAMnemonicR[a];
if(offset > 0)
buf << "|$" << HEX2 << offset;
}
else
buf << "$" << HEX2 << addr;
}
else
{
uInt16 a = addr & 0x3F, offset = addr & 0xFFC0;
if(ourTIAMnemonicW[a])
{
buf << ourTIAMnemonicW[a];
if(offset > 0)
buf << "|$" << HEX2 << offset;
}
else
buf << "$" << HEX2 << addr;
}
return true;
}
case ADDR_IO:
{
uInt16 a = addr & 0xFF, offset = addr & 0xFD00;
if(a <= 0x97)
{
if(ourIOMnemonic[a - 0x80])
{
buf << ourIOMnemonic[a - 0x80];
if(offset > 0)
buf << "|$" << HEX2 << offset;
}
else
buf << "$" << HEX2 << addr;
}
else
buf << "$" << HEX2 << addr;
return true;
}
case ADDR_ZPRAM:
{
// RAM can use user-defined labels; otherwise we default to
// standard mnemonics
AddrToLabel::const_iterator iter;
if((iter = myUserLabels.find(addr)) != myUserLabels.end())
{
buf << iter->second;
}
else
{
uInt16 a = addr & 0xFF, offset = addr & 0xFF00;
if((iter = myUserLabels.find(a)) != myUserLabels.end())
buf << iter->second;
else
buf << ourZPMnemonic[a - 0x80];
if(offset > 0)
buf << "|$" << HEX2 << offset;
}
return true;
}
case ADDR_RAM:
case ADDR_ROM:
{
// These addresses can never be in the system labels list
AddrToLabel::const_iterator iter;
if((iter = myUserLabels.find(addr)) != myUserLabels.end())
return iter->second;
{
buf << iter->second;
return true;
}
break;
}
}
if(places > -1)
{
ostringstream buf;
buf << "$" << setw(places) << hex << addr;
return result = buf.str();
return true;
}
return EmptyString;
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::getLabel(uInt16 addr, bool isRead, int places) const
{
ostringstream buf;
getLabel(buf, addr, isRead, places);
return buf.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -843,39 +918,73 @@ string CartDebug::saveDisassembly()
// Output stream for disassembly
ostringstream buf;
AddrToLabel::const_iterator iter;
// Some boilerplate, similar to what DiStella adds
time_t currtime;
time(&currtime);
buf << "; Disassembly of " << myOSystem.romFile() << "\n"
<< "; Disassembled " << ctime(&currtime)
<< "; Using Stella " << STELLA_VERSION << "\n;\n"
<< "; Settings used: TODO - add args\n;\n"
<< "; Legend: * = CODE not yet run (preliminary code)\n"
<< "; D = DATA directive (referenced in some way)\n"
<< "; G = GFX directive, shown as '#' (stored in player, missile, ball)\n"
<< "; P = PGFX directive, shown as '*' (stored in playfield)\n"
<< "\n processor 6502\n\n";
<< "; P = PGFX directive, shown as '*' (stored in playfield)\n\n"
<< " processor 6502\n\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; TIA AND IO CONSTANTS\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr][0] != '$')
buf << ALIGN(10) << ourTIAMnemonicR[addr] << " = $"
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr])
buf << ALIGN(6) << ourTIAMnemonicR[addr] << " = $"
<< HEX2 << right << addr << " ; (R)\n";
for(uInt16 addr = 0x00; addr <= 0x7F; ++addr)
if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr][0] != '$')
buf << ALIGN(10) << ourTIAMnemonicW[addr] << " = $"
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr])
buf << ALIGN(6) << ourTIAMnemonicW[addr] << " = $"
<< HEX2 << right << addr << " ; (W)\n";
for(uInt16 addr = 0x00; addr <= 0x17; ++addr)
if(myReserved.IOReadWrite[addr] && ourIOMnemonic[addr][0] != '$')
buf << ALIGN(10) << ourIOMnemonic[addr] << " = $"
if(myReserved.IOReadWrite[addr] && ourIOMnemonic[addr])
buf << ALIGN(6) << ourIOMnemonic[addr] << " = $"
<< HEX4 << right << (addr+0x280) << "\n";
AddrToLabel::const_iterator iter;
for(iter = myReserved.Label.begin(); iter != myReserved.Label.end(); ++iter)
buf << ALIGN(10) << iter->second << " = $" << iter->first << "\n";
buf << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; RIOT (zero-page) RAM\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
for(uInt16 addr = 0x80; addr <= 0xFF; ++addr)
{
if(myReserved.ZPRAM[addr-0x80] &&
myUserLabels.find(addr) == myUserLabels.end())
{
buf << ALIGN(6) << ourZPMnemonic[addr-0x80] << " = $"
<< HEX2 << right << (addr) << "\n";
}
}
buf << "\n";
if(myReserved.Label.size() > 0)
{
buf << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; NON LOCATABLE\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
for(iter = myReserved.Label.begin(); iter != myReserved.Label.end(); ++iter)
buf << ALIGN(10) << iter->second << " = $" << iter->first << "\n";
}
if(myUserLabels.size() > 0)
{
buf << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; USER DEFINED\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
int max_len = 0;
for(iter = myUserLabels.begin(); iter != myUserLabels.end(); ++iter)
max_len = BSPF_max(max_len, (int)iter->second.size());
for(iter = myUserLabels.begin(); iter != myUserLabels.end(); ++iter)
buf << ALIGN(max_len) << iter->second << " = $" << iter->first << "\n";
}
buf << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;\n"
<< "; MAIN PROGRAM\n"
<< ";\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
// Use specific settings for disassembly output
// This will most likely differ from what you see in the debugger
@ -889,7 +998,6 @@ string CartDebug::saveDisassembly()
Disassembly disasm;
disasm.list.reserve(2048);
disasm.fieldwidth = 10 + myLabelLength;
for(int bank = 0; bank < myConsole.cartridge().bankCount(); ++bank)
{
BankInfo& info = myBankInfo[bank];
@ -898,7 +1006,8 @@ string CartDebug::saveDisassembly()
DiStella distella(*this, disasm.list, info, settings,
myDisLabels, myDisDirectives, myReserved, true);
buf << " ORG $" << HEX4 << info.offset << "\n\n";
buf << " SEG CODE\n"
<< " ORG $" << HEX4 << info.offset << "\n\n";
// Format in 'distella' style
for(uInt32 i = 0; i < disasm.list.size(); ++i)
@ -907,15 +1016,14 @@ string CartDebug::saveDisassembly()
// Add label (if any)
if(tag.label != "")
buf << ALIGN(7) << (tag.label+":");
else
buf << " ";
buf << ALIGN(7) << (tag.label+":") << endl;
buf << " ";
switch(tag.type)
{
case CartDebug::CODE:
{
buf << ALIGN(19) << tag.disasm << tag.ccount << "\n";
buf << ALIGN(25) << tag.disasm << tag.ccount << "\n";
break;
}
case CartDebug::NONE:
@ -1042,10 +1150,10 @@ string CartDebug::clearConfig(int bank)
void CartDebug::getCompletions(const char* in, StringList& completions) const
{
// First scan system equates
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
if(BSPF_startsWithIgnoreCase(ourTIAMnemonicR[addr], in))
completions.push_back(ourTIAMnemonicR[addr]);
for(uInt16 addr = 0x00; addr <= 0x7F; ++addr)
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
if(BSPF_startsWithIgnoreCase(ourTIAMnemonicW[addr], in))
completions.push_back(ourTIAMnemonicW[addr]);
for(uInt16 addr = 0; addr <= 0x297-0x280; ++addr)
@ -1068,12 +1176,10 @@ CartDebug::AddrType CartDebug::addressType(uInt16 addr) const
// Determine the type of address to access the correct list
// These addresses were based on (and checked against) Kroko's 2600 memory
// map, found at http://www.qotile.net/minidig/docs/2600_mem_map.txt
AddrType type = ADDR_ROM;
if(addr % 0x2000 < 0x1000)
{
uInt16 z = addr & 0x00ff;
if(z < 0x80)
type = ADDR_TIA;
if((addr & 0x00ff) < 0x80)
return ADDR_TIA;
else
{
switch(addr & 0x0f00)
@ -1086,8 +1192,7 @@ CartDebug::AddrType CartDebug::addressType(uInt16 addr) const
case 0x900:
case 0xc00:
case 0xd00:
type = ADDR_RAM;
break;
return ADDR_ZPRAM;
case 0x200:
case 0x300:
case 0x600:
@ -1096,12 +1201,11 @@ CartDebug::AddrType CartDebug::addressType(uInt16 addr) const
case 0xb00:
case 0xe00:
case 0xf00:
type = ADDR_RIOT;
break;
return ADDR_IO;
}
}
}
return type;
return ADDR_ROM;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1222,51 +1326,44 @@ void CartDebug::disasmTypeAsString(ostream& buf, uInt8 flags) const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* CartDebug::ourTIAMnemonicR[64] = {
// Standard $00-based TIA read locations:
const char* CartDebug::ourTIAMnemonicR[16] = {
"CXM0P", "CXM1P", "CXP0FB", "CXP1FB", "CXM0FB", "CXM1FB", "CXBLPF", "CXPPMM",
"INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", "$0E", "$0F",
// Mirrored $10-based TIA read locations:
"CXM0P.10", "CXM1P.10", "CXP0FB.10", "CXP1FB.10", "CXM0FB.10", "CXM1FB.10",
"CXBLPF.10", "CXPPMM.10", "INPT0.10", "INPT1.10", "INPT2.10", "INPT3.10",
"INPT4.10", "INPT5.10", "$1E", "$1F",
// Mirrored $20-based TIA read locations:
"CXM0P.20", "CXM1P.20", "CXP0FB.20", "CXP1FB.20", "CXM0FB.20", "CXM1FB.20",
"CXBLPF.20", "CXPPMM.20", "INPT0.20", "INPT1.20", "INPT2.20", "INPT3.20",
"INPT4.20", "INPT5.20", "$2E", "$2F",
// Mirrored $30-based TIA read locations:
"CXM0P.30", "CXM1P.30", "CXP0FB.30", "CXP1FB.30", "CXM0FB.30", "CXM1FB.30",
"CXBLPF.30", "CXPPMM.30", "INPT0.30", "INPT1.30", "INPT2.30", "INPT3.30",
"INPT4.30", "INPT5.30", "$3E", "$3F",
"INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", 0, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* CartDebug::ourTIAMnemonicW[128] = {
// Standard $00-based TIA write locations:
const char* CartDebug::ourTIAMnemonicW[64] = {
"VSYNC", "VBLANK", "WSYNC", "RSYNC", "NUSIZ0", "NUSIZ1", "COLUP0", "COLUP1",
"COLUPF", "COLUBK", "CTRLPF", "REFP0", "REFP1", "PF0", "PF1", "PF2",
"RESP0", "RESP1", "RESM0", "RESM1", "RESBL", "AUDC0", "AUDC1", "AUDF0",
"AUDF1", "AUDV0", "AUDV1", "GRP0", "GRP1", "ENAM0", "ENAM1", "ENABL",
"HMP0", "HMP1", "HMM0", "HMM1", "HMBL", "VDELP0", "VDELP1", "VDELBL",
"RESMP0", "RESMP1", "HMOVE", "HMCLR", "CXCLR", "$2D", "$2E", "$2F",
"$30", "$31", "$32", "$33", "$34", "$35", "$36", "$37",
"$38", "$39", "$3A", "$3B", "$3C", "$3D", "$3E", "$3F",
// Mirrored $40-based TIA write locations:
"VSYNC.40", "VBLANK.40", "WSYNC.40", "RSYNC.40", "NUSIZ0.40", "NUSIZ1.40",
"COLUP0.40", "COLUP1.40", "COLUPF.40", "COLUBK.40", "CTRLPF.40", "REFP0.40",
"REFP1.40", "PF0.40", "PF1.40", "PF2.40", "RESP0.40", "RESP1.40", "RESM0.40",
"RESM1.40", "RESBL.40", "AUDC0.40", "AUDC1.40", "AUDF0.40", "AUDF1.40",
"AUDV0.40", "AUDV1.40", "GRP0.40", "GRP1.40", "ENAM0.40", "ENAM1.40",
"ENABL.40", "HMP0.40", "HMP1.40", "HMM0.40", "HMM1.40", "HMBL.40",
"VDELP0.40", "VDELP1.40", "VDELBL.40", "RESMP0.40", "RESMP1.40", "HMOVE.40",
"HMCLR.40", "CXCLR.40", "$6D", "$6E", "$6F",
"$70", "$71", "$72", "$73", "$74", "$75", "$76", "$77",
"$78", "$79", "$7A", "$7B", "$7C", "$7D", "$7E", "$7F"
"RESMP0", "RESMP1", "HMOVE", "HMCLR", "CXCLR", 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* CartDebug::ourIOMnemonic[24] = {
"SWCHA", "SWACNT", "SWCHB", "SWBCNT", "INTIM", "TIMINT", "$0286", "$0287",
"$0288", "$0289", "$028A", "$028B", "$028C", "$028D", "$028E", "$028F",
"$0290", "$0291", "$0292", "$0293", "TIM1T", "TIM8T", "TIM64T", "T1024T"
"SWCHA", "SWACNT", "SWCHB", "SWBCNT", "INTIM", "TIMINT", 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, "TIM1T", "TIM8T", "TIM64T", "T1024T"
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* CartDebug::ourZPMnemonic[128] = {
"ram_80", "ram_81", "ram_82", "ram_83", "ram_84", "ram_85", "ram_86", "ram_87",
"ram_88", "ram_89", "ram_8A", "ram_8B", "ram_8C", "ram_8D", "ram_8E", "ram_8F",
"ram_90", "ram_91", "ram_92", "ram_93", "ram_94", "ram_95", "ram_96", "ram_97",
"ram_98", "ram_99", "ram_9A", "ram_9B", "ram_9C", "ram_9D", "ram_9E", "ram_9F",
"ram_A0", "ram_A1", "ram_A2", "ram_A3", "ram_A4", "ram_A5", "ram_A6", "ram_A7",
"ram_A8", "ram_A9", "ram_AA", "ram_AB", "ram_AC", "ram_AD", "ram_AE", "ram_AF",
"ram_B0", "ram_B1", "ram_B2", "ram_B3", "ram_B4", "ram_B5", "ram_B6", "ram_B7",
"ram_B8", "ram_B9", "ram_BA", "ram_BB", "ram_BC", "ram_BD", "ram_BE", "ram_BF",
"ram_C0", "ram_C1", "ram_C2", "ram_C3", "ram_C4", "ram_C5", "ram_C6", "ram_C7",
"ram_C8", "ram_C9", "ram_CA", "ram_CB", "ram_CC", "ram_CD", "ram_CE", "ram_CF",
"ram_D0", "ram_D1", "ram_D2", "ram_D3", "ram_D4", "ram_D5", "ram_D6", "ram_D7",
"ram_D8", "ram_D9", "ram_DA", "ram_DB", "ram_DC", "ram_DD", "ram_DE", "ram_DF",
"ram_E0", "ram_E1", "ram_E2", "ram_E3", "ram_E4", "ram_E5", "ram_E6", "ram_E7",
"ram_E8", "ram_E9", "ram_EA", "ram_EB", "ram_EC", "ram_ED", "ram_EE", "ram_EF",
"ram_F0", "ram_F1", "ram_F2", "ram_F3", "ram_F4", "ram_F5", "ram_F6", "ram_F7",
"ram_F8", "ram_F9", "ram_FA", "ram_FB", "ram_FC", "ram_FD", "ram_FE", "ram_FF"
};

View File

@ -227,7 +227,8 @@ class CartDebug : public DebuggerSystem
If places is not -1 and a label hasn't been defined, return a
formatted hexidecimal address
*/
const string& getLabel(uInt16 addr, bool isRead, int places = -1) const;
bool getLabel(ostream& buf, uInt16 addr, bool isRead, int places = -1) const;
string getLabel(uInt16 addr, bool isRead, int places = -1) const;
int getAddress(const string& label) const;
/**
@ -275,8 +276,8 @@ class CartDebug : public DebuggerSystem
// Determine 'type' of address (ie, what part of the system accessed)
enum AddrType {
ADDR_TIA,
ADDR_RAM,
ADDR_RIOT,
ADDR_IO,
ADDR_ZPRAM,
ADDR_ROM
};
AddrType addressType(uInt16 addr) const;
@ -305,9 +306,10 @@ class CartDebug : public DebuggerSystem
// Information on equates used in the disassembly
struct ReservedEquates {
bool TIARead[64];
bool TIAWrite[128];
bool TIARead[16];
bool TIAWrite[64];
bool IOReadWrite[24];
bool ZPRAM[128];
AddrToLabel Label;
};
ReservedEquates myReserved;
@ -370,9 +372,10 @@ class CartDebug : public DebuggerSystem
string mySymbolFile, myCfgFile, myDisasmFile, myRomFile;
/// Table of instruction mnemonics
static const char* ourTIAMnemonicR[64]; // read mode
static const char* ourTIAMnemonicW[128]; // write mode
static const char* ourTIAMnemonicR[16]; // read mode
static const char* ourTIAMnemonicW[64]; // write mode
static const char* ourIOMnemonic[24];
static const char* ourZPMnemonic[128];
};
#endif

View File

@ -221,10 +221,8 @@ DiStella::~DiStella()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DiStella::disasm(uInt32 distart, int pass)
{
#define USER_OR_AUTO_LABEL(pre, address, post) \
const string& l = myDbg.getLabel(address, true); \
if(l != EmptyString) nextline << pre << l << post; \
else nextline << pre << "L" << HEX4 << address << post;
#define LABEL_A12_HIGH(address) labelA12High(nextline, op, address, labfound)
#define LABEL_A12_LOW(address) labelA12Low(nextline, op, address, labfound)
uInt8 op, d1;
uInt16 ad;
@ -517,24 +515,26 @@ void DiStella::disasm(uInt32 distart, int pass)
if (labfound == 1)
{
USER_OR_AUTO_LABEL("", ad, "");
LABEL_A12_HIGH(ad);
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
else if (labfound == 3)
else if (labfound == 4)
{
nextline << CartDebug::ourIOMnemonic[ad-0x280];
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
myReserved.IOReadWrite[ad-0x280] = true;
}
else if (labfound == 4 && mySettings.rflag)
{
int tmp = (ad & myAppData.end)+myOffset;
USER_OR_AUTO_LABEL("", tmp, "");
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
if(mySettings.rflag)
{
int tmp = (ad & myAppData.end)+myOffset;
LABEL_A12_HIGH(tmp);
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
}
else
{
nextline << "$" << HEX4 << ad;
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
}
else
{
nextline << "$" << HEX4 << ad;
LABEL_A12_LOW(ad);
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
}
@ -550,19 +550,15 @@ void DiStella::disasm(uInt32 distart, int pass)
if (labfound == 2)
{
if(ourLookup[op].rw_mode == READ)
{
nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x3f];
myReserved.TIARead[d1&0x3f] = true;
}
myReserved.TIARead[d1 & 0x0F] = true;
else
{
nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x7f];
myReserved.TIAWrite[d1&0x7f] = true;
}
myReserved.TIAWrite[d1 & 0x3F] = true;
}
else
nextline << " $" << HEX2 << (int)d1;
else if (labfound == 5)
myReserved.ZPRAM[(d1 & 0xFF) - 0x80] = true;
nextline << " ";
LABEL_A12_LOW((int)d1);
nextlinebytes << HEX2 << (int)d1;
}
break;
@ -600,24 +596,29 @@ void DiStella::disasm(uInt32 distart, int pass)
if (labfound == 1)
{
USER_OR_AUTO_LABEL("", ad, ",X");
LABEL_A12_HIGH(ad);
nextline << ",X";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
else if (labfound == 3)
else if (labfound == 4)
{
nextline << CartDebug::ourIOMnemonic[ad-0x280] << ",X";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
myReserved.IOReadWrite[ad-0x280] = true;
}
else if (labfound == 4 && mySettings.rflag)
{
int tmp = (ad & myAppData.end)+myOffset;
USER_OR_AUTO_LABEL("", tmp, ",X");
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
if(mySettings.rflag)
{
int tmp = (ad & myAppData.end)+myOffset;
LABEL_A12_HIGH(tmp);
nextline << ",X";
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
}
else
{
nextline << "$" << HEX4 << ad << ",X";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
}
else
{
nextline << "$" << HEX4 << ad << ",X";
LABEL_A12_LOW(ad);
nextline << ",X";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
}
@ -645,24 +646,29 @@ void DiStella::disasm(uInt32 distart, int pass)
if (labfound == 1)
{
USER_OR_AUTO_LABEL("", ad, ",Y");
LABEL_A12_HIGH(ad);
nextline << ",Y";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
else if (labfound == 3)
else if (labfound == 4)
{
nextline << CartDebug::ourIOMnemonic[ad-0x280] << ",Y";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
myReserved.IOReadWrite[ad-0x280] = true;
}
else if (labfound == 4 && mySettings.rflag)
{
int tmp = (ad & myAppData.end)+myOffset;
USER_OR_AUTO_LABEL("", tmp, ",Y");
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
if(mySettings.rflag)
{
int tmp = (ad & myAppData.end)+myOffset;
LABEL_A12_HIGH(tmp);
nextline << ",Y";
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
}
else
{
nextline << "$" << HEX4 << ad << ",Y";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
}
else
{
nextline << "$" << HEX4 << ad << ",Y";
LABEL_A12_LOW(ad);
nextline << ",Y";
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
}
}
@ -674,7 +680,10 @@ void DiStella::disasm(uInt32 distart, int pass)
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
if (pass == 3)
{
nextline << " ($" << HEX2 << (int)d1 << ",X)";
labfound = mark(d1, 0); // dummy call to get address type
nextline << " (";
LABEL_A12_LOW(d1);
nextline << ",X)";
nextlinebytes << HEX2 << (int)d1;
}
break;
@ -685,7 +694,10 @@ void DiStella::disasm(uInt32 distart, int pass)
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
if (pass == 3)
{
nextline << " ($" << HEX2 << (int)d1 << "),Y";
labfound = mark(d1, 0); // dummy call to get address type
nextline << " (";
LABEL_A12_LOW(d1);
nextline << "),Y";
nextlinebytes << HEX2 << (int)d1;
}
break;
@ -697,21 +709,9 @@ void DiStella::disasm(uInt32 distart, int pass)
labfound = mark(d1, CartDebug::REFERENCED);
if (pass == 3)
{
if (labfound == 2)
{
if(ourLookup[op].rw_mode == READ)
{
nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x3f] << ",X";
myReserved.TIARead[d1&0x3f] = true;
}
else
{
nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x7f] << ",X";
myReserved.TIAWrite[d1&0x7f] = true;
}
}
else
nextline << " $" << HEX2 << (int)d1 << ",X";
nextline << " ";
LABEL_A12_LOW(d1);
nextline << ",X";
}
nextlinebytes << HEX2 << (int)d1;
break;
@ -723,21 +723,9 @@ void DiStella::disasm(uInt32 distart, int pass)
labfound = mark(d1, CartDebug::REFERENCED);
if (pass == 3)
{
if (labfound == 2)
{
if(ourLookup[op].rw_mode == READ)
{
nextline << " " << CartDebug::ourTIAMnemonicR[d1&0x3f] << ",Y";
myReserved.TIARead[d1&0x3f] = true;
}
else
{
nextline << " " << CartDebug::ourTIAMnemonicW[d1&0x7f] << ",Y";
myReserved.TIAWrite[d1&0x7f] = true;
}
}
else
nextline << " $" << HEX2 << (int)d1 << ",Y";
nextline << " ";
LABEL_A12_LOW(d1);
nextline << ",Y";
}
nextlinebytes << HEX2 << (int)d1;
break;
@ -764,7 +752,8 @@ void DiStella::disasm(uInt32 distart, int pass)
{
if (labfound == 1)
{
USER_OR_AUTO_LABEL(" ", ad, "");
nextline << " ";
LABEL_A12_HIGH(ad);
}
else
nextline << " $" << HEX4 << ad;
@ -795,15 +784,17 @@ void DiStella::disasm(uInt32 distart, int pass)
}
if (labfound == 1)
{
USER_OR_AUTO_LABEL("(", ad, ")");
}
else if (labfound == 3)
{
nextline << "(" << CartDebug::ourIOMnemonic[ad-0x280] << ")";
myReserved.IOReadWrite[ad-0x280] = true;
nextline << "(";
LABEL_A12_HIGH(ad);
nextline << ")";
}
// TODO - should we consider case 4??
else
nextline << "($" << HEX4 << ad << ")";
{
nextline << "(";
LABEL_A12_LOW(ad);
nextline << ")";
}
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
break;
@ -874,8 +865,8 @@ int DiStella::mark(uInt32 address, uInt8 mask, bool directive)
A quick example breakdown for a 2600 4K cart:
===========================================================
$00-$3d = system equates (WSYNC, etc...); mark the array's element
with the appropriate bit; return 2.
$00-$3d = system equates (WSYNC, etc...); return 2.
$80-$ff = zero-page RAM (ram_80, etc...); return 5.
$0280-$0297 = system equates (INPT0, etc...); mark the array's element
with the appropriate bit; return 3.
$1000-$1FFF = mark the code/data array for the mirrored address
@ -900,14 +891,19 @@ int DiStella::mark(uInt32 address, uInt8 mask, bool directive)
// Check for equates before ROM/ZP-RAM accesses, because the original logic
// of Distella assumed either equates or ROM; it didn't take ZP-RAM into account
if (address <= 0x3f)
CartDebug::AddrType type = myDbg.addressType(address);
if (type == CartDebug::ADDR_TIA)
{
return 2;
}
else if (address >= 0x280 && address <= 0x297)
else if (type == CartDebug::ADDR_IO)
{
return 3;
}
else if (type == CartDebug::ADDR_ZPRAM)
{
return 5;
}
else if (address >= myOffset && address <= myAppData.end + myOffset)
{
myLabels[address-myOffset] = myLabels[address-myOffset] | mask;

View File

@ -90,6 +90,28 @@ class DiStella
int mark(uInt32 address, uInt8 mask, bool directive = false);
bool check_bit(uInt16 address, uInt8 mask) const;
// Convenience methods to generate appropriate labels
inline void labelA12High(stringstream& buf, uInt8 op, uInt16 addr, int labfound)
{
if(!myDbg.getLabel(buf, addr, true))
buf << "L" << HEX4 << addr;
}
inline void labelA12Low(stringstream& buf, uInt8 op, uInt16 addr, int labfound)
{
myDbg.getLabel(buf, addr, ourLookup[op].rw_mode == READ, 2);
if (labfound == 2)
{
if(ourLookup[op].rw_mode == READ)
myReserved.TIARead[addr & 0x0F] = true;
else
myReserved.TIAWrite[addr & 0x3F] = true;
}
else if (labfound == 3)
myReserved.IOReadWrite[(addr & 0xFF) - 0x80] = true;
else if (labfound == 5)
myReserved.ZPRAM[(addr & 0xFF) - 0x80] = true;
}
private:
const CartDebug& myDbg;
CartDebug::DisassemblyList& myList;

View File

@ -76,8 +76,8 @@ RomListWidget::RomListWidget(GuiObject* boss, const GUI::Font& font,
const int fontWidth = font.getMaxCharWidth(),
numchars = w / fontWidth;
_labelWidth = BSPF_max(16, int(0.35 * (numchars - 12))) * fontWidth - 1;
_bytesWidth = 10 * fontWidth;
_labelWidth = BSPF_max(16, int(0.20 * (numchars - 12))) * fontWidth - 1;
_bytesWidth = 12 * fontWidth;
//////////////////////////////////////////////////////
// Add checkboxes