mirror of https://github.com/stella-emu/stella.git
More changes to CartDebug. Labels read from a symbol list or defined on
the debugger commandline are now reflected in most parts of the debugger UI. Still TODO is have DiStella use those labels in the disassembly, and deal with the formatting issues this will entail. Still completely broken are built-in functions, getting an equate address based on label, and tab-completions. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1963 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
0c6f564fa8
commit
6de4e358e1
|
@ -96,7 +96,7 @@ int CartDebug::readFromWritePort()
|
|||
// A read from the write port occurs when the read is actually in the write
|
||||
// port address space AND the last access was actually a read (the latter
|
||||
// differentiates between reads that are normally part of a write cycle vs.
|
||||
// ones that are illegal
|
||||
// ones that are illegal)
|
||||
if(mySystem.m6502().lastReadAddress() && peekAddress & 0x1000)
|
||||
{
|
||||
uInt16 addr = peekAddress & 0x0FFF;
|
||||
|
@ -217,7 +217,7 @@ int CartDebug::addressToLine(uInt16 address) const
|
|||
string CartDebug::disassemble(uInt16 start, uInt16 lines) const
|
||||
{
|
||||
if(!(start & 0x1000))
|
||||
return "Disassembly below 0x1000 not yet supported";
|
||||
return DebuggerParser::red("Disassembly below 0x1000 not yet supported");
|
||||
|
||||
DisassemblyList list;
|
||||
DiStella distella(list, start, false);
|
||||
|
@ -260,57 +260,34 @@ string CartDebug::getCartType()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void CartDebug::addLabel(const string& label, uInt16 address)
|
||||
{
|
||||
// First check if this already exists as a hard-coded equate
|
||||
LabelToAddr::const_iterator iter = mySystemAddresses.find(label);
|
||||
if(iter != mySystemAddresses.end() && iter->second.address == address)
|
||||
return;
|
||||
|
||||
// Create a new user equate, and determine if its RAM or ROM
|
||||
// For now, these are the only types we care about
|
||||
// Technically, addresses above 0x1000 are ROM and are read-only
|
||||
// However, somes ROMs have dedicated RAM mapped to those addresses
|
||||
// as well, and we don't yet have an infrastructure to determine that,
|
||||
// so the entire region is marked as read-write
|
||||
equate_t flags = EQF_READ;
|
||||
#if 0
|
||||
if(address >= 0x80 && address <= 0xff)
|
||||
flags = EQF_RW;
|
||||
else if((address & 0x1000) == 0x1000)
|
||||
flags = EQF_RW;
|
||||
else
|
||||
{
|
||||
cerr << "label = " << label << ", address = " << hex << address << " discarded\n";
|
||||
return; // don't know what else to do for now
|
||||
// Only user-defined labels can be added
|
||||
switch(addressType(address))
|
||||
{
|
||||
case ADDR_TIA:
|
||||
case ADDR_RIOT:
|
||||
return;
|
||||
default:
|
||||
cerr << "addLabel: label = " << label << ", address = " << hex << address << endl;
|
||||
removeLabel(label);
|
||||
myUserAddresses.insert(make_pair(label, address));
|
||||
myUserLabels.insert(make_pair(address, label));
|
||||
break;
|
||||
}
|
||||
#else
|
||||
// The above section of code is deactivated until a better means of
|
||||
// determining constants vs. addresses is found
|
||||
flags = EQF_RW;
|
||||
#endif
|
||||
|
||||
removeLabel(label);
|
||||
|
||||
Equate e;
|
||||
e.label = label;
|
||||
e.address = address;
|
||||
e.flags = flags;
|
||||
|
||||
myUserAddresses.insert(make_pair(label, e));
|
||||
myUserLabels.insert(make_pair(address, e));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::removeLabel(const string& label)
|
||||
{
|
||||
// Note that only user-defined equates can be removed
|
||||
// Only user-defined labels can be removed
|
||||
LabelToAddr::iterator iter = myUserAddresses.find(label);
|
||||
if(iter != myUserAddresses.end())
|
||||
{
|
||||
cerr << "removeLabel: label = " << label << endl;
|
||||
// Erase the label
|
||||
myUserAddresses.erase(iter);
|
||||
|
||||
// And also erase the address assigned to it
|
||||
AddrToLabel::iterator iter2 = myUserLabels.find(iter->second.address);
|
||||
AddrToLabel::iterator iter2 = myUserLabels.find(iter->second);
|
||||
if(iter2 != myUserLabels.end())
|
||||
myUserLabels.erase(iter2);
|
||||
|
||||
|
@ -323,73 +300,25 @@ bool CartDebug::removeLabel(const string& label)
|
|||
const string& CartDebug::getLabel(uInt16 addr, bool isRead, int places) const
|
||||
{
|
||||
static string result;
|
||||
AddrToLabel::const_iterator iter;
|
||||
|
||||
// Is this a read or write?
|
||||
// For now, there aren't separate read & write lists for user labels
|
||||
const AddrToLabel& systemLabels = isRead ?
|
||||
(const AddrToLabel&) mySystemReadLabels :
|
||||
(const AddrToLabel&) mySystemWriteLabels;
|
||||
|
||||
// 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
|
||||
address_t type = ADDR_ROM;
|
||||
if(addr % 0x2000 < 0x1000)
|
||||
{
|
||||
uInt16 z = addr & 0x00ff;
|
||||
if(z < 0x80)
|
||||
type = ADDR_TIA;
|
||||
else
|
||||
{
|
||||
switch(addr & 0x0f00)
|
||||
{
|
||||
case 0x000:
|
||||
case 0x100:
|
||||
case 0x400:
|
||||
case 0x500:
|
||||
case 0x800:
|
||||
case 0x900:
|
||||
case 0xc00:
|
||||
case 0xd00:
|
||||
type = ADDR_RAM;
|
||||
break;
|
||||
case 0x200:
|
||||
case 0x300:
|
||||
case 0x600:
|
||||
case 0x700:
|
||||
case 0xa00:
|
||||
case 0xb00:
|
||||
case 0xe00:
|
||||
case 0xf00:
|
||||
type = ADDR_RIOT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch(type)
|
||||
switch(addressType(addr))
|
||||
{
|
||||
case ADDR_TIA:
|
||||
if((iter = systemLabels.find(addr&0x7f)) != systemLabels.end())
|
||||
return iter->second.label;
|
||||
else if((iter = myUserLabels.find(addr)) != myUserLabels.end())
|
||||
return iter->second.label;
|
||||
break;
|
||||
return result =
|
||||
(isRead ? ourTIAMnemonicR[addr&0x0f] : ourTIAMnemonicW[addr&0x3f]);
|
||||
|
||||
case ADDR_RIOT: // FIXME - add mirrors for RIOT
|
||||
if((iter = systemLabels.find(addr)) != systemLabels.end())
|
||||
return iter->second.label;
|
||||
else if((iter = myUserLabels.find(addr)) != myUserLabels.end())
|
||||
return iter->second.label;
|
||||
break;
|
||||
case ADDR_RIOT:
|
||||
return result = ourIOMnemonic[(addr&0xf00)-280];
|
||||
|
||||
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.label;
|
||||
return iter->second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(places > -1)
|
||||
|
@ -405,6 +334,7 @@ const string& CartDebug::getLabel(uInt16 addr, bool isRead, int places) const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartDebug::getAddress(const string& label) const
|
||||
{
|
||||
/* FIXME
|
||||
LabelToAddr::const_iterator iter;
|
||||
|
||||
if((iter = mySystemAddresses.find(label)) != mySystemAddresses.end())
|
||||
|
@ -413,6 +343,8 @@ int CartDebug::getAddress(const string& label) const
|
|||
return iter->second.address;
|
||||
else
|
||||
return -1;
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -425,6 +357,8 @@ string CartDebug::loadSymbolFile(const string& f)
|
|||
else
|
||||
file += ".sym";
|
||||
|
||||
cerr << "loadSymbolFile: " << file << endl;
|
||||
|
||||
int pos = 0, lines = 0, curVal;
|
||||
string curLabel;
|
||||
char line[1024];
|
||||
|
@ -467,37 +401,15 @@ string CartDebug::loadSymbolFile(const string& f)
|
|||
return "loaded " + file + " OK";
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::saveSymbolFile(const string& file)
|
||||
{
|
||||
// Only user-defined equates are saved; system equates are always
|
||||
// available, so there's no need to save them
|
||||
char buf[256];
|
||||
|
||||
ofstream out(file.c_str());
|
||||
if(!out.is_open())
|
||||
return false;
|
||||
|
||||
out << "--- Symbol List (sorted by symbol)" << endl;
|
||||
|
||||
LabelToAddr::const_iterator iter;
|
||||
for(iter = myUserAddresses.begin(); iter != myUserAddresses.end(); iter++)
|
||||
{
|
||||
sprintf(buf, "%-24s %04x \n", iter->second.label.c_str(), iter->second.address);
|
||||
out << buf;
|
||||
}
|
||||
|
||||
out << "--- End of Symbol List." << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int CartDebug::countCompletions(const char *in)
|
||||
{
|
||||
/* FIXME
|
||||
myCompletions = myCompPrefix = "";
|
||||
return countCompletions(in, mySystemAddresses) +
|
||||
countCompletions(in, myUserAddresses);
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -534,6 +446,48 @@ int CartDebug::countCompletions(const char *in, LabelToAddr& addresses)
|
|||
return count;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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;
|
||||
else
|
||||
{
|
||||
switch(addr & 0x0f00)
|
||||
{
|
||||
case 0x000:
|
||||
case 0x100:
|
||||
case 0x400:
|
||||
case 0x500:
|
||||
case 0x800:
|
||||
case 0x900:
|
||||
case 0xc00:
|
||||
case 0xd00:
|
||||
type = ADDR_RAM;
|
||||
break;
|
||||
case 0x200:
|
||||
case 0x300:
|
||||
case 0x600:
|
||||
case 0x700:
|
||||
case 0xa00:
|
||||
case 0xb00:
|
||||
case 0xe00:
|
||||
case 0xf00:
|
||||
type = ADDR_RIOT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::extractLabel(char *c) const
|
||||
{
|
||||
|
@ -574,3 +528,28 @@ int CartDebug::extractValue(char *c) const
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const char* CartDebug::ourTIAMnemonicR[16] = {
|
||||
"CXM0P", "CXM1P", "CXP0FB", "CXP1FB", "CXM0FB", "CXM1FB", "CXBLPF", "CXPPMM",
|
||||
"INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", "$0E", "$0F"
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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"
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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"
|
||||
};
|
||||
|
|
|
@ -44,6 +44,9 @@ class CartState : public DebuggerState
|
|||
|
||||
class CartDebug : public DebuggerSystem
|
||||
{
|
||||
// The disassembler needs special access to this class
|
||||
friend class DiStella;
|
||||
|
||||
public:
|
||||
struct DisassemblyTag {
|
||||
uInt16 address;
|
||||
|
@ -124,12 +127,14 @@ class CartDebug : public DebuggerSystem
|
|||
|
||||
////////////////////////////////////////
|
||||
/**
|
||||
Add a label and associated address
|
||||
Add a label and associated address.
|
||||
Labels that reference either TIA or RIOT spaces will not be processed.
|
||||
*/
|
||||
void addLabel(const string& label, uInt16 address);
|
||||
|
||||
/**
|
||||
Remove the given label and its associated address
|
||||
Remove the given label and its associated address.
|
||||
Labels that reference either TIA or RIOT spaces will not be processed.
|
||||
*/
|
||||
bool removeLabel(const string& label);
|
||||
|
||||
|
@ -147,15 +152,10 @@ class CartDebug : public DebuggerSystem
|
|||
int getAddress(const string& label) const;
|
||||
|
||||
/**
|
||||
Load user equates from the given symbol file (generated by DASM)
|
||||
Load user equates from the given symbol file (as generated by DASM)
|
||||
*/
|
||||
string loadSymbolFile(const string& file);
|
||||
|
||||
/**
|
||||
Save user equates into a symbol file similar to that generated by DASM
|
||||
*/
|
||||
bool saveSymbolFile(const string& file);
|
||||
|
||||
/**
|
||||
Methods used by the command parser for tab-completion
|
||||
*/
|
||||
|
@ -165,27 +165,18 @@ class CartDebug : public DebuggerSystem
|
|||
////////////////////////////////////////
|
||||
|
||||
private:
|
||||
enum equate_t {
|
||||
EQF_READ = 1 << 0, // address can be read from
|
||||
EQF_WRITE = 1 << 1, // address can be written to
|
||||
EQF_RW = EQF_READ | EQF_WRITE // address can be both read and written
|
||||
};
|
||||
enum address_t {
|
||||
ADDR_TIA = 1 << 0,
|
||||
ADDR_RAM = 1 << 1,
|
||||
ADDR_RIOT = 1 << 2,
|
||||
ADDR_ROM = 1 << 3
|
||||
};
|
||||
struct Equate {
|
||||
string label;
|
||||
uInt16 address;
|
||||
equate_t flags;
|
||||
};
|
||||
typedef map<uInt16, string> AddrToLabel;
|
||||
typedef map<string, uInt16> LabelToAddr;
|
||||
|
||||
typedef map<uInt16, Equate> AddrToLabel;
|
||||
typedef map<string, Equate> LabelToAddr;
|
||||
// Determine 'type' of address (ie, what part of the system accessed)
|
||||
enum AddrType {
|
||||
ADDR_TIA,
|
||||
ADDR_RAM,
|
||||
ADDR_RIOT,
|
||||
ADDR_ROM
|
||||
};
|
||||
AddrType addressType(uInt16 addr) const;
|
||||
|
||||
private:
|
||||
// Extract labels and values from the given character stream
|
||||
string extractLabel(char *c) const;
|
||||
int extractValue(char *c) const;
|
||||
|
@ -196,23 +187,28 @@ class CartDebug : public DebuggerSystem
|
|||
private:
|
||||
CartState myState;
|
||||
CartState myOldState;
|
||||
RamAreaList myRamAreas;
|
||||
|
||||
// Used for the disassembly display, and mapping from addresses
|
||||
// to corresponding lines of text in that display
|
||||
DisassemblyList myDisassembly;
|
||||
map<uInt16, int> myAddrToLineList;
|
||||
|
||||
LabelToAddr mySystemAddresses;
|
||||
AddrToLabel mySystemReadLabels; // labels used in a read context
|
||||
AddrToLabel mySystemWriteLabels; // labels used in a write context
|
||||
|
||||
LabelToAddr myUserAddresses;
|
||||
// Mappings from label to address (and vice versa) for items
|
||||
// defined by the user (either through a symbol file or manually
|
||||
// from the commandline in the debugger)
|
||||
AddrToLabel myUserLabels;
|
||||
|
||||
RamAreaList myRamAreas;
|
||||
LabelToAddr myUserAddresses;
|
||||
|
||||
string myCompletions;
|
||||
string myCompPrefix;
|
||||
|
||||
uInt16 myRWPortAddress;
|
||||
|
||||
/// Table of instruction mnemonics
|
||||
static const char* ourTIAMnemonicR[16]; // read mode
|
||||
static const char* ourTIAMnemonicW[64]; // write mode
|
||||
static const char* ourIOMnemonic[24];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1224,16 +1224,6 @@ void DebuggerParser::executeSavestate()
|
|||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "savesym"
|
||||
void DebuggerParser::executeSavesym()
|
||||
{
|
||||
if(debugger->cartDebug().saveSymbolFile(argStrings[0]))
|
||||
commandResult = "saved symbols to file " + argStrings[0];
|
||||
else
|
||||
commandResult = red("I/O error");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// "scanline"
|
||||
void DebuggerParser::executeScanline()
|
||||
|
@ -1736,15 +1726,6 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
|
|||
&DebuggerParser::executeSavestate
|
||||
},
|
||||
|
||||
{
|
||||
"savesym",
|
||||
"Save symbols to file",
|
||||
true,
|
||||
false,
|
||||
{ kARG_FILE, kARG_END_ARGS },
|
||||
&DebuggerParser::executeSavesym
|
||||
},
|
||||
|
||||
{
|
||||
"scanline",
|
||||
"Advance emulation by xx scanlines (default=1)",
|
||||
|
|
|
@ -81,7 +81,7 @@ class DebuggerParser
|
|||
|
||||
private:
|
||||
enum {
|
||||
kNumCommands = 56,
|
||||
kNumCommands = 55,
|
||||
kMAX_ARG_TYPES = 10 // TODO: put in separate header file Command.hxx
|
||||
};
|
||||
|
||||
|
@ -177,7 +177,6 @@ class DebuggerParser
|
|||
void executeSaverom();
|
||||
void executeSaveses();
|
||||
void executeSavestate();
|
||||
void executeSavesym();
|
||||
void executeScanline();
|
||||
void executeStep();
|
||||
void executeTia();
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
DiStella::DiStella(CartDebug::DisassemblyList& list, uInt16 start,
|
||||
bool autocode)
|
||||
: labels(NULL) /* array of information about addresses-- can be from 2K-48K bytes in size */
|
||||
: myList(list),
|
||||
labels(NULL) /* array of information about addresses-- can be from 2K-48K bytes in size */
|
||||
{
|
||||
while(!myAddressQueue.empty())
|
||||
myAddressQueue.pop();
|
||||
|
@ -74,7 +75,7 @@ DiStella::DiStella(CartDebug::DisassemblyList& list, uInt16 start,
|
|||
myPC = myAddressQueue.front();
|
||||
myPCBeg = myPC;
|
||||
myAddressQueue.pop();
|
||||
disasm(list, myPC, 1);
|
||||
disasm(myPC, 1);
|
||||
for (uInt32 k = myPCBeg; k <= myPCEnd; k++)
|
||||
mark(k, REACHABLE);
|
||||
}
|
||||
|
@ -87,10 +88,10 @@ DiStella::DiStella(CartDebug::DisassemblyList& list, uInt16 start,
|
|||
}
|
||||
|
||||
// Second pass
|
||||
disasm(list, myOffset, 2);
|
||||
disasm(myOffset, 2);
|
||||
|
||||
// Third pass
|
||||
disasm(list, myOffset, 3);
|
||||
disasm(myOffset, 3);
|
||||
|
||||
free(labels); /* Free dynamic memory before program ends */
|
||||
}
|
||||
|
@ -101,7 +102,7 @@ DiStella::~DiStella()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass)
|
||||
void DiStella::disasm(uInt32 distart, int pass)
|
||||
{
|
||||
#define HEX4 uppercase << hex << setw(4) << setfill('0')
|
||||
#define HEX2 uppercase << hex << setw(2) << setfill('0')
|
||||
|
@ -135,7 +136,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
myBuf << ".byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset) << " ; ";
|
||||
showgfx(Debugger::debugger().peek(myPC+myOffset));
|
||||
myBuf << " $" << HEX4 << myPC+myOffset;
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
}
|
||||
myPC++;
|
||||
}
|
||||
|
@ -159,7 +160,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
bytes++;
|
||||
if (bytes == 17)
|
||||
{
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
myBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
|
||||
bytes = 1;
|
||||
}
|
||||
|
@ -171,9 +172,9 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
if (pass == 3)
|
||||
{
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
myBuf << " ' ' ";
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -238,7 +239,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
/* Line information is already printed; append .byte since last instruction will
|
||||
put recompilable object larger that original binary file */
|
||||
myBuf << ".byte $" << HEX2 << op;
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
|
||||
if (myPC == myAppData.end)
|
||||
{
|
||||
|
@ -249,7 +250,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
op = Debugger::debugger().peek(myPC+myOffset); myPC++;
|
||||
myBuf << ".byte $" << HEX2 << (int)op;
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
}
|
||||
}
|
||||
myPCEnd = myAppData.end + myOffset;
|
||||
|
@ -273,7 +274,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
strcat(nextline,linebuff);
|
||||
|
||||
myBuf << nextline;
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
strcpy(nextline,"");
|
||||
strcpy(nextlinebytes,"");
|
||||
}
|
||||
|
@ -348,7 +349,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
}
|
||||
else if (labfound == 3)
|
||||
{
|
||||
sprintf(linebuff,"%s",ourIOMnemonic[ad-0x280]);
|
||||
sprintf(linebuff,"%s",CartDebug::ourIOMnemonic[ad-0x280]);
|
||||
strcat(nextline,linebuff);
|
||||
sprintf(linebuff,"%02X %02X",(ad&0xff),(ad>>8));
|
||||
strcat(nextlinebytes,linebuff);
|
||||
|
@ -381,7 +382,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
if (labfound == 2)
|
||||
{
|
||||
sprintf(linebuff," %s", ourLookup[op].rw_mode == READ ?
|
||||
ourTIAMnemonicR[d1&0x0f] : ourTIAMnemonicW[d1&0x3f]);
|
||||
CartDebug::ourTIAMnemonicR[d1&0x0f] : CartDebug::ourTIAMnemonicW[d1&0x3f]);
|
||||
strcat(nextline,linebuff);
|
||||
}
|
||||
else
|
||||
|
@ -434,7 +435,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
}
|
||||
else if (labfound == 3)
|
||||
{
|
||||
sprintf(linebuff,"%s,X",ourIOMnemonic[ad-0x280]);
|
||||
sprintf(linebuff,"%s,X",CartDebug::ourIOMnemonic[ad-0x280]);
|
||||
strcat(nextline,linebuff);
|
||||
sprintf(linebuff,"%02X %02X",(ad&0xff),(ad>>8));
|
||||
strcat(nextlinebytes,linebuff);
|
||||
|
@ -483,7 +484,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
}
|
||||
else if (labfound == 3)
|
||||
{
|
||||
sprintf(linebuff,"%s,Y",ourIOMnemonic[ad-0x280]);
|
||||
sprintf(linebuff,"%s,Y",CartDebug::ourIOMnemonic[ad-0x280]);
|
||||
strcat(nextline,linebuff);
|
||||
sprintf(linebuff,"%02X %02X",(ad&0xff),(ad>>8));
|
||||
strcat(nextlinebytes,linebuff);
|
||||
|
@ -542,7 +543,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
if (labfound == 2)
|
||||
{
|
||||
sprintf(linebuff," %s,X", ourLookup[op].rw_mode == READ ?
|
||||
ourTIAMnemonicR[d1&0x0f] : ourTIAMnemonicW[d1&0x3f]);
|
||||
CartDebug::ourTIAMnemonicR[d1&0x0f] : CartDebug::ourTIAMnemonicW[d1&0x3f]);
|
||||
strcat(nextline,linebuff);
|
||||
}
|
||||
else
|
||||
|
@ -565,7 +566,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
if (labfound == 2)
|
||||
{
|
||||
sprintf(linebuff," %s,Y", ourLookup[op].rw_mode == READ ?
|
||||
ourTIAMnemonicR[d1&0x0f] : ourTIAMnemonicW[d1&0x3f]);
|
||||
CartDebug::ourTIAMnemonicR[d1&0x0f] : CartDebug::ourTIAMnemonicW[d1&0x3f]);
|
||||
strcat(nextline,linebuff);
|
||||
}
|
||||
else
|
||||
|
@ -641,7 +642,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
}
|
||||
else if (labfound == 3)
|
||||
{
|
||||
sprintf(linebuff,"(%s)",ourIOMnemonic[ad-0x280]);
|
||||
sprintf(linebuff,"(%s)",CartDebug::ourIOMnemonic[ad-0x280]);
|
||||
strcat(nextline,linebuff);
|
||||
sprintf(linebuff,"%02X %02X",(ad&0xff),(ad>>8));
|
||||
strcat(nextlinebytes,linebuff);
|
||||
|
@ -678,11 +679,11 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
myBuf << " ";
|
||||
}
|
||||
myBuf << ";" << dec << (int)ourLookup[op].cycles << "'" << nextlinebytes;
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
if (op == 0x40 || op == 0x60)
|
||||
{
|
||||
myBuf << " ' ' ";
|
||||
addEntry(list);
|
||||
addEntry();
|
||||
}
|
||||
|
||||
strcpy(nextline,"");
|
||||
|
@ -770,12 +771,6 @@ int DiStella::mark(uInt32 address, MarkType bit)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int DiStella::check_bit(uInt8 bitflags, int i)
|
||||
{
|
||||
return (int)(bitflags & i);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DiStella::showgfx(uInt8 c)
|
||||
{
|
||||
|
@ -795,7 +790,7 @@ void DiStella::showgfx(uInt8 c)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void DiStella::addEntry(CartDebug::DisassemblyList& list)
|
||||
void DiStella::addEntry()
|
||||
{
|
||||
const string& line = myBuf.str();
|
||||
CartDebug::DisassemblyTag tag;
|
||||
|
@ -821,7 +816,7 @@ void DiStella::addEntry(CartDebug::DisassemblyList& list)
|
|||
tag.bytes = line.substr(29);
|
||||
break;
|
||||
}
|
||||
list.push_back(tag);
|
||||
myList.push_back(tag);
|
||||
|
||||
myBuf.str("");
|
||||
}
|
||||
|
@ -1155,31 +1150,6 @@ const DiStella::Instruction_tag DiStella::ourLookup[256] = {
|
|||
/* ff */ { "isb", ABSOLUTE_X, M_ABSX, WRITE, 7 }
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const char* DiStella::ourTIAMnemonicR[16] = {
|
||||
"CXM0P", "CXM1P", "CXP0FB", "CXP1FB", "CXM0FB", "CXM1FB", "CXBLPF", "CXPPMM",
|
||||
"INPT0", "INPT1", "INPT2", "INPT3", "INPT4", "INPT5", "$0E", "$0F"
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const char* DiStella::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"
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const char* DiStella::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"
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const int DiStella::ourCLength[14] = {
|
||||
1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0
|
||||
|
|
|
@ -71,15 +71,16 @@ 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(CartDebug::DisassemblyList& list);
|
||||
void addEntry();
|
||||
|
||||
// These functions are part of the original Distella code
|
||||
void disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass);
|
||||
void disasm(uInt32 distart, int pass);
|
||||
int mark(uInt32 address, MarkType bit);
|
||||
int check_bit(uInt8 bitflags, int i);
|
||||
void showgfx(uInt8 c);
|
||||
inline int check_bit(uInt8 bitflags, int i) { return (bitflags & i); }
|
||||
|
||||
private:
|
||||
CartDebug::DisassemblyList& myList;
|
||||
stringstream myBuf;
|
||||
queue<uInt16> myAddressQueue;
|
||||
uInt32 myOffset, myPC, myPCBeg, myPCEnd;
|
||||
|
@ -146,11 +147,6 @@ class DiStella
|
|||
};
|
||||
static const Instruction_tag ourLookup[256];
|
||||
|
||||
/// Table of instruction mnemonics
|
||||
static const char* ourTIAMnemonicR[16]; // read mode
|
||||
static const char* ourTIAMnemonicW[64]; // write mode
|
||||
static const char* ourIOMnemonic[24];
|
||||
|
||||
static const int ourCLength[14];
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue