Checking in WIP for DiStella integration. The disassembly is now shown in

the RomListWidget instead of being printed to the terminal.  There are still
graphical glitches with this, but for a first pass, it's nice to see actual
Distella output in Stella.

Partially working 'disasm' command from the PromptWidget.  Currently, it
only disassembles cart address space (aka, 0x1000 or above).

Removed the old disassembly code from CartDebug.  Still TODO is fix the
label stuff, both in getting DiStella to use it, and adding/removing
labels.  This is greatly reduced now that we only have to worry about
user labels.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1934 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-02-07 21:23:26 +00:00
parent 03191759ab
commit 8ca34a4d90
8 changed files with 183 additions and 735 deletions

View File

@ -169,177 +169,74 @@ string CartDebug::toString()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& CartDebug::disassemble(int start, int lines) bool CartDebug::disassemble(bool autocode)
{ {
static string result= ""; bool changed = false;
ostringstream buffer;
string cpubuf;
if(start < 0x80 || start > 0xffff) // Test current disassembly; don't re-disassemble if it hasn't changed
return result; // ...
changed = true; // FIXME
do { if(changed)
buffer << getLabel(start, true, 4) << ": ";
int count = disassemble(start, cpubuf);
for(int i = 0; i < count; i++)
buffer << hex << setw(2) << setfill('0') << myDebugger.peek(start++) << " " << dec;
if(count < 3) buffer << " ";
if(count < 2) buffer << " ";
buffer << " " << cpubuf << "\n";
} while(--lines > 0 && start <= 0xffff);
result = buffer.str();
return result;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartDebug::disassemble(IntArray& addr, StringList& addrLabel,
StringList& bytes, StringList& data,
int start, int end)
{
if(start < 0x80 || end > 0xffff)
return;
string cpubuf, tmp;
char buf[255];
do {
addr.push_back(start);
addrLabel.push_back(getLabel(start, true, 4) + ":");
cpubuf = "";
int count = disassemble(start, cpubuf);
tmp = "";
for(int i = 0; i < count; i++)
{
sprintf(buf, "%02x ", myDebugger.peek(start++));
tmp += buf;
}
bytes.push_back(tmp);
data.push_back(cpubuf);
}
while(start <= end);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CartDebug::disassemble(DisassemblyList& list, uInt16 start, bool autocode)
{
DiStella distella;
distella.disassemble(list, start, autocode);
// TODO - look at list, extract address to label mappings
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CartDebug::disassemble(int address, string& result)
{
ostringstream buf;
int count = 0;
int opcode = mySystem.peek(address);
// Are we looking at a read or write operation?
// It will determine what type of label to use
bool isRead = (CartDebug::AccessModeTable[opcode] == CartDebug::Read);
switch(CartDebug::AddressModeTable[opcode])
{ {
case CartDebug::Absolute: myDisassembly.clear();
buf << CartDebug::InstructionMnemonicTable[opcode] << " " myAddrToLineList.clear();
<< getLabel(myDebugger.dpeek(address + 1), isRead, 4) << " ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 3;
break;
case CartDebug::AbsoluteX: // TODO - add logic to determine correct start address to use
buf << CartDebug::InstructionMnemonicTable[opcode] << " " // it will depend on the current bank and PC
<< getLabel(myDebugger.dpeek(address + 1), isRead, 4) << ",x ; " uInt16 start = myDebugger.dpeek(0xfffc);
<< M6502::ourInstructionCycleTable[opcode];
count = 3;
break;
case CartDebug::AbsoluteY: DiStella distella(myDisassembly, start, autocode);
buf << CartDebug::InstructionMnemonicTable[opcode] << " "
<< getLabel(myDebugger.dpeek(address + 1), isRead, 4) << ",y ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 3;
break;
case CartDebug::Immediate: // Parts of the disassembly will be accessed later in different ways
buf << CartDebug::InstructionMnemonicTable[opcode] << " #$" // We place those parts in separate maps, to speed up access
<< hex << setw(2) << setfill('0') << (int) mySystem.peek(address + 1) << " ; " for(uInt32 i = 0; i < myDisassembly.size(); ++i)
<< dec << M6502::ourInstructionCycleTable[opcode]; {
count = 2; const DisassemblyTag& tag = myDisassembly[i];
break;
case CartDebug::Implied: // Create a mapping from addresses to line numbers
buf << CartDebug::InstructionMnemonicTable[opcode] << " ; " if(tag.address != 0)
<< M6502::ourInstructionCycleTable[opcode]; myAddrToLineList.insert(make_pair(tag.address, i));
count = 1;
break;
case CartDebug::Indirect: // TODO - look at list, extract address to label mappings
buf << CartDebug::InstructionMnemonicTable[opcode] << " (" // we need these for label support in the UI and promptwidget
<< getLabel(myDebugger.dpeek(address + 1), isRead, 4) << ") ; " }
<< M6502::ourInstructionCycleTable[opcode];
count = 3;
break;
case CartDebug::IndirectX:
buf << CartDebug::InstructionMnemonicTable[opcode] << " ("
<< getLabel(mySystem.peek(address + 1), isRead, 2) << ",x) ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 2;
break;
case CartDebug::IndirectY:
buf << CartDebug::InstructionMnemonicTable[opcode] << " ("
<< getLabel(mySystem.peek(address + 1), isRead, 2) << "),y ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 2;
break;
case CartDebug::Relative:
buf << CartDebug::InstructionMnemonicTable[opcode] << " "
<< getLabel(address + 2 + ((Int16)(Int8)mySystem.peek(address + 1)), isRead, 4)
<< " ; " << M6502::ourInstructionCycleTable[opcode];
count = 2;
break;
case CartDebug::Zero:
buf << CartDebug::InstructionMnemonicTable[opcode] << " "
<< getLabel(mySystem.peek(address + 1), isRead, 2) << " ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 2;
break;
case CartDebug::ZeroX:
buf << CartDebug::InstructionMnemonicTable[opcode] << " "
<< getLabel(mySystem.peek(address + 1), isRead, 2) << ",x ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 2;
break;
case CartDebug::ZeroY:
buf << CartDebug::InstructionMnemonicTable[opcode] << " "
<< getLabel(mySystem.peek(address + 1), isRead, 2) << ",y ; "
<< M6502::ourInstructionCycleTable[opcode];
count = 2;
break;
default:
buf << "dc $" << hex << setw(2) << setfill('0') << (int) opcode << " ; "
<< dec << M6502::ourInstructionCycleTable[opcode];
count = 1;
break;
} }
result = buf.str(); return changed;
return count; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CartDebug::addressToLine(uInt16 address) const
{
map<uInt16, int>::const_iterator iter = myAddrToLineList.find(address);
return iter != myAddrToLineList.end() ? iter->second : 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::disassemble(uInt16 start, uInt16 lines) const
{
if(!(start & 0x1000))
return "Disassembly below 0x1000 not yet supported";
DisassemblyList list;
DiStella distella(list, start, false);
// Fill the string with disassembled data
start &= 0xFFF;
ostringstream buffer;
for(uInt32 i = 0; i < list.size() && lines > 0; ++i)
{
const CartDebug::DisassemblyTag& tag = list[i];
if((tag.address & 0xfff) >= start)
{
buffer << uppercase << hex << setw(4) << setfill('0') << tag.address
<< ": " << tag.disasm << " " << tag.bytes << endl;
--lines;
}
}
return buffer.str();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -677,396 +574,3 @@ int CartDebug::extractValue(char *c) const
} }
return ret; return ret;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const CartDebug::Equate CartDebug::ourSystemEquates[kSystemEquateSize] = {
// Standard $00-based TIA write locations:
{ "VSYNC", 0x00, EQF_WRITE },
{ "VBLANK", 0x01, EQF_WRITE },
{ "WSYNC", 0x02, EQF_WRITE },
{ "RSYNC", 0x03, EQF_WRITE },
{ "NUSIZ0", 0x04, EQF_WRITE },
{ "NUSIZ1", 0x05, EQF_WRITE },
{ "COLUP0", 0x06, EQF_WRITE },
{ "COLUP1", 0x07, EQF_WRITE },
{ "COLUPF", 0x08, EQF_WRITE },
{ "COLUBK", 0x09, EQF_WRITE },
{ "CTRLPF", 0x0A, EQF_WRITE },
{ "REFP0", 0x0B, EQF_WRITE },
{ "REFP1", 0x0C, EQF_WRITE },
{ "PF0", 0x0D, EQF_WRITE },
{ "PF1", 0x0E, EQF_WRITE },
{ "PF2", 0x0F, EQF_WRITE },
{ "RESP0", 0x10, EQF_WRITE },
{ "RESP1", 0x11, EQF_WRITE },
{ "RESM0", 0x12, EQF_WRITE },
{ "RESM1", 0x13, EQF_WRITE },
{ "RESBL", 0x14, EQF_WRITE },
{ "AUDC0", 0x15, EQF_WRITE },
{ "AUDC1", 0x16, EQF_WRITE },
{ "AUDF0", 0x17, EQF_WRITE },
{ "AUDF1", 0x18, EQF_WRITE },
{ "AUDV0", 0x19, EQF_WRITE },
{ "AUDV1", 0x1A, EQF_WRITE },
{ "GRP0", 0x1B, EQF_WRITE },
{ "GRP1", 0x1C, EQF_WRITE },
{ "ENAM0", 0x1D, EQF_WRITE },
{ "ENAM1", 0x1E, EQF_WRITE },
{ "ENABL", 0x1F, EQF_WRITE },
{ "HMP0", 0x20, EQF_WRITE },
{ "HMP1", 0x21, EQF_WRITE },
{ "HMM0", 0x22, EQF_WRITE },
{ "HMM1", 0x23, EQF_WRITE },
{ "HMBL", 0x24, EQF_WRITE },
{ "VDELP0", 0x25, EQF_WRITE },
{ "VDEL01", 0x26, EQF_WRITE },
{ "VDELP1", 0x26, EQF_WRITE },
{ "VDELBL", 0x27, EQF_WRITE },
{ "RESMP0", 0x28, EQF_WRITE },
{ "RESMP1", 0x29, EQF_WRITE },
{ "HMOVE", 0x2A, EQF_WRITE },
{ "HMCLR", 0x2B, EQF_WRITE },
{ "CXCLR", 0x2C, EQF_WRITE },
// Mirrored $40-based TIA write locations:
{ "VSYNC.40", 0x40, EQF_WRITE },
{ "VBLANK.40", 0x41, EQF_WRITE },
{ "WSYNC.40", 0x42, EQF_WRITE },
{ "RSYNC.40", 0x43, EQF_WRITE },
{ "NUSIZ0.40", 0x44, EQF_WRITE },
{ "NUSIZ1.40", 0x45, EQF_WRITE },
{ "COLUP0.40", 0x46, EQF_WRITE },
{ "COLUP1.40", 0x47, EQF_WRITE },
{ "COLUPF.40", 0x48, EQF_WRITE },
{ "COLUBK.40", 0x49, EQF_WRITE },
{ "CTRLPF.40", 0x4A, EQF_WRITE },
{ "REFP0.40", 0x4B, EQF_WRITE },
{ "REFP1.40", 0x4C, EQF_WRITE },
{ "PF0.40", 0x4D, EQF_WRITE },
{ "PF1.40", 0x4E, EQF_WRITE },
{ "PF2.40", 0x4F, EQF_WRITE },
{ "RESP0.40", 0x50, EQF_WRITE },
{ "RESP1.40", 0x51, EQF_WRITE },
{ "RESM0.40", 0x52, EQF_WRITE },
{ "RESM1.40", 0x53, EQF_WRITE },
{ "RESBL.40", 0x54, EQF_WRITE },
{ "AUDC0.40", 0x55, EQF_WRITE },
{ "AUDC1.40", 0x56, EQF_WRITE },
{ "AUDF0.40", 0x57, EQF_WRITE },
{ "AUDF1.40", 0x58, EQF_WRITE },
{ "AUDV0.40", 0x59, EQF_WRITE },
{ "AUDV1.40", 0x5A, EQF_WRITE },
{ "GRP0.40", 0x5B, EQF_WRITE },
{ "GRP1.40", 0x5C, EQF_WRITE },
{ "ENAM0.40", 0x5D, EQF_WRITE },
{ "ENAM1.40", 0x5E, EQF_WRITE },
{ "ENABL.40", 0x5F, EQF_WRITE },
{ "HMP0.40", 0x60, EQF_WRITE },
{ "HMP1.40", 0x61, EQF_WRITE },
{ "HMM0.40", 0x62, EQF_WRITE },
{ "HMM1.40", 0x63, EQF_WRITE },
{ "HMBL.40", 0x64, EQF_WRITE },
{ "VDELP0.40", 0x65, EQF_WRITE },
{ "VDEL01.40", 0x66, EQF_WRITE },
{ "VDELP1.40", 0x66, EQF_WRITE },
{ "VDELBL.40", 0x67, EQF_WRITE },
{ "RESMP0.40", 0x68, EQF_WRITE },
{ "RESMP1.40", 0x69, EQF_WRITE },
{ "HMOVE.40", 0x6A, EQF_WRITE },
{ "HMCLR.40", 0x6B, EQF_WRITE },
{ "CXCLR.40", 0x6C, EQF_WRITE },
// Standard $00-based TIA read locations:
{ "CXM0P", 0x00, EQF_READ },
{ "CXM1P", 0x01, EQF_READ },
{ "CXP0FB", 0x02, EQF_READ },
{ "CXP1FB", 0x03, EQF_READ },
{ "CXM0FB", 0x04, EQF_READ },
{ "CXM1FB", 0x05, EQF_READ },
{ "CXBLPF", 0x06, EQF_READ },
{ "CXPPMM", 0x07, EQF_READ },
{ "INPT0", 0x08, EQF_READ },
{ "INPT1", 0x09, EQF_READ },
{ "INPT2", 0x0A, EQF_READ },
{ "INPT3", 0x0B, EQF_READ },
{ "INPT4", 0x0C, EQF_READ },
{ "INPT5", 0x0D, EQF_READ },
// Mirrored $10-based TIA read locations:
{ "CXM0P.10", 0x10, EQF_READ },
{ "CXM1P.10", 0x11, EQF_READ },
{ "CXP0FB.10", 0x12, EQF_READ },
{ "CXP1FB.10", 0x13, EQF_READ },
{ "CXM0FB.10", 0x14, EQF_READ },
{ "CXM1FB.10", 0x15, EQF_READ },
{ "CXBLPF.10", 0x16, EQF_READ },
{ "CXPPMM.10", 0x17, EQF_READ },
{ "INPT0.10", 0x18, EQF_READ },
{ "INPT1.10", 0x19, EQF_READ },
{ "INPT2.10", 0x1A, EQF_READ },
{ "INPT3.10", 0x1B, EQF_READ },
{ "INPT4.10", 0x1C, EQF_READ },
{ "INPT5.10", 0x1D, EQF_READ },
// Mirrored $20-based TIA read locations:
{ "CXM0P.20", 0x20, EQF_READ },
{ "CXM1P.20", 0x21, EQF_READ },
{ "CXP0FB.20", 0x22, EQF_READ },
{ "CXP1FB.20", 0x23, EQF_READ },
{ "CXM0FB.20", 0x24, EQF_READ },
{ "CXM1FB.20", 0x25, EQF_READ },
{ "CXBLPF.20", 0x26, EQF_READ },
{ "CXPPMM.20", 0x27, EQF_READ },
{ "INPT0.20", 0x28, EQF_READ },
{ "INPT1.20", 0x29, EQF_READ },
{ "INPT2.20", 0x2A, EQF_READ },
{ "INPT3.20", 0x2B, EQF_READ },
{ "INPT4.20", 0x2C, EQF_READ },
{ "INPT5.20", 0x2D, EQF_READ },
// Mirrored $30-based TIA read locations:
{ "CXM0P.30", 0x30, EQF_READ },
{ "CXM1P.30", 0x31, EQF_READ },
{ "CXP0FB.30", 0x32, EQF_READ },
{ "CXP1FB.30", 0x33, EQF_READ },
{ "CXM0FB.30", 0x34, EQF_READ },
{ "CXM1FB.30", 0x35, EQF_READ },
{ "CXBLPF.30", 0x36, EQF_READ },
{ "CXPPMM.30", 0x37, EQF_READ },
{ "INPT0.30", 0x38, EQF_READ },
{ "INPT1.30", 0x39, EQF_READ },
{ "INPT2.30", 0x3A, EQF_READ },
{ "INPT3.30", 0x3B, EQF_READ },
{ "INPT4.30", 0x3C, EQF_READ },
{ "INPT5.30", 0x3D, EQF_READ },
// Standard RIOT locations (read, write, or both):
{ "SWCHA", 0x280, EQF_RW },
{ "SWCHB", 0x282, EQF_RW },
{ "SWACNT", 0x281, EQF_WRITE },
{ "SWBCNT", 0x283, EQF_WRITE },
{ "INTIM", 0x284, EQF_READ },
{ "TIMINT", 0x285, EQF_READ },
{ "TIM1T", 0x294, EQF_WRITE },
{ "TIM8T", 0x295, EQF_WRITE },
{ "TIM64T", 0x296, EQF_WRITE },
{ "T1024T", 0x297, EQF_WRITE }
};
///////////////////////////////////////////////////////////////////
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartDebug::AddressingMode CartDebug::AddressModeTable[256] = {
Implied, IndirectX, Invalid, IndirectX, // 0x0?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x1?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Absolute, IndirectX, Invalid, IndirectX, // 0x2?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x3?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Implied, IndirectX, Invalid, IndirectX, // 0x4?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x5?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Implied, IndirectX, Invalid, IndirectX, // 0x6?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Indirect, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x7?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Immediate, IndirectX, Immediate, IndirectX, // 0x8?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0x9?
ZeroX, ZeroX, ZeroY, ZeroY,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY,
Immediate, IndirectX, Immediate, IndirectX, // 0xA?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0xB?
ZeroX, ZeroX, ZeroY, ZeroY,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteY, AbsoluteY,
Immediate, IndirectX, Immediate, IndirectX, // 0xC?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0xD?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX,
Immediate, IndirectX, Immediate, IndirectX, // 0xE?
Zero, Zero, Zero, Zero,
Implied, Immediate, Implied, Immediate,
Absolute, Absolute, Absolute, Absolute,
Relative, IndirectY, Invalid, IndirectY, // 0xF?
ZeroX, ZeroX, ZeroX, ZeroX,
Implied, AbsoluteY, Implied, AbsoluteY,
AbsoluteX, AbsoluteX, AbsoluteX, AbsoluteX
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CartDebug::AccessMode CartDebug::AccessModeTable[256] = {
None, Read, None, Write, // 0x0?
None, Read, Write, Write,
None, Read, Write, Read,
None, Read, Write, Write,
Read, Read, None, Write, // 0x1?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
Read, Read, None, Write, // 0x2?
Read, Read, Write, Write,
None, Read, Write, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0x3?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
None, Read, None, Write, // 0x4?
None, Read, Write, Write,
None, Read, Write, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0x5?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
None, Read, None, Write, // 0x6?
None, Read, Write, Write,
None, Read, Write, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0x7?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
None, Write, None, Write, // 0x8?
Write, Write, Write, Write,
None, None, None, Read,
Write, Write, Write, Write,
Read, Write, None, Write, // 0x9?
Write, Write, Write, Write,
None, Write, None, Write,
Write, Write, Write, Write,
Read, Read, Read, Read, // 0xA?
Read, Read, Read, Read,
None, Read, None, Read,
Read, Read, Read, Read,
Read, Read, None, Read, // 0xB?
Read, Read, Read, Read,
None, Read, None, Read,
Read, Read, Read, Read,
Read, Read, None, Write, // 0xC?
Read, Read, Write, Write,
None, Read, None, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0xD?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write,
Read, Read, None, Write, // 0xE?
Read, Read, Write, Write,
None, Read, None, Read,
Read, Read, Write, Write,
Read, Read, None, Write, // 0xF?
None, Read, Write, Write,
None, Read, None, Write,
None, Read, Write, Write
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const char* CartDebug::InstructionMnemonicTable[256] = {
"BRK", "ORA", "n/a", "slo", "nop", "ORA", "ASL", "slo", // 0x0?
"PHP", "ORA", "ASLA", "anc", "nop", "ORA", "ASL", "slo",
"BPL", "ORA", "n/a", "slo", "nop", "ORA", "ASL", "slo", // 0x1?
"CLC", "ORA", "nop", "slo", "nop", "ORA", "ASL", "slo",
"JSR", "AND", "n/a", "rla", "BIT", "AND", "ROL", "rla", // 0x2?
"PLP", "AND", "ROLA", "anc", "BIT", "AND", "ROL", "rla",
"BMI", "AND", "n/a", "rla", "nop", "AND", "ROL", "rla", // 0x3?
"SEC", "AND", "nop", "rla", "nop", "AND", "ROL", "rla",
"RTI", "EOR", "n/a", "sre", "nop", "EOR", "LSR", "sre", // 0x4?
"PHA", "EOR", "LSRA", "asr", "JMP", "EOR", "LSR", "sre",
"BVC", "EOR", "n/a", "sre", "nop", "EOR", "LSR", "sre", // 0x5?
"CLI", "EOR", "nop", "sre", "nop", "EOR", "LSR", "sre",
"RTS", "ADC", "n/a", "rra", "nop", "ADC", "ROR", "rra", // 0x6?
"PLA", "ADC", "RORA", "arr", "JMP", "ADC", "ROR", "rra",
"BVS", "ADC", "n/a", "rra", "nop", "ADC", "ROR", "rra", // 0x7?
"SEI", "ADC", "nop", "rra", "nop", "ADC", "ROR", "rra",
"nop", "STA", "nop", "sax", "STY", "STA", "STX", "sax", // 0x8?
"DEY", "nop", "TXA", "ane", "STY", "STA", "STX", "sax",
"BCC", "STA", "n/a", "sha", "STY", "STA", "STX", "sax", // 0x9?
"TYA", "STA", "TXS", "shs", "shy", "STA", "shx", "sha",
"LDY", "LDA", "LDX", "lax", "LDY", "LDA", "LDX", "lax", // 0xA?
"TAY", "LDA", "TAX", "lxa", "LDY", "LDA", "LDX", "lax",
"BCS", "LDA", "n/a", "lax", "LDY", "LDA", "LDX", "lax", // 0xB?
"CLV", "LDA", "TSX", "las", "LDY", "LDA", "LDX", "lax",
"CPY", "CMP", "nop", "dcp", "CPY", "CMP", "DEC", "dcp", // 0xC?
"INY", "CMP", "DEX", "sbx", "CPY", "CMP", "DEC", "dcp",
"BNE", "CMP", "n/a", "dcp", "nop", "CMP", "DEC", "dcp", // 0xD?
"CLD", "CMP", "nop", "dcp", "nop", "CMP", "DEC", "dcp",
"CPX", "SBC", "nop", "isb", "CPX", "SBC", "INC", "isb", // 0xE?
"INX", "SBC", "NOP", "sbc", "CPX", "SBC", "INC", "isb",
"BEQ", "SBC", "n/a", "isb", "nop", "SBC", "INC", "isb", // 0xF?
"SED", "SBC", "nop", "isb", "nop", "SBC", "INC", "isb"
};

View File

@ -21,6 +21,8 @@
class System; class System;
#include <map>
#include "bspf.hxx" #include "bspf.hxx"
#include "Array.hxx" #include "Array.hxx"
#include "Cart.hxx" #include "Cart.hxx"
@ -83,32 +85,44 @@ class CartDebug : public DebuggerSystem
*/ */
void addRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset); void addRamArea(uInt16 start, uInt16 size, uInt16 roffset, uInt16 woffset);
//////////////////////////////////////// // The following two methods are meant to be used together
/** // First, a call is made to disassemble(), which updates the disassembly
Disassemble from the starting address the specified number of lines // list; it will figure out when an actual complete disassembly is
and place result in a string. // required, and when the previous results can be used
*/ //
const string& disassemble(int start, int lines); // Later, successive calls to disassemblyList() simply return the
// previous results; no disassembly is done in this case
/**
Disassemble from the starting address to the ending address
and place addresses, bytes and data in given arrays.
*/
void disassemble(IntArray& addr, StringList& addrLabel,
StringList& bytes, StringList& data,
int start, int end);
/** /**
Disassemble from the given address using the Distella disassembler Disassemble from the given address using the Distella disassembler
Address-to-label mappings (and vice-versa) are also determined here Address-to-label mappings (and vice-versa) are also determined here
@return True if disassembly changed from previous call, else false
*/ */
void disassemble(DisassemblyList& list, uInt16 start, bool autocode); bool disassemble(bool autocode);
/**
Get the results from the most recent call to disassemble()
*/
const DisassemblyList& disassemblyList() const { return myDisassembly; }
/**
Determine the line in the disassembly that corresponds to the given
address. A value of zero indicates that no such address exists.
*/
int addressToLine(uInt16 address) const;
/**
Disassemble from the starting address the specified number of lines.
Note that automatic code determination is turned off for this method;
it will treat all address contents as instructions.
*/
string disassemble(uInt16 start, uInt16 lines) const;
int getBank(); int getBank();
int bankCount(); int bankCount();
string getCartType(); string getCartType();
////////////////////////////////////////
////////////////////////////////////////
/** /**
Add a label and associated address Add a label and associated address
*/ */
@ -148,9 +162,7 @@ class CartDebug : public DebuggerSystem
int countCompletions(const char *in); int countCompletions(const char *in);
const string& getCompletions() const { return myCompletions; } const string& getCompletions() const { return myCompletions; }
const string& getCompletionPrefix() const { return myCompPrefix; } const string& getCompletionPrefix() const { return myCompPrefix; }
////////////////////////////////////////
private:
int disassemble(int address, string& result);
private: private:
enum equate_t { enum equate_t {
@ -186,6 +198,7 @@ class CartDebug : public DebuggerSystem
CartState myOldState; CartState myOldState;
DisassemblyList myDisassembly; DisassemblyList myDisassembly;
map<uInt16, int> myAddrToLineList;
LabelToAddr mySystemAddresses; LabelToAddr mySystemAddresses;
AddrToLabel mySystemReadLabels; // labels used in a read context AddrToLabel mySystemReadLabels; // labels used in a read context
@ -200,40 +213,6 @@ class CartDebug : public DebuggerSystem
string myCompPrefix; string myCompPrefix;
uInt16 myRWPortAddress; uInt16 myRWPortAddress;
enum { kSystemEquateSize = 158 };
static const Equate ourSystemEquates[kSystemEquateSize];
//////////////////////////////////////////////
/**
Enumeration of the 6502 addressing modes
*/
enum AddressingMode
{
Absolute, AbsoluteX, AbsoluteY, Immediate, Implied,
Indirect, IndirectX, IndirectY, Invalid, Relative,
Zero, ZeroX, ZeroY
};
/**
Enumeration of the 6502 access modes
*/
enum AccessMode
{
Read, Write, None
};
/// Addressing mode for each of the 256 opcodes
/// This specifies how the opcode argument is addressed
static AddressingMode AddressModeTable[256];
/// Access mode for each of the 256 opcodes
/// This specifies how the opcode will access its argument
static AccessMode AccessModeTable[256];
/// Table of instruction mnemonics
static const char* InstructionMnemonicTable[256];
//////////////////////////////////////////////
}; };
#endif #endif

View File

@ -25,19 +25,9 @@
#include "DiStella.hxx" #include "DiStella.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DiStella::DiStella() DiStella::DiStella(CartDebug::DisassemblyList& list, uInt16 start,
bool autocode)
: labels(NULL) /* array of information about addresses-- can be from 2K-48K bytes in size */ : labels(NULL) /* array of information about addresses-- can be from 2K-48K bytes in size */
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DiStella::~DiStella()
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 DiStella::disassemble(CartDebug::DisassemblyList& list, uInt16 start,
bool autocode)
{ {
while(!myAddressQueue.empty()) while(!myAddressQueue.empty())
myAddressQueue.pop(); myAddressQueue.pop();
@ -52,7 +42,7 @@ uInt32 DiStella::disassemble(CartDebug::DisassemblyList& list, uInt16 start,
if (labels == NULL) if (labels == NULL)
{ {
fprintf (stderr, "Malloc failed for 'labels' variable\n"); fprintf (stderr, "Malloc failed for 'labels' variable\n");
return 0; return;
} }
memset(labels,0,myAppData.length); memset(labels,0,myAppData.length);
@ -103,8 +93,11 @@ uInt32 DiStella::disassemble(CartDebug::DisassemblyList& list, uInt16 start,
disasm(list, myOffset, 3); disasm(list, myOffset, 3);
free(labels); /* Free dynamic memory before program ends */ free(labels); /* Free dynamic memory before program ends */
}
return list.size(); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DiStella::~DiStella()
{
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -139,8 +132,8 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
else else
myBuf << HEX4 << myPC+myOffset << "' '"; myBuf << HEX4 << myPC+myOffset << "' '";
myBuf << ".byte $" << HEX2 << (int)Debugger::debugger().peek(myPC|0x1000) << " ; "; myBuf << ".byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset) << " ; ";
showgfx(Debugger::debugger().peek(myPC|0x1000)); showgfx(Debugger::debugger().peek(myPC+myOffset));
myBuf << " $" << HEX4 << myPC+myOffset; myBuf << " $" << HEX4 << myPC+myOffset;
addEntry(list); addEntry(list);
} }
@ -154,7 +147,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
{ {
bytes = 1; bytes = 1;
myBuf << HEX4 << myPC+myOffset << "'L" << myPC+myOffset << "'.byte " myBuf << HEX4 << myPC+myOffset << "'L" << myPC+myOffset << "'.byte "
<< "$" << HEX2 << (int)Debugger::debugger().peek(myPC|0x1000); << "$" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
} }
myPC++; myPC++;
@ -167,11 +160,11 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
if (bytes == 17) if (bytes == 17)
{ {
addEntry(list); addEntry(list);
myBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC|0x1000); myBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
bytes = 1; bytes = 1;
} }
else else
myBuf << ",$" << HEX2 << (int)Debugger::debugger().peek(myPC|0x1000); myBuf << ",$" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
} }
myPC++; myPC++;
} }
@ -185,7 +178,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
} }
else else
{ {
op = Debugger::debugger().peek(myPC|0x1000); op = Debugger::debugger().peek(myPC+myOffset);
/* version 2.1 bug fix */ /* version 2.1 bug fix */
if (pass == 2) if (pass == 2)
mark(myPC+myOffset, VALID_ENTRY); mark(myPC+myOffset, VALID_ENTRY);
@ -254,7 +247,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
else else
myBuf << HEX4 << myPC+myOffset << "' '"; myBuf << HEX4 << myPC+myOffset << "' '";
op = Debugger::debugger().peek(myPC|0x1000); myPC++; op = Debugger::debugger().peek(myPC+myOffset); myPC++;
myBuf << ".byte $" << HEX2 << (int)op; myBuf << ".byte $" << HEX2 << (int)op;
addEntry(list); addEntry(list);
} }
@ -321,7 +314,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ABSOLUTE: case ABSOLUTE:
{ {
ad = Debugger::debugger().dpeek(myPC|0x1000); myPC+=2; ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, REFERENCED); labfound = mark(ad, REFERENCED);
if (pass == 1) if (pass == 1)
{ {
@ -380,7 +373,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ZERO_PAGE: case ZERO_PAGE:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
labfound = mark(d1, REFERENCED); labfound = mark(d1, REFERENCED);
if (pass == 3) if (pass == 3)
{ {
@ -402,7 +395,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case IMMEDIATE: case IMMEDIATE:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
if (pass == 3) if (pass == 3)
{ {
sprintf(linebuff," #$%.2X ",d1); sprintf(linebuff," #$%.2X ",d1);
@ -415,7 +408,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ABSOLUTE_X: case ABSOLUTE_X:
{ {
ad = Debugger::debugger().dpeek(myPC|0x1000); myPC+=2; ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, REFERENCED); labfound = mark(ad, REFERENCED);
if (pass == 3) if (pass == 3)
{ {
@ -465,7 +458,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ABSOLUTE_Y: case ABSOLUTE_Y:
{ {
ad = Debugger::debugger().dpeek(myPC|0x1000); myPC+=2; ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, REFERENCED); labfound = mark(ad, REFERENCED);
if (pass == 3) if (pass == 3)
{ {
@ -514,7 +507,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case INDIRECT_X: case INDIRECT_X:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
if (pass == 3) if (pass == 3)
{ {
sprintf(linebuff," ($%.2X,X)",d1); sprintf(linebuff," ($%.2X,X)",d1);
@ -527,7 +520,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case INDIRECT_Y: case INDIRECT_Y:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
if (pass == 3) if (pass == 3)
{ {
sprintf(linebuff," ($%.2X),Y",d1); sprintf(linebuff," ($%.2X),Y",d1);
@ -540,7 +533,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ZERO_PAGE_X: case ZERO_PAGE_X:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
labfound = mark(d1, REFERENCED); labfound = mark(d1, REFERENCED);
if (pass == 3) if (pass == 3)
{ {
@ -562,7 +555,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ZERO_PAGE_Y: case ZERO_PAGE_Y:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
labfound = mark(d1,REFERENCED); labfound = mark(d1,REFERENCED);
if (pass == 3) if (pass == 3)
{ {
@ -584,7 +577,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case RELATIVE: case RELATIVE:
{ {
d1 = Debugger::debugger().peek(myPC|0x1000); myPC++; d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
ad = d1; ad = d1;
if (d1 >= 128) if (d1 >= 128)
ad = d1 - 256; ad = d1 - 256;
@ -620,7 +613,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
case ABS_INDIRECT: case ABS_INDIRECT:
{ {
ad = Debugger::debugger().dpeek(myPC|0x1000); myPC+=2; ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
labfound = mark(ad, REFERENCED); labfound = mark(ad, REFERENCED);
if (pass == 3) if (pass == 3)
{ {

View File

@ -41,10 +41,6 @@
*/ */
class DiStella class DiStella
{ {
public:
DiStella();
~DiStella();
public: public:
/** /**
Disassemble the current state of the System from the given start address. Disassemble the current state of the System from the given start address.
@ -52,11 +48,11 @@ class DiStella
@param list The results of the disassembly are placed here @param list The results of the disassembly are placed here
@param start The address at which to start disassembly @param start The address at which to start disassembly
@param autocode If enabled, try to determine code vs. data sections @param autocode If enabled, try to determine code vs. data sections
@return The number of lines that were disassembled
*/ */
uInt32 disassemble(CartDebug::DisassemblyList& list, uInt16 start, DiStella(CartDebug::DisassemblyList& list, uInt16 start,
bool autocode = true); bool autocode = true);
~DiStella();
private: private:
// Marked bits // Marked bits

View File

@ -52,12 +52,15 @@ RomListWidget::~RomListWidget()
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomListWidget::setList(StringList& label, StringList& bytes, StringList& disasm, void RomListWidget::setList(const CartDebug::DisassemblyList& list,
BoolArray& state) const BoolArray& state)
{ {
myLabel = label; myList = &list;
myDisasm = disasm;
// TODO - maybe there's a better way than copying all the bytes again??
StringList bytes;
for(uInt32 i = 0; i < list.size(); ++i)
bytes.push_back(list[i].bytes);
CheckListWidget::setList(bytes, state); CheckListWidget::setList(bytes, state);
} }
@ -85,7 +88,8 @@ void RomListWidget::drawWidget(bool hilite)
{ {
//cerr << "RomListWidget::drawWidget\n"; //cerr << "RomListWidget::drawWidget\n";
FBSurface& s = _boss->dialog().surface(); FBSurface& s = _boss->dialog().surface();
int i, pos, xpos, ypos, len = _list.size(); const CartDebug::DisassemblyList& dlist = *myList;
int i, pos, xpos, ypos, len = dlist.size();
string buffer; string buffer;
int deltax; int deltax;
@ -126,11 +130,11 @@ void RomListWidget::drawWidget(bool hilite)
} }
// Draw labels // Draw labels
s.drawString(_font, myLabel[pos], xpos, ypos, s.drawString(_font, dlist[pos].label, xpos, ypos,
myLabelWidth, kTextColor); myLabelWidth, kTextColor);
// Draw disassembly // Draw disassembly
s.drawString(_font, myDisasm[pos], xpos + myLabelWidth, ypos, s.drawString(_font, dlist[pos].disasm, xpos + myLabelWidth, ypos,
r.left, kTextColor); r.left, kTextColor);
// Draw editable bytes // Draw editable bytes

View File

@ -26,7 +26,7 @@ class CheckboxWidget;
class ContextMenu; class ContextMenu;
#include "CheckListWidget.hxx" #include "CheckListWidget.hxx"
#include "CartDebug.hxx"
/** RomListWidget */ /** RomListWidget */
class RomListWidget : public CheckListWidget class RomListWidget : public CheckListWidget
@ -38,8 +38,7 @@ class RomListWidget : public CheckListWidget
int x, int y, int w, int h); int x, int y, int w, int h);
virtual ~RomListWidget(); virtual ~RomListWidget();
void setList(StringList& label, StringList& bytes, StringList& disasm, void setList(const CartDebug::DisassemblyList& list, const BoolArray& state);
BoolArray& state);
protected: protected:
void handleMouseDown(int x, int y, int button, int clickCount); void handleMouseDown(int x, int y, int button, int clickCount);
@ -56,7 +55,7 @@ class RomListWidget : public CheckListWidget
int myLabelWidth; int myLabelWidth;
int myBytesWidth; int myBytesWidth;
StringList myLabel, myDisasm; const CartDebug::DisassemblyList* myList;
}; };
#endif #endif

View File

@ -100,9 +100,6 @@ RomWidget::RomWidget(GuiObject* boss, const GUI::Font& font, int x, int y)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RomWidget::~RomWidget() RomWidget::~RomWidget()
{ {
myAddrList.clear();
myLineList.clear();
delete mySaveRom; delete mySaveRom;
} }
@ -166,71 +163,39 @@ void RomWidget::loadConfig()
// Fill romlist the current bank of source or disassembly // Fill romlist the current bank of source or disassembly
// Only reload full bank when necessary // Only reload full bank when necessary
if(myListIsDirty || bankChanged) // TODO - bank changes aren't the only time that the disassembly needs to
// be redone; ROMs which dynamically change cart address space and
// have self-modifying code need to be taken into account
// As well, we don't always start from the 0xfffc; this only
// happens in the startup bank
myListIsDirty |= cart.disassemble(true);
if(myListIsDirty)
{ {
/* const CartDebug::DisassemblyList& list = cart.disassemblyList();
// Clear old mappings
myAddrList.clear();
myLineList.clear();
StringList label, data, disasm;
BoolArray state; BoolArray state;
// Disassemble zero-page RAM and entire bank and reset breakpoints
cart.disassemble(myAddrList, label, data, disasm, 0x80, 0xff);
cart.disassemble(myAddrList, label, data, disasm, 0xf000, 0xffff);
PackedBitArray& bp = dbg.breakpoints(); PackedBitArray& bp = dbg.breakpoints();
for(unsigned int i = 0; i < data.size(); ++i) for(uInt32 i = 0; i < list.size(); ++i)
{ {
if(bp.isSet(myAddrList[i])) const CartDebug::DisassemblyTag& tag = list[i];
if(tag.address != 0 && bp.isSet(tag.address))
state.push_back(true); state.push_back(true);
else else
state.push_back(false); state.push_back(false);
} }
// Create a mapping from addresses to line numbers myRomList->setList(list, state);
for(unsigned int i = 0; i < myAddrList.size(); ++i)
myLineList.insert(make_pair(myAddrList[i], i));
myRomList->setList(label, data, disasm, state);
// Restore the old bank, in case we inadvertently switched while reading. // Restore the old bank, in case we inadvertently switched while reading.
dbg.setBank(myCurrentBank); dbg.setBank(myCurrentBank);
*/
CartDebug::DisassemblyList list;
cart.disassemble(list, dbg.dpeek(0xfffc), true);
for(uInt32 i = 0; i < list.size(); ++i)
{
const CartDebug::DisassemblyTag& tag = list[i];
printf("%.4X|%5s|%s|%s|\n", tag.address, tag.label.c_str(), tag.disasm.c_str(), tag.bytes.c_str());
}
myListIsDirty = false; myListIsDirty = false;
} }
// Update romlist to point to current PC // Update romlist to point to current PC
// Take mirroring of PC into account, as well as zero-page RAM int pcline = cart.addressToLine(dbg.cpuDebug().pc());
int pc = dbg.cpuDebug().pc(); if(pcline > 0)
if(pc & 0x1000) pc |= 0xe000; myRomList->setHighlighted(pcline);
AddrToLine::iterator iter = myLineList.find(pc);
// if current PC not found, do an update (we're executing what
// we thought was an operand)
// This doesn't help, and seems to actually hurt.
/*
if(iter == myLineList.end()) {
incrementalUpdate(myRomList->currentPos(), myRomList->rows());
iter = myLineList.find(pc);
}
*/
if(iter != myLineList.end())
myRomList->setHighlighted(iter->second);
// Set current bank // Set current bank
IntArray alist; IntArray alist;
@ -249,34 +214,53 @@ void RomWidget::loadConfig()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::setBreak(int data) void RomWidget::setBreak(int data)
{ {
const CartDebug::DisassemblyList& list =
instance().debugger().cartDebug().disassemblyList();
if(data >= (int)list.size()) return;
bool state = myRomList->getState(data); bool state = myRomList->getState(data);
instance().debugger().setBreakPoint(myAddrList[data], state); if(list[data].address != 0)
instance().debugger().setBreakPoint(list[data].address, state);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::setPC(int data) void RomWidget::setPC(int data)
{ {
ostringstream command; const CartDebug::DisassemblyList& list =
command << "pc #" << myAddrList[data]; instance().debugger().cartDebug().disassemblyList();
instance().debugger().run(command.str()); if(data >= (int)list.size()) return;
if(list[data].address != 0)
{
ostringstream command;
command << "pc #" << list[data].address;
instance().debugger().run(command.str());
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RomWidget::patchROM(int data, const string& bytes) void RomWidget::patchROM(int data, const string& bytes)
{ {
ostringstream command; const CartDebug::DisassemblyList& list =
instance().debugger().cartDebug().disassemblyList();
if(data >= (int)list.size()) return;
// Temporarily set to base 16, since that's the format the disassembled if(list[data].address != 0)
// byte string is in. This eliminates the need to prefix each byte with {
// a '$' character ostringstream command;
BaseFormat oldbase = instance().debugger().parser().base();
instance().debugger().parser().setBase(kBASE_16);
command << "rom #" << myAddrList[data] << " " << bytes; // Temporarily set to base 16, since that's the format the disassembled
instance().debugger().run(command.str()); // byte string is in. This eliminates the need to prefix each byte with
// a '$' character
BaseFormat oldbase = instance().debugger().parser().base();
instance().debugger().parser().setBase(kBASE_16);
// Restore previous base command << "rom #" << list[data].address << " " << bytes;
instance().debugger().parser().setBase(oldbase); instance().debugger().run(command.str());
// Restore previous base
instance().debugger().parser().setBase(oldbase);
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -29,14 +29,10 @@ class InputTextDialog;
class RomListWidget; class RomListWidget;
class StringList; class StringList;
#include <map>
#include "Array.hxx" #include "Array.hxx"
#include "Widget.hxx" #include "Widget.hxx"
#include "Command.hxx" #include "Command.hxx"
#include "CartDebug.hxx"
typedef map<int,int> AddrToLine;
class RomWidget : public Widget, public CommandSender class RomWidget : public Widget, public CommandSender
{ {
@ -60,14 +56,7 @@ class RomWidget : public Widget, public CommandSender
kRomNameEntered = 'RWrn' kRomNameEntered = 'RWrn'
}; };
RomListWidget* myRomList; RomListWidget* myRomList;
/** List of addresses indexed by line number */
IntArray myAddrList;
/** List of line numbers indexed by address */
AddrToLine myLineList;
DataGridWidget* myBank; DataGridWidget* myBank;
EditTextWidget* myBankCount; EditTextWidget* myBankCount;
InputTextDialog* mySaveRom; InputTextDialog* mySaveRom;