mirror of https://github.com/stella-emu/stella.git
DiStella::disassemble is now called from RomWidget! Of course, the output
isn't actually sent to the UI yet (it's still printed to the console), but at least the two parts of the code are now talking to each other. Note that the disassembly window in the debugger will be empty until I get this changeover complete. And with that, I'm not feeling well, so I'm taking the rest of the night off. git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1932 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
91f1406ed4
commit
deedb04709
|
@ -100,9 +100,9 @@ class CartDebug : public DebuggerSystem
|
|||
|
||||
/**
|
||||
Disassemble from the starting address, placing results into a
|
||||
DisassemblyList.
|
||||
DisassemblyList. If enabled, try to determine code vs. data.
|
||||
*/
|
||||
void disassemble(DisassemblyList& list, uInt16 start);
|
||||
void disassemble(DisassemblyList& list, uInt16 start, bool autocode);
|
||||
|
||||
int getBank();
|
||||
int bankCount();
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
DiStella::DiStella(System& system)
|
||||
: mySystem(system),
|
||||
mem(NULL), /* copied data from the file-- can be from 2K-48K bytes in size */
|
||||
labels(NULL) /* array of information about addresses-- can be from 2K-48K bytes in size */
|
||||
{
|
||||
}
|
||||
|
@ -40,15 +39,12 @@ DiStella::~DiStella()
|
|||
uInt32 DiStella::disassemble(CartDebug::DisassemblyList& list, uInt16 PC,
|
||||
bool autocode)
|
||||
{
|
||||
myLineCount = 0;
|
||||
while(!myAddressQueue.empty())
|
||||
myAddressQueue.pop();
|
||||
|
||||
myAppData.start = 0x0;
|
||||
myAppData.load = 0x0000;
|
||||
myAppData.length = 0;
|
||||
myAppData.length = 4096;
|
||||
myAppData.end = 0x0FFF;
|
||||
myAppData.disp_data = 0;
|
||||
|
||||
/*====================================*/
|
||||
/* Allocate memory for "labels" variable */
|
||||
|
@ -59,69 +55,43 @@ uInt32 DiStella::disassemble(CartDebug::DisassemblyList& list, uInt16 PC,
|
|||
return 0;
|
||||
}
|
||||
memset(labels,0,myAppData.length);
|
||||
/*====================================*/
|
||||
|
||||
/*-----------------------------------------------------
|
||||
The last 3 words of a program are as follows:
|
||||
The last 3 words of a program are as follows:
|
||||
|
||||
.word INTERRUPT (isr_adr)
|
||||
.word START (start_adr)
|
||||
.word BRKroutine (brk_adr)
|
||||
|
||||
Since we always process START, move the Program
|
||||
Counter 3 bytes back from the final byte.
|
||||
-----------------------------------------------------*/
|
||||
Since we always process START, move the Program
|
||||
Counter 3 bytes back from the final byte.
|
||||
-----------------------------------------------------*/
|
||||
|
||||
myPC = PC;
|
||||
uInt32 start_adr = read_adr();
|
||||
uInt16 start_adr = dpeek();
|
||||
|
||||
if (myAppData.end == 0x7ff) /* 2K case */
|
||||
{
|
||||
/*============================================
|
||||
What is the offset? Well, it's an address
|
||||
where the code segment starts. For a 2K game,
|
||||
it is usually 0xf800, which would then have the
|
||||
code data end at 0xffff, but that is not
|
||||
necessarily the case. Because the Atari 2600
|
||||
only has 13 address lines, it's possible that
|
||||
the "code" can be considered to start in a lot
|
||||
of different places. So, we use the start
|
||||
address as a reference to determine where the
|
||||
offset is, logically-anded to produce an offset
|
||||
that is a multiple of 2K.
|
||||
/*============================================
|
||||
The offset is the address where the code segment
|
||||
starts. For a 4K game, it is usually 0xf000,
|
||||
which would then have the code data end at 0xffff,
|
||||
but that is not necessarily the case. Because the
|
||||
Atari 2600 only has 13 address lines, it's possible
|
||||
that the "code" can be considered to start in a lot
|
||||
of different places. So, we use the start
|
||||
address as a reference to determine where the
|
||||
offset is, logically-anded to produce an offset
|
||||
that is a multiple of 4K.
|
||||
|
||||
Example:
|
||||
Start address = $D973, so therefore
|
||||
Offset to code = $D800
|
||||
Code range = $D800-$DFFF
|
||||
=============================================*/
|
||||
myOffset = (start_adr & 0xf800);
|
||||
}
|
||||
else if (myAppData.end == 0xfff) /* 4K case */
|
||||
{
|
||||
/*============================================
|
||||
The offset is the address where the code segment
|
||||
starts. For a 4K game, it is usually 0xf000,
|
||||
which would then have the code data end at 0xffff,
|
||||
but that is not necessarily the case. Because the
|
||||
Atari 2600 only has 13 address lines, it's possible
|
||||
that the "code" can be considered to start in a lot
|
||||
of different places. So, we use the start
|
||||
address as a reference to determine where the
|
||||
offset is, logically-anded to produce an offset
|
||||
that is a multiple of 4K.
|
||||
|
||||
Example:
|
||||
Start address = $D973, so therefore
|
||||
Offset to code = $D000
|
||||
Code range = $D000-$DFFF
|
||||
=============================================*/
|
||||
myOffset = (start_adr - (start_adr % 0x1000));
|
||||
}
|
||||
Example:
|
||||
Start address = $D973, so therefore
|
||||
Offset to code = $D000
|
||||
Code range = $D000-$DFFF
|
||||
=============================================*/
|
||||
myOffset = (start_adr - (start_adr % 0x1000));
|
||||
|
||||
myAddressQueue.push(start_adr);
|
||||
|
||||
if (autocode)
|
||||
if(autocode)
|
||||
{
|
||||
while(!myAddressQueue.empty())
|
||||
{
|
||||
|
@ -147,66 +117,23 @@ uInt32 DiStella::disassemble(CartDebug::DisassemblyList& list, uInt16 PC,
|
|||
disasm(list, myOffset, 3);
|
||||
|
||||
free(labels); /* Free dynamic memory before program ends */
|
||||
free(mem); /* Free dynamic memory before program ends */
|
||||
|
||||
return myLineCount;
|
||||
return list.size();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt16 DiStella::read_adr()
|
||||
inline uInt16 DiStella::dpeek()
|
||||
{
|
||||
uInt8 d1,d2;
|
||||
|
||||
d1 = mySystem.peek(myPC++);
|
||||
d2 = mySystem.peek(myPC++);
|
||||
uInt8 d1 = mySystem.peek(myPC++ | 0x1000);
|
||||
uInt8 d2 = mySystem.peek(myPC++ | 0x1000);
|
||||
|
||||
return (uInt16) ((d2 << 8)+d1);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int DiStella::file_load(const char* file)
|
||||
inline uInt8 DiStella::peek()
|
||||
{
|
||||
FILE *fn;
|
||||
|
||||
fn=fopen(file,"rb");
|
||||
if (fn == NULL)
|
||||
return 0;
|
||||
|
||||
if (myAppData.length == 0)
|
||||
myAppData.length = filesize(fn);
|
||||
|
||||
if (myAppData.length == 2048)
|
||||
myAppData.end = 0x7ff;
|
||||
else if (myAppData.length == 4096)
|
||||
myAppData.end = 0xfff;
|
||||
else
|
||||
{
|
||||
printf("Error: .bin file must be 2048 or 4096 bytes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*====================================*/
|
||||
/* Dynamically allocate memory for "mem" variable */
|
||||
mem=(uInt8 *)malloc(myAppData.length);
|
||||
if (mem == NULL)
|
||||
{
|
||||
printf ("Malloc failed for 'mem' variable\n");
|
||||
exit(1);
|
||||
}
|
||||
memset(mem,0,myAppData.length);
|
||||
/*====================================*/
|
||||
|
||||
rewind(fn); /* Point to beginning of file again */
|
||||
|
||||
/* if no header exists, just read in the file data */
|
||||
fread(&mem[myAppData.load],1,myAppData.length,fn);
|
||||
|
||||
fclose(fn); /* Data is read in, so close the file */
|
||||
|
||||
if (myAppData.start == 0)
|
||||
myAppData.start = myAppData.load;
|
||||
|
||||
return 1;
|
||||
return mySystem.peek(myPC | 0x1000);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -241,8 +168,8 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
else
|
||||
myBuf << HEX4 << myPC+myOffset << "' '";
|
||||
|
||||
myBuf << ".byte $" << HEX2 << (int)mem[myPC] << " ; ";
|
||||
showgfx(mem[myPC]);
|
||||
myBuf << ".byte $" << HEX2 << (int)peek() << " ; ";
|
||||
showgfx(peek());
|
||||
myBuf << " $" << HEX4 << myPC+myOffset;
|
||||
addEntry(list);
|
||||
}
|
||||
|
@ -256,7 +183,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
{
|
||||
bytes = 1;
|
||||
myBuf << HEX4 << myPC+myOffset << "'L" << myPC+myOffset << "'.byte "
|
||||
<< "$" << HEX2 << (int)mem[myPC];
|
||||
<< "$" << HEX2 << (int)peek();
|
||||
}
|
||||
myPC++;
|
||||
|
||||
|
@ -269,11 +196,11 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
if (bytes == 17)
|
||||
{
|
||||
addEntry(list);
|
||||
myBuf << " ' '.byte $" << HEX2 << (int)mem[myPC];
|
||||
myBuf << " ' '.byte $" << HEX2 << (int)peek();
|
||||
bytes = 1;
|
||||
}
|
||||
else
|
||||
myBuf << ",$" << HEX2 << (int)mem[myPC];
|
||||
myBuf << ",$" << HEX2 << (int)peek();
|
||||
}
|
||||
myPC++;
|
||||
}
|
||||
|
@ -287,7 +214,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
}
|
||||
else
|
||||
{
|
||||
op = mem[myPC];
|
||||
op = peek();
|
||||
/* version 2.1 bug fix */
|
||||
if (pass == 2)
|
||||
mark(myPC+myOffset, VALID_ENTRY);
|
||||
|
@ -300,16 +227,6 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
}
|
||||
|
||||
amode = ourLookup[op].addr_mode;
|
||||
if (myAppData.disp_data)
|
||||
{
|
||||
for (int i = 0; i < ourCLength[amode]; i++)
|
||||
if (pass == 3)
|
||||
myBuf << HEX2 << (int)mem[myPC+i] << " ";
|
||||
|
||||
if (pass == 3)
|
||||
myBuf << " ";
|
||||
}
|
||||
|
||||
myPC++;
|
||||
|
||||
if (ourLookup[op].mnemonic[0] == '.')
|
||||
|
@ -366,7 +283,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
else
|
||||
myBuf << HEX4 << myPC+myOffset << "' '";
|
||||
|
||||
op = mem[myPC++];
|
||||
op = peek(); myPC++;
|
||||
myBuf << ".byte $" << HEX2 << (int)op;
|
||||
addEntry(list);
|
||||
}
|
||||
|
@ -418,7 +335,6 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
{
|
||||
sprintf(linebuff,"\n");
|
||||
strcat(nextline,linebuff);
|
||||
++myLineCount;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -434,7 +350,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ABSOLUTE:
|
||||
{
|
||||
ad = read_adr();
|
||||
ad = dpeek();
|
||||
labfound = mark(ad, REFERENCED);
|
||||
if (pass == 1)
|
||||
{
|
||||
|
@ -493,7 +409,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ZERO_PAGE:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
labfound = mark(d1, REFERENCED);
|
||||
if (pass == 3)
|
||||
{
|
||||
|
@ -515,7 +431,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case IMMEDIATE:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
if (pass == 3)
|
||||
{
|
||||
sprintf(linebuff," #$%.2X ",d1);
|
||||
|
@ -528,7 +444,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ABSOLUTE_X:
|
||||
{
|
||||
ad = read_adr();
|
||||
ad = dpeek();
|
||||
labfound = mark(ad, REFERENCED);
|
||||
if (pass == 3)
|
||||
{
|
||||
|
@ -578,7 +494,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ABSOLUTE_Y:
|
||||
{
|
||||
ad = read_adr();
|
||||
ad = dpeek();
|
||||
labfound = mark(ad, REFERENCED);
|
||||
if (pass == 3)
|
||||
{
|
||||
|
@ -627,7 +543,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case INDIRECT_X:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
if (pass == 3)
|
||||
{
|
||||
sprintf(linebuff," ($%.2X,X)",d1);
|
||||
|
@ -640,7 +556,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case INDIRECT_Y:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
if (pass == 3)
|
||||
{
|
||||
sprintf(linebuff," ($%.2X),Y",d1);
|
||||
|
@ -653,7 +569,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ZERO_PAGE_X:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
labfound = mark(d1, REFERENCED);
|
||||
if (pass == 3)
|
||||
{
|
||||
|
@ -675,7 +591,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ZERO_PAGE_Y:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
labfound = mark(d1,REFERENCED);
|
||||
if (pass == 3)
|
||||
{
|
||||
|
@ -697,7 +613,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case RELATIVE:
|
||||
{
|
||||
d1 = mem[myPC++];
|
||||
d1 = peek(); myPC++;
|
||||
ad = d1;
|
||||
if (d1 >= 128)
|
||||
ad = d1 - 256;
|
||||
|
@ -733,7 +649,7 @@ void DiStella::disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass
|
|||
|
||||
case ABS_INDIRECT:
|
||||
{
|
||||
ad = read_adr();
|
||||
ad = dpeek();
|
||||
labfound = mark(ad, REFERENCED);
|
||||
if (pass == 3)
|
||||
{
|
||||
|
@ -940,7 +856,6 @@ void DiStella::addEntry(CartDebug::DisassemblyList& list)
|
|||
list.push_back(tag);
|
||||
|
||||
myBuf.str("");
|
||||
++myLineCount;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1295,21 +1210,3 @@ const char* DiStella::ourIOMnemonic[24] = {
|
|||
const int DiStella::ourCLength[14] = {
|
||||
1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 0
|
||||
};
|
||||
|
||||
#ifdef USE_MAIN
|
||||
int main(int ac, char* av[])
|
||||
{
|
||||
DiStella dis;
|
||||
DisassemblyList list;
|
||||
|
||||
int count = dis.disassemble(list, 0xfff-3, av[1]);
|
||||
|
||||
for(uInt32 i = 0; i < list.size(); ++i)
|
||||
{
|
||||
const DisassemblyTag& tag = list[i];
|
||||
printf("%.4X|%5s|%s|%s|\n", tag.address, tag.label.c_str(), tag.disasm.c_str(), tag.bytes.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -78,9 +78,13 @@ class DiStella
|
|||
// Here, we add a new entry to the DisassemblyList
|
||||
void addEntry(CartDebug::DisassemblyList& list);
|
||||
|
||||
// Get a word and byte, respectively, from the System
|
||||
// We use functions for this since Distella assumes that ROM starts
|
||||
// at address 0, whereas the System class starts above $1000 instead
|
||||
inline uInt16 dpeek();
|
||||
inline uInt8 peek();
|
||||
|
||||
// These functions are part of the original Distella code
|
||||
uInt16 read_adr();
|
||||
int file_load(const char* file);
|
||||
void disasm(CartDebug::DisassemblyList& list, uInt32 distart, int pass);
|
||||
int mark(uInt32 address, MarkType bit);
|
||||
int check_bit(uInt8 bitflags, int i);
|
||||
|
@ -90,18 +94,15 @@ class DiStella
|
|||
System& mySystem;
|
||||
stringstream myBuf;
|
||||
queue<uInt16> myAddressQueue;
|
||||
uInt32 myOffset, myPC, myPCBeg, myPCEnd, myLineCount;
|
||||
uInt32 myOffset, myPC, myPCBeg, myPCEnd;
|
||||
|
||||
struct resource {
|
||||
uInt16 start;
|
||||
uInt16 load;
|
||||
uInt32 length;
|
||||
uInt16 end;
|
||||
int disp_data;
|
||||
} myAppData;
|
||||
|
||||
/* Memory */
|
||||
uInt8* mem;
|
||||
uInt8* labels;
|
||||
|
||||
/**
|
||||
|
|
|
@ -168,6 +168,7 @@ void RomWidget::loadConfig()
|
|||
// Only reload full bank when necessary
|
||||
if(myListIsDirty || bankChanged)
|
||||
{
|
||||
/*
|
||||
// Clear old mappings
|
||||
myAddrList.clear();
|
||||
myLineList.clear();
|
||||
|
@ -197,6 +198,17 @@ void RomWidget::loadConfig()
|
|||
// Restore the old bank, in case we inadvertently switched while reading.
|
||||
dbg.setBank(myCurrentBank);
|
||||
|
||||
*/
|
||||
CartDebug::DisassemblyList list;
|
||||
cart.disassemble(list, 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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue