Rearranged disassembly file output header to be output after an

initial pass of the disassembler.  This was required in certain cases,
notably when issuing 'savedis' when the code was currently running from
zero-page.

Fixed missed labels for zero-page RAM when running ZP code.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2740 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2013-05-20 21:53:25 +00:00
parent e6dd326435
commit e053ed4e0e
4 changed files with 122 additions and 101 deletions

View File

@ -30,7 +30,8 @@
- 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).
of INPT4 for address $3C). Special thanks to Omegamatrix for
sample code and idea for this feature.
- 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

@ -93,6 +93,7 @@ CartDebug::CartDebug(Debugger& dbg, Console& console, const OSystem& osystem)
}
myReserved.Label.clear();
myDisassembly.list.reserve(2048);
// Add settings for Distella
DiStella::settings.gfx_format =
@ -309,8 +310,7 @@ bool CartDebug::disassemble(const string& resolvedata, bool force)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CartDebug::fillDisassemblyList(BankInfo& info, bool resolvedata, uInt16 search)
{
myDisassembly.list.clear();
myDisassembly.list.reserve(2048);
myDisassembly.list.clear(false);
myDisassembly.fieldwidth = 14 + myLabelLength;
DiStella distella(*this, myDisassembly.list, info, DiStella::settings,
myDisLabels, myDisDirectives, myReserved, resolvedata);
@ -910,78 +910,37 @@ string CartDebug::saveConfigFile()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::saveDisassembly()
{
#define ALIGN(x) setfill(' ') << left << setw(x)
if(myConsole.cartridge().bankCount() > 1)
return DebuggerParser::red("multi-bank ROM not yet supported");
// Output stream for disassembly
ostringstream buf;
// Currently, the default naming/location for disassembly files is:
// 1) ROM dir based on properties entry name
if(myDisasmFile == "")
{
const string& propsname =
myConsole.properties().get(Cartridge_Name) + ".asm";
FilesystemNode case0(FilesystemNode(myOSystem.romFile()).getParent().getPath() +
propsname);
if(case0.getParent().isWritable())
myDisasmFile = case0.getPath();
else
return DebuggerParser::red("disassembly file not writable:\n " + case0.getShortPath());
}
FilesystemNode node(myDisasmFile);
ofstream out(node.getPath().c_str());
if(!out.is_open())
return "Unable to save disassembly to " + node.getShortPath();
#define ALIGN(x) setfill(' ') << left << setw(x)
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"
<< "; 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"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; TIA AND IO CONSTANTS\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
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 <= 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])
buf << ALIGN(6) << ourIOMnemonic[addr] << " = $"
<< HEX4 << right << (addr+0x280) << "\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";
}
}
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";
}
// We can't print the header to the disassembly until it's actually
// been processed; therefore buffer output to a string first
ostringstream buf;
buf << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n;\n"
<< "; MAIN PROGRAM\n"
<< ";\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
@ -1066,9 +1025,77 @@ string CartDebug::saveDisassembly()
}
}
cout << buf.str() << endl; // TODO - redirect to file
// Some boilerplate, similar to what DiStella adds
time_t currtime;
time(&currtime);
out << "; Disassembly of " << myOSystem.romFile() << "\n"
<< "; Disassembled " << ctime(&currtime)
<< "; Using Stella " << STELLA_VERSION << "\n;\n"
<< "; ROM properties name : " << myConsole.properties().get(Cartridge_Name) << "\n"
<< "; ROM properties MD5 : " << myConsole.properties().get(Cartridge_MD5) << "\n"
<< "; Bankswitch type : " << myConsole.cartridge().about() << "\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";
return DebuggerParser::red("not save to file yet");
out << ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; TIA AND IO CONSTANTS\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
for(uInt16 addr = 0x00; addr <= 0x0F; ++addr)
if(myReserved.TIARead[addr] && ourTIAMnemonicR[addr])
out << ALIGN(6) << ourTIAMnemonicR[addr] << " = $"
<< HEX2 << right << addr << " ; (R)\n";
for(uInt16 addr = 0x00; addr <= 0x3F; ++addr)
if(myReserved.TIAWrite[addr] && ourTIAMnemonicW[addr])
out << ALIGN(6) << ourTIAMnemonicW[addr] << " = $"
<< HEX2 << right << addr << " ; (W)\n";
for(uInt16 addr = 0x00; addr <= 0x17; ++addr)
if(myReserved.IOReadWrite[addr] && ourIOMnemonic[addr])
out << ALIGN(6) << ourIOMnemonic[addr] << " = $"
<< HEX4 << right << (addr+0x280) << "\n";
out << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; RIOT RAM (zero-page)\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
for(uInt16 addr = 0x80; addr <= 0xFF; ++addr)
{
if(myReserved.ZPRAM[addr-0x80] &&
myUserLabels.find(addr) == myUserLabels.end())
{
out << ALIGN(6) << ourZPMnemonic[addr-0x80] << " = $"
<< HEX2 << right << (addr) << "\n";
}
}
if(myReserved.Label.size() > 0)
{
out << "\n;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"
<< "; NON LOCATABLE\n"
<< ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n";
for(iter = myReserved.Label.begin(); iter != myReserved.Label.end(); ++iter)
out << ALIGN(10) << iter->second << " = $" << iter->first << "\n";
}
if(myUserLabels.size() > 0)
{
out << "\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)
out << ALIGN(max_len) << iter->second << " = $" << iter->first << "\n";
}
// And finally, output the disassembly
out << buf.str();
out.close();
return "saved " + node.getShortPath() + " OK";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1187,23 +1214,11 @@ CartDebug::AddrType CartDebug::addressType(uInt16 addr) const
{
switch(addr & 0x0f00)
{
case 0x000:
case 0x100:
case 0x400:
case 0x500:
case 0x800:
case 0x900:
case 0xc00:
case 0xd00:
case 0x000: case 0x100: case 0x400: case 0x500:
case 0x800: case 0x900: case 0xc00: case 0xd00:
return ADDR_ZPRAM;
case 0x200:
case 0x300:
case 0x600:
case 0x700:
case 0xa00:
case 0xb00:
case 0xe00:
case 0xf00:
case 0x200: case 0x300: case 0x600: case 0x700:
case 0xa00: case 0xb00: case 0xe00: case 0xf00:
return ADDR_IO;
}
}
@ -1284,7 +1299,6 @@ CartDebug::DisasmType CartDebug::disasmTypeAbsolute(uInt8 flags) const
return CartDebug::NONE;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartDebug::disasmTypeAsString(ostream& buf, DisasmType type) const
{

View File

@ -299,6 +299,17 @@ class CartDebug : public DebuggerSystem
DirectiveList directiveList; // overrides for automatic code determination
BankInfo() : start(0), end(0), offset(0), size(0) { }
friend ostream& operator<<(ostream& os, const BankInfo& b)
{
os << "start=$" << HEX4 << b.start << ", end=$" << HEX4 << b.end
<< ", offset=$" << HEX4 << b.offset << ", size=" << dec << b.size
<< endl
<< "addrlist: ";
AddressList::const_iterator i;
for(i = b.addressList.begin(); i != b.addressList.end(); ++i)
os << HEX4 << *i << " ";
return os;
}
};
// Address type information determined by Distella

View File

@ -203,9 +203,14 @@ DiStella::DiStella(const CartDebug& dbg, CartDebug::DisassemblyList& list,
// If we have a piece of code referenced somewhere else, but cannot
// locate the label in code (i.e because the address is inside of a
// multi-byte instruction, then we make note of that address for reference
reservedLabel.str("");
reservedLabel << "L" << HEX4 << (k+myOffset);
myReserved.Label.insert(make_pair(k+myOffset, reservedLabel.str()));
//
// However, we only do this for labels pointing to ROM (above $1000)
if(myDbg.addressType(k+myOffset) == CartDebug::ADDR_ROM)
{
reservedLabel.str("");
reservedLabel << "L" << HEX4 << (k+myOffset);
myReserved.Label.insert(make_pair(k+myOffset, reservedLabel.str()));
}
}
}
@ -547,16 +552,6 @@ void DiStella::disasm(uInt32 distart, int pass)
labfound = mark(d1, CartDebug::REFERENCED);
if (pass == 3)
{
if (labfound == 2)
{
if(ourLookup[op].rw_mode == READ)
myReserved.TIARead[d1 & 0x0F] = true;
else
myReserved.TIAWrite[d1 & 0x3F] = true;
}
else if (labfound == 5)
myReserved.ZPRAM[(d1 & 0xFF) - 0x80] = true;
nextline << " ";
LABEL_A12_LOW((int)d1);
nextlinebytes << HEX2 << (int)d1;