Debugger: Separate disassembler functions from display (PR #933)
Makes it easier to use them in different environments.
This commit is contained in:
parent
3f75012c0e
commit
c7f515015b
11 changed files with 779 additions and 760 deletions
|
@ -329,6 +329,14 @@
|
|||
RelativePath=".\source\Debugger\Debugger_Console.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Debugger\Debugger_Disassembler.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Debugger\Debugger_Disassembler.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\source\Debugger\Debugger_DisassemblerData.cpp"
|
||||
>
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
<ClInclude Include="source\Debugger\Debugger_Assembler.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Color.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Console.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Disassembler.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_DisassemblerData.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Display.h" />
|
||||
<ClInclude Include="source\Debugger\Debugger_Help.h" />
|
||||
|
@ -153,6 +154,7 @@
|
|||
<ClCompile Include="source\Configuration\PropertySheetHelper.cpp" />
|
||||
<ClCompile Include="source\Core.cpp" />
|
||||
<ClCompile Include="source\CPU.cpp" />
|
||||
<ClCompile Include="source\Debugger\Debugger_Disassembler.cpp" />
|
||||
<ClCompile Include="source\Disk2CardManager.cpp" />
|
||||
<ClCompile Include="source\FrameBase.cpp" />
|
||||
<ClCompile Include="source\RGBMonitor.cpp" />
|
||||
|
|
|
@ -220,6 +220,9 @@
|
|||
<ClCompile Include="source\Windows\Win32Frame.cpp">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\Debugger\Debugger_Disassembler.cpp">
|
||||
<Filter>Source Files\Debugger</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="source\CommonVICE\6510core.h">
|
||||
|
@ -522,6 +525,9 @@
|
|||
<ClInclude Include="source\Windows\Win32Frame.h">
|
||||
<Filter>Source Files\Windows</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\Debugger\Debugger_Disassembler.h">
|
||||
<Filter>Source Files\Debugger</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="resource\Applewin.bmp">
|
||||
|
|
|
@ -361,21 +361,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
Update_t _CmdWindowViewCommon (int iNewWindow);
|
||||
|
||||
// Utility
|
||||
char FormatCharTxtCtrl ( const BYTE b, bool *pWasCtrl_ );
|
||||
char FormatCharTxtAsci ( const BYTE b, bool *pWasAsci_ );
|
||||
char FormatCharTxtHigh ( const BYTE b, bool *pWasHi_ );
|
||||
char FormatChar4Font ( const BYTE b, bool *pWasHi_, bool *pWasLo_ );
|
||||
|
||||
void _CursorMoveDownAligned( int nDelta );
|
||||
void _CursorMoveUpAligned( int nDelta );
|
||||
|
||||
void DisasmCalcTopFromCurAddress( bool bUpdateTop = true );
|
||||
void DisasmCalcCurFromTopAddress();
|
||||
void DisasmCalcBotFromTopAddress();
|
||||
void DisasmCalcTopBotAddress ();
|
||||
WORD DisasmCalcAddressFromLines( WORD iAddress, int nLines );
|
||||
|
||||
|
||||
// DebugVideoMode _____________________________________________________________
|
||||
|
||||
// Fix for GH#345
|
||||
|
@ -2957,133 +2945,6 @@ Update_t CmdConfigGetFont (int nArgs)
|
|||
|
||||
// Cursor _________________________________________________________________________________________
|
||||
|
||||
// Given an Address, and Line to display it on
|
||||
// Calculate the address of the top and bottom lines
|
||||
// @param bUpdateCur
|
||||
// true = Update Cur based on Top
|
||||
// false = Update Top & Bot based on Cur
|
||||
//===========================================================================
|
||||
void DisasmCalcTopFromCurAddress( bool bUpdateTop )
|
||||
{
|
||||
int nLen = ((g_nDisasmWinHeight - g_nDisasmCurLine) * 3); // max 3 opcodes/instruction, is our search window
|
||||
|
||||
// Look for a start address that when disassembled,
|
||||
// will have the cursor on the specified line and address
|
||||
int iTop = g_nDisasmCurAddress - nLen;
|
||||
int iCur = g_nDisasmCurAddress;
|
||||
|
||||
g_bDisasmCurBad = false;
|
||||
|
||||
bool bFound = false;
|
||||
while (iTop <= iCur)
|
||||
{
|
||||
WORD iAddress = iTop;
|
||||
// int iOpcode;
|
||||
int iOpmode;
|
||||
int nOpbytes;
|
||||
|
||||
for( int iLine = 0; iLine <= nLen; iLine++ ) // min 1 opcode/instruction
|
||||
{
|
||||
// a.
|
||||
_6502_GetOpmodeOpbyte( iAddress, iOpmode, nOpbytes );
|
||||
// b.
|
||||
// _6502_GetOpcodeOpmodeOpbyte( iOpcode, iOpmode, nOpbytes );
|
||||
|
||||
if (iLine == g_nDisasmCurLine) // && (iAddress == g_nDisasmCurAddress))
|
||||
{
|
||||
if (iAddress == g_nDisasmCurAddress)
|
||||
// b.
|
||||
// && (iOpmode != AM_1) &&
|
||||
// && (iOpmode != AM_2) &&
|
||||
// && (iOpmode != AM_3) &&
|
||||
// && _6502_IsOpcodeValid( iOpcode))
|
||||
{
|
||||
g_nDisasmTopAddress = iTop;
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// .20 Fixed: DisasmCalcTopFromCurAddress()
|
||||
//if ((eMode >= AM_1) && (eMode <= AM_3))
|
||||
#if 0 // _DEBUG
|
||||
TCHAR sText[ CONSOLE_WIDTH ];
|
||||
wsprintf( sText, "%04X : %d bytes\n", iAddress, nOpbytes );
|
||||
OutputDebugString( sText );
|
||||
#endif
|
||||
iAddress += nOpbytes;
|
||||
}
|
||||
if (bFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
iTop++;
|
||||
}
|
||||
|
||||
if (! bFound)
|
||||
{
|
||||
// Well, we're up the creek.
|
||||
// There is no (valid) solution!
|
||||
// Basically, there is no address, that when disassembled,
|
||||
// will put our Address on the cursor Line!
|
||||
// So, like typical game programming, when we don't like the solution, change the problem!
|
||||
// if (bUpdateTop)
|
||||
g_nDisasmTopAddress = g_nDisasmCurAddress;
|
||||
|
||||
g_bDisasmCurBad = true; // Bad Disassembler, no opcode for you!
|
||||
|
||||
// We reall should move the cursor line to the top for one instruction.
|
||||
// Moving the cursor line around is not really a good idea, since we're breaking consistency paradigm for the user.
|
||||
// g_nDisasmCurLine = 0;
|
||||
#if 0 // _DEBUG
|
||||
TCHAR sText[ CONSOLE_WIDTH * 2 ];
|
||||
sprintf( sText, TEXT("DisasmCalcTopFromCurAddress()\n"
|
||||
"\tTop: %04X\n"
|
||||
"\tLen: %04X\n"
|
||||
"\tMissed: %04X"),
|
||||
g_nDisasmCurAddress - nLen, nLen, g_nDisasmCurAddress );
|
||||
GetFrame().FrameMessageBox( sText, "ERROR", MB_OK );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
WORD DisasmCalcAddressFromLines( WORD iAddress, int nLines )
|
||||
{
|
||||
while (nLines-- > 0)
|
||||
{
|
||||
int iOpmode;
|
||||
int nOpbytes;
|
||||
_6502_GetOpmodeOpbyte( iAddress, iOpmode, nOpbytes );
|
||||
iAddress += nOpbytes;
|
||||
}
|
||||
return iAddress;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void DisasmCalcCurFromTopAddress()
|
||||
{
|
||||
g_nDisasmCurAddress = DisasmCalcAddressFromLines( g_nDisasmTopAddress, g_nDisasmCurLine );
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void DisasmCalcBotFromTopAddress( )
|
||||
{
|
||||
g_nDisasmBotAddress = DisasmCalcAddressFromLines( g_nDisasmTopAddress, g_nDisasmWinHeight );
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void DisasmCalcTopBotAddress ()
|
||||
{
|
||||
DisasmCalcTopFromCurAddress();
|
||||
DisasmCalcBotFromTopAddress();
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
Update_t CmdCursorFollowTarget ( int nArgs )
|
||||
{
|
||||
|
@ -8859,7 +8720,6 @@ void DebugInitialize ()
|
|||
memset( g_aZeroPagePointers, 0, MAX_ZEROPAGE_POINTERS * sizeof(ZeroPagePointers_t));
|
||||
|
||||
// Load Main, Applesoft, and User Symbols
|
||||
extern bool g_bSymbolsDisplayMissingFile;
|
||||
g_bSymbolsDisplayMissingFile = false;
|
||||
|
||||
g_iCommand = CMD_SYMBOLS_ROM;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "Debugger_Types.h"
|
||||
#include "Debugger_DisassemblerData.h"
|
||||
#include "Debugger_Disassembler.h"
|
||||
#include "Debugger_Range.h"
|
||||
#include "Debugger_Parser.h"
|
||||
#include "Debugger_Console.h"
|
||||
|
@ -145,15 +146,6 @@
|
|||
|
||||
// Source Level Debugging
|
||||
int FindSourceLine( WORD nAddress );
|
||||
const char* FormatAddress( WORD nAddress, int nBytes );
|
||||
|
||||
// Symbol Table / Memory
|
||||
bool FindAddressFromSymbol( const char* pSymbol, WORD * pAddress_ = NULL, int * iTable_ = NULL );
|
||||
WORD GetAddressFromSymbol( const char* symbol); // HACK: returns 0 if symbol not found
|
||||
void SymbolUpdate( SymbolTable_Index_e eSymbolTable, const char *pSymbolName, WORD nAddrss, bool bRemoveSymbol, bool bUpdateSymbol );
|
||||
|
||||
const char* FindSymbolFromAddress( WORD nAdress, int * iTable_ = NULL );
|
||||
const char* GetSymbol( WORD nAddress, int nBytes);
|
||||
|
||||
// Memory
|
||||
size_t Util_GetTextScreen( char* &pText_ );
|
||||
|
|
723
source/Debugger/Debugger_Disassembler.cpp
Normal file
723
source/Debugger/Debugger_Disassembler.cpp
Normal file
|
@ -0,0 +1,723 @@
|
|||
#include "StdAfx.h"
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
#include "../Memory.h"
|
||||
|
||||
//===========================================================================
|
||||
const char* FormatAddress(WORD nAddress, int nBytes)
|
||||
{
|
||||
// There is no symbol for this nAddress
|
||||
static TCHAR sSymbol[8] = TEXT("");
|
||||
switch (nBytes)
|
||||
{
|
||||
case 2: wsprintf(sSymbol, TEXT("$%02X"), (unsigned)nAddress); break;
|
||||
case 3: wsprintf(sSymbol, TEXT("$%04X"), (unsigned)nAddress); break;
|
||||
// TODO: FIXME: Can we get called with nBytes == 16 ??
|
||||
default: sSymbol[0] = 0; break; // clear since is static
|
||||
}
|
||||
return sSymbol;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen)
|
||||
{
|
||||
for (int i = 0; i < nLen; i++)
|
||||
*pDst++ = FormatCharTxtCtrl(*pSrc++);
|
||||
return pDst;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_)
|
||||
{
|
||||
if (pWasAsci_)
|
||||
*pWasAsci_ = false;
|
||||
|
||||
char c = (b & 0x7F);
|
||||
if (b <= 0x7F)
|
||||
{
|
||||
if (pWasAsci_)
|
||||
{
|
||||
*pWasAsci_ = true;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// Note: FormatCharTxtCtrl() and RemapChar()
|
||||
//===========================================================================
|
||||
char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_)
|
||||
{
|
||||
if (pWasCtrl_)
|
||||
*pWasCtrl_ = false;
|
||||
|
||||
char c = (b & 0x7F); // .32 Changed: Lo now maps High Ascii to printable chars. i.e. ML1 D0D0
|
||||
if (b < 0x20) // SPACE
|
||||
{
|
||||
if (pWasCtrl_)
|
||||
{
|
||||
*pWasCtrl_ = true;
|
||||
}
|
||||
c = b + '@'; // map ctrl chars to visible
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char FormatCharTxtHigh(const BYTE b, bool* pWasHi_)
|
||||
{
|
||||
if (pWasHi_)
|
||||
*pWasHi_ = false;
|
||||
|
||||
char c = b;
|
||||
if (b > 0x7F)
|
||||
{
|
||||
if (pWasHi_)
|
||||
{
|
||||
*pWasHi_ = true;
|
||||
}
|
||||
c = (b & 0x7F);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
char FormatChar4Font(const BYTE b, bool* pWasHi_, bool* pWasLo_)
|
||||
{
|
||||
// Most Windows Fonts don't have (printable) glyphs for control chars
|
||||
BYTE b1 = FormatCharTxtHigh(b, pWasHi_);
|
||||
BYTE b2 = FormatCharTxtCtrl(b1, pWasLo_);
|
||||
return b2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Disassembly
|
||||
/*
|
||||
// Thought about moving MouseText to another location, say high bit, 'A' + 0x80
|
||||
// But would like to keep compatibility with existing CHARSET40
|
||||
// Since we should be able to display all apple chars 0x00 .. 0xFF with minimal processing
|
||||
// Use CONSOLE_COLOR_ESCAPE_CHAR to shift to mouse text
|
||||
* Apple Font
|
||||
K Mouse Text Up Arror
|
||||
H Mouse Text Left Arrow
|
||||
J Mouse Text Down Arrow
|
||||
* Wingdings
|
||||
\xE1 Up Arrow
|
||||
\xE2 Down Arrow
|
||||
* Webdings // M$ Font
|
||||
\x35 Up Arrow
|
||||
\x33 Left Arrow (\x71 recycl is too small to make out details)
|
||||
\x36 Down Arrow
|
||||
* Symols
|
||||
\xAD Up Arrow
|
||||
\xAF Down Arrow
|
||||
* ???
|
||||
\x18 Up
|
||||
\x19 Down
|
||||
*/
|
||||
#if USE_APPLE_FONT
|
||||
const char* g_sConfigBranchIndicatorUp[NUM_DISASM_BRANCH_TYPES + 1] = { " ", "^", "\x8B" }; // "`K" 0x4B
|
||||
const char* g_sConfigBranchIndicatorEqual[NUM_DISASM_BRANCH_TYPES + 1] = { " ", "=", "\x88" }; // "`H" 0x48
|
||||
const char* g_sConfigBranchIndicatorDown[NUM_DISASM_BRANCH_TYPES + 1] = { " ", "v", "\x8A" }; // "`J" 0x4A
|
||||
#else
|
||||
const char* g_sConfigBranchIndicatorUp[NUM_DISASM_BRANCH_TYPES + 1] = { " ", "^", "\x35" };
|
||||
const char* g_sConfigBranchIndicatorEqual[NUM_DISASM_BRANCH_TYPES + 1] = { " ", "=", "\x33" };
|
||||
char* g_sConfigBranchIndicatorDown[NUM_DISASM_BRANCH_TYPES + 1] = { " ", "v", "\x36" };
|
||||
#endif
|
||||
|
||||
// Disassembly ____________________________________________________________________________________
|
||||
|
||||
void GetTargets_IgnoreDirectJSRJMP(const BYTE iOpcode, int& nTargetPointer)
|
||||
{
|
||||
if (iOpcode == OPCODE_JSR || iOpcode == OPCODE_JMP_A)
|
||||
nTargetPointer = NO_6502_TARGET;
|
||||
}
|
||||
|
||||
|
||||
// Get the data needed to disassemble one line of opcodes. Fills in the DisasmLine info.
|
||||
// Disassembly formatting flags returned
|
||||
// @parama sTargetValue_ indirect/indexed final value
|
||||
//===========================================================================
|
||||
int GetDisassemblyLine(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
// char *sAddress_, char *sOpCodes_,
|
||||
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_,
|
||||
// char *sTargetPointer_, char *sTargetValue_,
|
||||
// char *sImmediate_, char & nImmediate_, char *sBranch_ )
|
||||
{
|
||||
line_.Clear();
|
||||
|
||||
int iOpcode;
|
||||
int iOpmode;
|
||||
int nOpbyte;
|
||||
|
||||
iOpcode = _6502_GetOpmodeOpbyte(nBaseAddress, iOpmode, nOpbyte, &line_.pDisasmData);
|
||||
const DisasmData_t* pData = line_.pDisasmData; // Disassembly_IsDataAddress( nBaseAddress );
|
||||
|
||||
line_.iOpcode = iOpcode;
|
||||
line_.iOpmode = iOpmode;
|
||||
line_.nOpbyte = nOpbyte;
|
||||
|
||||
#if _DEBUG
|
||||
// if (iLine != 41)
|
||||
// return nOpbytes;
|
||||
#endif
|
||||
|
||||
if (iOpmode == AM_M)
|
||||
line_.bTargetImmediate = true;
|
||||
|
||||
if ((iOpmode >= AM_IZX) && (iOpmode <= AM_NA))
|
||||
line_.bTargetIndirect = true; // ()
|
||||
|
||||
if ((iOpmode >= AM_IZX) && (iOpmode <= AM_NZY))
|
||||
line_.bTargetIndexed = true; // ()
|
||||
|
||||
if (((iOpmode >= AM_A) && (iOpmode <= AM_ZY)) || line_.bTargetIndirect)
|
||||
line_.bTargetValue = true; // #$
|
||||
|
||||
if ((iOpmode == AM_AX) || (iOpmode == AM_ZX) || (iOpmode == AM_IZX) || (iOpmode == AM_IAX))
|
||||
line_.bTargetX = true; // ,X
|
||||
|
||||
if ((iOpmode == AM_AY) || (iOpmode == AM_ZY) || (iOpmode == AM_NZY))
|
||||
line_.bTargetY = true; // ,Y
|
||||
|
||||
unsigned int nMinBytesLen = (MAX_OPCODES * (2 + g_bConfigDisasmOpcodeSpaces)); // 2 char for byte (or 3 with space)
|
||||
|
||||
int bDisasmFormatFlags = 0;
|
||||
|
||||
// Composite string that has the symbol or target nAddress
|
||||
WORD nTarget = 0;
|
||||
|
||||
if ((iOpmode != AM_IMPLIED) &&
|
||||
(iOpmode != AM_1) &&
|
||||
(iOpmode != AM_2) &&
|
||||
(iOpmode != AM_3))
|
||||
{
|
||||
// Assume target address starts after the opcode ...
|
||||
// BUT in the Assembler Directive / Data Disassembler case for define addr/word
|
||||
// the opcode literally IS the target address!
|
||||
if (pData)
|
||||
{
|
||||
nTarget = pData->nTargetAddress;
|
||||
}
|
||||
else {
|
||||
nTarget = mem[(nBaseAddress + 1) & 0xFFFF] | (mem[(nBaseAddress + 2) & 0xFFFF] << 8);
|
||||
if (nOpbyte == 2)
|
||||
nTarget &= 0xFF;
|
||||
}
|
||||
|
||||
if (iOpmode == AM_R) // Relative
|
||||
{
|
||||
line_.bTargetRelative = true;
|
||||
|
||||
nTarget = nBaseAddress + 2 + (int)(signed char)nTarget;
|
||||
|
||||
line_.nTarget = nTarget;
|
||||
sprintf(line_.sTargetValue, "%04X", nTarget & 0xFFFF);
|
||||
|
||||
// Always show branch indicators
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_BRANCH;
|
||||
|
||||
if (nTarget < nBaseAddress)
|
||||
{
|
||||
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorUp[g_iConfigDisasmBranchType]);
|
||||
}
|
||||
else
|
||||
if (nTarget > nBaseAddress)
|
||||
{
|
||||
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorDown[g_iConfigDisasmBranchType]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(line_.sBranch, "%s", g_sConfigBranchIndicatorEqual[g_iConfigDisasmBranchType]);
|
||||
}
|
||||
}
|
||||
// intentional re-test AM_R ...
|
||||
|
||||
// if ((iOpmode >= AM_A) && (iOpmode <= AM_NA))
|
||||
if ((iOpmode == AM_A) || // Absolute
|
||||
(iOpmode == AM_Z) || // Zeropage
|
||||
(iOpmode == AM_AX) || // Absolute, X
|
||||
(iOpmode == AM_AY) || // Absolute, Y
|
||||
(iOpmode == AM_ZX) || // Zeropage, X
|
||||
(iOpmode == AM_ZY) || // Zeropage, Y
|
||||
(iOpmode == AM_R) || // Relative
|
||||
(iOpmode == AM_IZX) || // Indexed (Zeropage Indirect, X)
|
||||
(iOpmode == AM_IAX) || // Indexed (Absolute Indirect, X)
|
||||
(iOpmode == AM_NZY) || // Indirect (Zeropage) Index, Y
|
||||
(iOpmode == AM_NZ) || // Indirect (Zeropage)
|
||||
(iOpmode == AM_NA)) //(Indirect Absolute)
|
||||
{
|
||||
line_.nTarget = nTarget;
|
||||
|
||||
const char* pTarget = NULL;
|
||||
const char* pSymbol = 0;
|
||||
|
||||
pSymbol = FindSymbolFromAddress(nTarget);
|
||||
|
||||
// Data Assembler
|
||||
if (pData && (!pData->bSymbolLookup))
|
||||
pSymbol = 0;
|
||||
|
||||
// Try exact match first
|
||||
if (pSymbol)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
||||
pTarget = pSymbol;
|
||||
}
|
||||
|
||||
if (!(bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
|
||||
{
|
||||
pSymbol = FindSymbolFromAddress(nTarget - 1);
|
||||
if (pSymbol)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_OFFSET;
|
||||
pTarget = pSymbol;
|
||||
line_.nTargetOffset = +1; // U FA82 LDA $3F1 BREAK-1
|
||||
}
|
||||
}
|
||||
|
||||
// Old Offset search: (Search +1 First) nTarget-1, (Search -1 Second) nTarget+1
|
||||
// Problem: U D038 shows as A.TRACE+1
|
||||
// New Offset search: (Search -1 First) nTarget+1, (Search +1 Second) nTarget+1
|
||||
// Problem: U D834, D87E shows as P.MUL-1, instead of P.ADD+1
|
||||
// 2.6.2.31 Fixed: address table was bailing on first possible match. U D000 -> da STOP+1, instead of END-1
|
||||
// 2.7.0.0: Try to match nTarget-1, nTarget+1, AND if we have both matches
|
||||
// Then we need to decide which one to show. If we have pData then pick this one.
|
||||
// TODO: Do we need to let the user decide which one they want searched first?
|
||||
// nFirstTarget = g_bDebugConfig_DisasmMatchSymbolOffsetMinus1First ? nTarget-1 : nTarget+1;
|
||||
// nSecondTarget = g_bDebugConfig_DisasmMatchSymbolOffsetMinus1First ? nTarget+1 : nTarget-1;
|
||||
if (!(bDisasmFormatFlags & DISASM_FORMAT_SYMBOL) || pData)
|
||||
{
|
||||
pSymbol = FindSymbolFromAddress(nTarget + 1);
|
||||
if (pSymbol)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_OFFSET;
|
||||
pTarget = pSymbol;
|
||||
line_.nTargetOffset = -1; // U FA82 LDA $3F3 BREAK+1
|
||||
}
|
||||
}
|
||||
|
||||
if (!(bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
|
||||
{
|
||||
pTarget = FormatAddress(nTarget, (iOpmode != AM_R) ? nOpbyte : 3); // GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
|
||||
}
|
||||
|
||||
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
|
||||
{
|
||||
int nAbsTargetOffset = (line_.nTargetOffset > 0) ? line_.nTargetOffset : -line_.nTargetOffset;
|
||||
sprintf(line_.sTargetOffset, "%d", nAbsTargetOffset);
|
||||
}
|
||||
sprintf(line_.sTarget, "%s", pTarget);
|
||||
|
||||
|
||||
// Indirect / Indexed
|
||||
int nTargetPartial;
|
||||
int nTargetPartial2;
|
||||
int nTargetPointer;
|
||||
WORD nTargetValue = 0; // de-ref
|
||||
_6502_GetTargets(nBaseAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, NULL);
|
||||
GetTargets_IgnoreDirectJSRJMP(iOpcode, nTargetPointer); // For *direct* JSR/JMP, don't show 'addr16:byte char'
|
||||
|
||||
if (nTargetPointer != NO_6502_TARGET)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_POINTER;
|
||||
|
||||
nTargetValue = *(mem + nTargetPointer) | (*(mem + ((nTargetPointer + 1) & 0xffff)) << 8);
|
||||
|
||||
// if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
|
||||
// sprintf( sTargetValue_, "%04X", nTargetValue ); // & 0xFFFF
|
||||
|
||||
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
|
||||
sprintf(line_.sTargetPointer, "%04X", nTargetPointer & 0xFFFF);
|
||||
|
||||
if (iOpcode != OPCODE_JMP_NA && iOpcode != OPCODE_JMP_IAX)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_VALUE;
|
||||
if (g_iConfigDisasmTargets & DISASM_TARGET_VAL)
|
||||
sprintf(line_.sTargetValue, "%02X", nTargetValue & 0xFF);
|
||||
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
|
||||
line_.nImmediate = (BYTE)nTargetValue;
|
||||
|
||||
unsigned _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
|
||||
sprintf(line_.sImmediate, "%c", _char);
|
||||
|
||||
// if (ConsoleColorIsEscapeMeta( nImmediate_ ))
|
||||
#if OLD_CONSOLE_COLOR
|
||||
if (ConsoleColorIsEscapeMeta(_char))
|
||||
sprintf(line_.sImmediate, "%c%c", _char, _char);
|
||||
else
|
||||
sprintf(line_.sImmediate, "%c", _char);
|
||||
#endif
|
||||
}
|
||||
|
||||
// if (iOpmode == AM_NA ) // Indirect Absolute
|
||||
// sprintf( sTargetValue_, "%04X", nTargetPointer & 0xFFFF );
|
||||
// else
|
||||
// // sprintf( sTargetValue_, "%02X", nTargetValue & 0xFF );
|
||||
// sprintf( sTargetValue_, "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
|
||||
}
|
||||
}
|
||||
else
|
||||
if (iOpmode == AM_M)
|
||||
{
|
||||
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, (unsigned)nTarget );
|
||||
sprintf(line_.sTarget, "%02X", (unsigned)nTarget);
|
||||
|
||||
if (iOpmode == AM_M)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
|
||||
line_.nImmediate = (BYTE)nTarget;
|
||||
unsigned _char = FormatCharTxtCtrl(FormatCharTxtHigh(line_.nImmediate, NULL), NULL);
|
||||
|
||||
sprintf(line_.sImmediate, "%c", _char);
|
||||
#if OLD_CONSOLE_COLOR
|
||||
if (ConsoleColorIsEscapeMeta(_char))
|
||||
sprintf(line_.sImmediate, "%c%c", _char, _char);
|
||||
else
|
||||
sprintf(line_.sImmediate, "%c", _char);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprintf(line_.sAddress, "%04X", nBaseAddress);
|
||||
|
||||
// Opcode Bytes
|
||||
FormatOpcodeBytes(nBaseAddress, line_);
|
||||
|
||||
// Data Disassembler
|
||||
if (pData)
|
||||
{
|
||||
line_.iNoptype = pData->eElementType;
|
||||
line_.iNopcode = pData->iDirective;
|
||||
strcpy(line_.sMnemonic, g_aAssemblerDirectives[line_.iNopcode].m_pMnemonic);
|
||||
|
||||
FormatNopcodeBytes(nBaseAddress, line_);
|
||||
}
|
||||
else { // Regular 6502/65C02 opcode -> mnemonic
|
||||
strcpy(line_.sMnemonic, g_aOpcodes[line_.iOpcode].sMnemonic);
|
||||
}
|
||||
|
||||
int nSpaces = strlen(line_.sOpCodes);
|
||||
while (nSpaces < (int)nMinBytesLen)
|
||||
{
|
||||
strcat(line_.sOpCodes, " ");
|
||||
nSpaces++;
|
||||
}
|
||||
|
||||
return bDisasmFormatFlags;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
{
|
||||
int nOpbyte = line_.nOpbyte;
|
||||
|
||||
char* pDst = line_.sOpCodes;
|
||||
int nMaxOpBytes = nOpbyte;
|
||||
if (nMaxOpBytes > MAX_OPCODES) // 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
|
||||
nMaxOpBytes = MAX_OPCODES;
|
||||
|
||||
for (int iByte = 0; iByte < nMaxOpBytes; iByte++)
|
||||
{
|
||||
BYTE nMem = mem[(nBaseAddress + iByte) & 0xFFFF];
|
||||
sprintf(pDst, "%02X", nMem); // sBytes+strlen(sBytes)
|
||||
pDst += 2;
|
||||
|
||||
// TODO: If Disassembly_IsDataAddress() don't show spaces...
|
||||
if (g_bConfigDisasmOpcodeSpaces)
|
||||
{
|
||||
strcat(pDst, " ");
|
||||
pDst++; // 2.5.3.3 fix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Formats Target string with bytes,words, string, etc...
|
||||
//===========================================================================
|
||||
void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_)
|
||||
{
|
||||
char* pDst = line_.sTarget;
|
||||
const char* pSrc = 0;
|
||||
DWORD nStartAddress = line_.pDisasmData->nStartAddress;
|
||||
DWORD nEndAddress = line_.pDisasmData->nEndAddress;
|
||||
// int nDataLen = nEndAddress - nStartAddress + 1 ;
|
||||
int nDisplayLen = nEndAddress - nBaseAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
|
||||
int len = nDisplayLen;
|
||||
|
||||
for (int iByte = 0; iByte < line_.nOpbyte; )
|
||||
{
|
||||
BYTE nTarget8 = *(LPBYTE)(mem + nBaseAddress + iByte);
|
||||
WORD nTarget16 = *(LPWORD)(mem + nBaseAddress + iByte);
|
||||
|
||||
switch (line_.iNoptype)
|
||||
{
|
||||
case NOP_BYTE_1:
|
||||
case NOP_BYTE_2:
|
||||
case NOP_BYTE_4:
|
||||
case NOP_BYTE_8:
|
||||
sprintf(pDst, "%02X", nTarget8); // sBytes+strlen(sBytes)
|
||||
pDst += 2;
|
||||
iByte++;
|
||||
if (line_.iNoptype == NOP_BYTE_1)
|
||||
if (iByte < line_.nOpbyte)
|
||||
{
|
||||
*pDst++ = ',';
|
||||
}
|
||||
break;
|
||||
case NOP_WORD_1:
|
||||
case NOP_WORD_2:
|
||||
case NOP_WORD_4:
|
||||
sprintf(pDst, "%04X", nTarget16); // sBytes+strlen(sBytes)
|
||||
pDst += 4;
|
||||
iByte += 2;
|
||||
if (iByte < line_.nOpbyte)
|
||||
{
|
||||
*pDst++ = ',';
|
||||
}
|
||||
break;
|
||||
case NOP_ADDRESS:
|
||||
// Nothing to do, already handled :-)
|
||||
iByte += 2;
|
||||
break;
|
||||
case NOP_STRING_APPLESOFT:
|
||||
iByte = line_.nOpbyte;
|
||||
strncpy(pDst, (const char*)(mem + nBaseAddress), iByte);
|
||||
pDst += iByte;
|
||||
*pDst = 0;
|
||||
case NOP_STRING_APPLE:
|
||||
iByte = line_.nOpbyte; // handle all bytes of text
|
||||
pSrc = (const char*)mem + nStartAddress;
|
||||
|
||||
if (len > (MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
|
||||
{
|
||||
if (len > MAX_IMMEDIATE_LEN) // no; need extra characters for ellipsis?
|
||||
len = (MAX_IMMEDIATE_LEN - 3); // ellipsis = true
|
||||
|
||||
// DISPLAY: text_longer_18...
|
||||
FormatCharCopy(pDst, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
|
||||
if (nDisplayLen > len) // ellipsis
|
||||
{
|
||||
*pDst++ = '.';
|
||||
*pDst++ = '.';
|
||||
*pDst++ = '.';
|
||||
}
|
||||
}
|
||||
else { // DISPLAY: "max_18_char"
|
||||
*pDst++ = '"';
|
||||
pDst = FormatCharCopy(pDst, pSrc, len); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
*pDst++ = '"';
|
||||
}
|
||||
|
||||
*pDst = 0;
|
||||
break;
|
||||
default:
|
||||
#if _DEBUG // Unhandled data disassembly!
|
||||
int* FATAL = 0;
|
||||
*FATAL = 0xDEADC0DE;
|
||||
#endif
|
||||
iByte++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly, const int nBufferSize)
|
||||
{
|
||||
//> Address Seperator Opcodes Label Mnemonic Target [Immediate] [Branch]
|
||||
//
|
||||
// Data Disassembler
|
||||
// Label Directive [Immediate]
|
||||
const char* pMnemonic = g_aOpcodes[line.iOpcode].sMnemonic;
|
||||
|
||||
sprintf(sDisassembly, "%s:%s %s "
|
||||
, line.sAddress
|
||||
, line.sOpCodes
|
||||
, pMnemonic
|
||||
);
|
||||
|
||||
/*
|
||||
if (line.bTargetIndexed || line.bTargetIndirect)
|
||||
{
|
||||
strcat( sDisassembly, "(" );
|
||||
}
|
||||
|
||||
if (line.bTargetImmediate)
|
||||
strcat( sDisassembly, "#$" );
|
||||
|
||||
if (line.bTargetValue)
|
||||
strcat( sDisassembly, line.sTarget );
|
||||
|
||||
if (line.bTargetIndirect)
|
||||
{
|
||||
if (line.bTargetX)
|
||||
strcat( sDisassembly, ", X" );
|
||||
if (line.bTargetY)
|
||||
strcat( sDisassembly, ", Y" );
|
||||
}
|
||||
|
||||
if (line.bTargetIndexed || line.bTargetIndirect)
|
||||
{
|
||||
strcat( sDisassembly, ")" );
|
||||
}
|
||||
|
||||
if (line.bTargetIndirect)
|
||||
{
|
||||
if (line.bTargetY)
|
||||
strcat( sDisassembly, ", Y" );
|
||||
}
|
||||
*/
|
||||
char sTarget[32];
|
||||
|
||||
if (line.bTargetValue || line.bTargetRelative || line.bTargetImmediate)
|
||||
{
|
||||
if (line.bTargetRelative)
|
||||
strcpy(sTarget, line.sTargetValue);
|
||||
else
|
||||
if (line.bTargetImmediate)
|
||||
{
|
||||
strcat(sDisassembly, "#");
|
||||
strncpy(sTarget, line.sTarget, sizeof(sTarget));
|
||||
sTarget[sizeof(sTarget) - 1] = 0;
|
||||
}
|
||||
else
|
||||
sprintf(sTarget, g_aOpmodes[line.iOpmode].m_sFormat, line.nTarget);
|
||||
|
||||
strcat(sDisassembly, "$");
|
||||
strcat(sDisassembly, sTarget);
|
||||
}
|
||||
}
|
||||
|
||||
// Given an Address, and Line to display it on
|
||||
// Calculate the address of the top and bottom lines
|
||||
// @param bUpdateCur
|
||||
// true = Update Cur based on Top
|
||||
// false = Update Top & Bot based on Cur
|
||||
//===========================================================================
|
||||
void DisasmCalcTopFromCurAddress(bool bUpdateTop)
|
||||
{
|
||||
int nLen = ((g_nDisasmWinHeight - g_nDisasmCurLine) * 3); // max 3 opcodes/instruction, is our search window
|
||||
|
||||
// Look for a start address that when disassembled,
|
||||
// will have the cursor on the specified line and address
|
||||
int iTop = g_nDisasmCurAddress - nLen;
|
||||
int iCur = g_nDisasmCurAddress;
|
||||
|
||||
g_bDisasmCurBad = false;
|
||||
|
||||
bool bFound = false;
|
||||
while (iTop <= iCur)
|
||||
{
|
||||
WORD iAddress = iTop;
|
||||
// int iOpcode;
|
||||
int iOpmode;
|
||||
int nOpbytes;
|
||||
|
||||
for (int iLine = 0; iLine <= nLen; iLine++) // min 1 opcode/instruction
|
||||
{
|
||||
// a.
|
||||
_6502_GetOpmodeOpbyte(iAddress, iOpmode, nOpbytes);
|
||||
// b.
|
||||
// _6502_GetOpcodeOpmodeOpbyte( iOpcode, iOpmode, nOpbytes );
|
||||
|
||||
if (iLine == g_nDisasmCurLine) // && (iAddress == g_nDisasmCurAddress))
|
||||
{
|
||||
if (iAddress == g_nDisasmCurAddress)
|
||||
// b.
|
||||
// && (iOpmode != AM_1) &&
|
||||
// && (iOpmode != AM_2) &&
|
||||
// && (iOpmode != AM_3) &&
|
||||
// && _6502_IsOpcodeValid( iOpcode))
|
||||
{
|
||||
g_nDisasmTopAddress = iTop;
|
||||
bFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// .20 Fixed: DisasmCalcTopFromCurAddress()
|
||||
//if ((eMode >= AM_1) && (eMode <= AM_3))
|
||||
#if 0 // _DEBUG
|
||||
TCHAR sText[CONSOLE_WIDTH];
|
||||
wsprintf(sText, "%04X : %d bytes\n", iAddress, nOpbytes);
|
||||
OutputDebugString(sText);
|
||||
#endif
|
||||
iAddress += nOpbytes;
|
||||
}
|
||||
if (bFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
iTop++;
|
||||
}
|
||||
|
||||
if (!bFound)
|
||||
{
|
||||
// Well, we're up the creek.
|
||||
// There is no (valid) solution!
|
||||
// Basically, there is no address, that when disassembled,
|
||||
// will put our Address on the cursor Line!
|
||||
// So, like typical game programming, when we don't like the solution, change the problem!
|
||||
// if (bUpdateTop)
|
||||
g_nDisasmTopAddress = g_nDisasmCurAddress;
|
||||
|
||||
g_bDisasmCurBad = true; // Bad Disassembler, no opcode for you!
|
||||
|
||||
// We reall should move the cursor line to the top for one instruction.
|
||||
// Moving the cursor line around is not really a good idea, since we're breaking consistency paradigm for the user.
|
||||
// g_nDisasmCurLine = 0;
|
||||
#if 0 // _DEBUG
|
||||
TCHAR sText[CONSOLE_WIDTH * 2];
|
||||
sprintf(sText, TEXT("DisasmCalcTopFromCurAddress()\n"
|
||||
"\tTop: %04X\n"
|
||||
"\tLen: %04X\n"
|
||||
"\tMissed: %04X"),
|
||||
g_nDisasmCurAddress - nLen, nLen, g_nDisasmCurAddress);
|
||||
GetFrame().FrameMessageBox(sText, "ERROR", MB_OK);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
WORD DisasmCalcAddressFromLines(WORD iAddress, int nLines)
|
||||
{
|
||||
while (nLines-- > 0)
|
||||
{
|
||||
int iOpmode;
|
||||
int nOpbytes;
|
||||
_6502_GetOpmodeOpbyte(iAddress, iOpmode, nOpbytes);
|
||||
iAddress += nOpbytes;
|
||||
}
|
||||
return iAddress;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void DisasmCalcCurFromTopAddress()
|
||||
{
|
||||
g_nDisasmCurAddress = DisasmCalcAddressFromLines(g_nDisasmTopAddress, g_nDisasmCurLine);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void DisasmCalcBotFromTopAddress()
|
||||
{
|
||||
g_nDisasmBotAddress = DisasmCalcAddressFromLines(g_nDisasmTopAddress, g_nDisasmWinHeight);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void DisasmCalcTopBotAddress()
|
||||
{
|
||||
DisasmCalcTopFromCurAddress();
|
||||
DisasmCalcBotFromTopAddress();
|
||||
}
|
26
source/Debugger/Debugger_Disassembler.h
Normal file
26
source/Debugger/Debugger_Disassembler.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
int GetDisassemblyLine(const WORD nOffset, DisasmLine_t& line_);
|
||||
// , int iOpcode, int iOpmode, int nOpbytes
|
||||
// char *sAddress_, char *sOpCodes_,
|
||||
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_, char *sTargetValue_,
|
||||
// char * sImmediate_, char & nImmediate_, char *sBranch_ );
|
||||
void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly_, const int nBufferSize);
|
||||
void FormatOpcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
|
||||
void FormatNopcodeBytes(WORD nBaseAddress, DisasmLine_t& line_);
|
||||
|
||||
const char* FormatAddress(WORD nAddress, int nBytes);
|
||||
char* FormatCharCopy(char* pDst, const char* pSrc, const int nLen);
|
||||
|
||||
char FormatCharTxtAsci(const BYTE b, bool* pWasAsci_ = NULL);
|
||||
char FormatCharTxtCtrl(const BYTE b, bool* pWasCtrl_ = NULL);
|
||||
char FormatCharTxtHigh(const BYTE b, bool* pWasHi_ = NULL);
|
||||
char FormatChar4Font(const BYTE b, bool* pWasHi_, bool* pWasLo_);
|
||||
|
||||
void GetTargets_IgnoreDirectJSRJMP(const BYTE iOpcode, int& nTargetPointer);
|
||||
|
||||
void DisasmCalcTopFromCurAddress(bool bUpdateTop = true);
|
||||
void DisasmCalcCurFromTopAddress();
|
||||
void DisasmCalcBotFromTopAddress();
|
||||
void DisasmCalcTopBotAddress();
|
||||
WORD DisasmCalcAddressFromLines(WORD iAddress, int nLines);
|
|
@ -31,6 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
|
||||
#include "Debug.h"
|
||||
#include "Debugger_Display.h"
|
||||
#include "Debugger_Disassembler.h"
|
||||
|
||||
#include "../Core.h"
|
||||
#include "../Interface.h"
|
||||
|
@ -115,40 +116,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||
RGB( 80, 192, 255 ) // Lite Blue
|
||||
};
|
||||
|
||||
// Disassembly
|
||||
/*
|
||||
// Thought about moving MouseText to another location, say high bit, 'A' + 0x80
|
||||
// But would like to keep compatibility with existing CHARSET40
|
||||
// Since we should be able to display all apple chars 0x00 .. 0xFF with minimal processing
|
||||
// Use CONSOLE_COLOR_ESCAPE_CHAR to shift to mouse text
|
||||
* Apple Font
|
||||
K Mouse Text Up Arror
|
||||
H Mouse Text Left Arrow
|
||||
J Mouse Text Down Arrow
|
||||
* Wingdings
|
||||
\xE1 Up Arrow
|
||||
\xE2 Down Arrow
|
||||
* Webdings // M$ Font
|
||||
\x35 Up Arrow
|
||||
\x33 Left Arrow (\x71 recycl is too small to make out details)
|
||||
\x36 Down Arrow
|
||||
* Symols
|
||||
\xAD Up Arrow
|
||||
\xAF Down Arrow
|
||||
* ???
|
||||
\x18 Up
|
||||
\x19 Down
|
||||
*/
|
||||
#if USE_APPLE_FONT
|
||||
const char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x8B" }; // "`K" 0x4B
|
||||
const char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x88" }; // "`H" 0x48
|
||||
const char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x8A" }; // "`J" 0x4A
|
||||
#else
|
||||
const char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x35" };
|
||||
const char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x33" };
|
||||
char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x36" };
|
||||
#endif
|
||||
|
||||
// Drawing
|
||||
// Width
|
||||
const int DISPLAY_WIDTH = 560;
|
||||
|
@ -229,12 +196,6 @@ static char ColorizeSpecialChar( char * sText, BYTE nData, const MemoryView_e iV
|
|||
|
||||
void DrawWindowBottom ( Update_t bUpdate, int iWindow );
|
||||
|
||||
char* FormatCharCopy( char *pDst, const char *pSrc, const int nLen );
|
||||
char FormatCharTxtAsci( const BYTE b, bool * pWasAsci_ = NULL );
|
||||
char FormatCharTxtCtrl( const BYTE b, bool * pWasCtrl_ = NULL );
|
||||
char FormatCharTxtHigh( const BYTE b, bool *pWasHi_ = NULL );
|
||||
char FormatChar4Font ( const BYTE b, bool *pWasHi_, bool *pWasLo_ );
|
||||
|
||||
void DrawRegister(int line, LPCTSTR name, int bytes, WORD value, int iSource = 0);
|
||||
|
||||
|
||||
|
@ -947,78 +908,6 @@ int PrintTextCursorY ( const char * pText, RECT & rRect )
|
|||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
char* FormatCharCopy( char *pDst, const char *pSrc, const int nLen )
|
||||
{
|
||||
for( int i = 0; i < nLen; i++ )
|
||||
*pDst++ = FormatCharTxtCtrl( *pSrc++ );
|
||||
return pDst;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char FormatCharTxtAsci ( const BYTE b, bool * pWasAsci_ )
|
||||
{
|
||||
if (pWasAsci_)
|
||||
*pWasAsci_ = false;
|
||||
|
||||
char c = (b & 0x7F);
|
||||
if (b <= 0x7F)
|
||||
{
|
||||
if (pWasAsci_)
|
||||
{
|
||||
*pWasAsci_ = true;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
// Note: FormatCharTxtCtrl() and RemapChar()
|
||||
//===========================================================================
|
||||
char FormatCharTxtCtrl ( const BYTE b, bool * pWasCtrl_ )
|
||||
{
|
||||
if (pWasCtrl_)
|
||||
*pWasCtrl_ = false;
|
||||
|
||||
char c = (b & 0x7F); // .32 Changed: Lo now maps High Ascii to printable chars. i.e. ML1 D0D0
|
||||
if (b < 0x20) // SPACE
|
||||
{
|
||||
if (pWasCtrl_)
|
||||
{
|
||||
*pWasCtrl_ = true;
|
||||
}
|
||||
c = b + '@'; // map ctrl chars to visible
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
char FormatCharTxtHigh ( const BYTE b, bool *pWasHi_ )
|
||||
{
|
||||
if (pWasHi_)
|
||||
*pWasHi_ = false;
|
||||
|
||||
char c = b;
|
||||
if (b > 0x7F)
|
||||
{
|
||||
if (pWasHi_)
|
||||
{
|
||||
*pWasHi_ = true;
|
||||
}
|
||||
c = (b & 0x7F);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
char FormatChar4Font ( const BYTE b, bool *pWasHi_, bool *pWasLo_ )
|
||||
{
|
||||
// Most Windows Fonts don't have (printable) glyphs for control chars
|
||||
BYTE b1 = FormatCharTxtHigh( b , pWasHi_ );
|
||||
BYTE b2 = FormatCharTxtCtrl( b1, pWasLo_ );
|
||||
return b2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1429,488 +1318,6 @@ void DrawConsoleInput ()
|
|||
}
|
||||
|
||||
|
||||
// Disassembly ____________________________________________________________________________________
|
||||
|
||||
void GetTargets_IgnoreDirectJSRJMP(const BYTE iOpcode, int& nTargetPointer)
|
||||
{
|
||||
if (iOpcode == OPCODE_JSR || iOpcode == OPCODE_JMP_A)
|
||||
nTargetPointer = NO_6502_TARGET;
|
||||
}
|
||||
|
||||
// Get the data needed to disassemble one line of opcodes. Fills in the DisasmLine info.
|
||||
// Disassembly formatting flags returned
|
||||
// @parama sTargetValue_ indirect/indexed final value
|
||||
//===========================================================================
|
||||
int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
|
||||
// char *sAddress_, char *sOpCodes_,
|
||||
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_,
|
||||
// char *sTargetPointer_, char *sTargetValue_,
|
||||
// char *sImmediate_, char & nImmediate_, char *sBranch_ )
|
||||
{
|
||||
line_.Clear();
|
||||
|
||||
int iOpcode;
|
||||
int iOpmode;
|
||||
int nOpbyte;
|
||||
|
||||
iOpcode = _6502_GetOpmodeOpbyte( nBaseAddress, iOpmode, nOpbyte, &line_.pDisasmData );
|
||||
const DisasmData_t* pData = line_.pDisasmData; // Disassembly_IsDataAddress( nBaseAddress );
|
||||
|
||||
line_.iOpcode = iOpcode;
|
||||
line_.iOpmode = iOpmode;
|
||||
line_.nOpbyte = nOpbyte;
|
||||
|
||||
#if _DEBUG
|
||||
// if (iLine != 41)
|
||||
// return nOpbytes;
|
||||
#endif
|
||||
|
||||
if (iOpmode == AM_M)
|
||||
line_.bTargetImmediate = true;
|
||||
|
||||
if ((iOpmode >= AM_IZX) && (iOpmode <= AM_NA))
|
||||
line_.bTargetIndirect = true; // ()
|
||||
|
||||
if ((iOpmode >= AM_IZX) && (iOpmode <= AM_NZY))
|
||||
line_.bTargetIndexed = true; // ()
|
||||
|
||||
if (((iOpmode >= AM_A) && (iOpmode <= AM_ZY)) || line_.bTargetIndirect)
|
||||
line_.bTargetValue = true; // #$
|
||||
|
||||
if ((iOpmode == AM_AX) || (iOpmode == AM_ZX) || (iOpmode == AM_IZX) || (iOpmode == AM_IAX))
|
||||
line_.bTargetX = true; // ,X
|
||||
|
||||
if ((iOpmode == AM_AY) || (iOpmode == AM_ZY) || (iOpmode == AM_NZY))
|
||||
line_.bTargetY = true; // ,Y
|
||||
|
||||
unsigned int nMinBytesLen = (MAX_OPCODES * (2 + g_bConfigDisasmOpcodeSpaces)); // 2 char for byte (or 3 with space)
|
||||
|
||||
int bDisasmFormatFlags = 0;
|
||||
|
||||
// Composite string that has the symbol or target nAddress
|
||||
WORD nTarget = 0;
|
||||
|
||||
if ((iOpmode != AM_IMPLIED) &&
|
||||
(iOpmode != AM_1) &&
|
||||
(iOpmode != AM_2) &&
|
||||
(iOpmode != AM_3))
|
||||
{
|
||||
// Assume target address starts after the opcode ...
|
||||
// BUT in the Assembler Directive / Data Disassembler case for define addr/word
|
||||
// the opcode literally IS the target address!
|
||||
if( pData )
|
||||
{
|
||||
nTarget = pData->nTargetAddress;
|
||||
} else {
|
||||
nTarget = mem[(nBaseAddress+1)&0xFFFF] | (mem[(nBaseAddress+2)&0xFFFF]<<8);
|
||||
if (nOpbyte == 2)
|
||||
nTarget &= 0xFF;
|
||||
}
|
||||
|
||||
if (iOpmode == AM_R) // Relative
|
||||
{
|
||||
line_.bTargetRelative = true;
|
||||
|
||||
nTarget = nBaseAddress+2+(int)(signed char)nTarget;
|
||||
|
||||
line_.nTarget = nTarget;
|
||||
sprintf( line_.sTargetValue, "%04X", nTarget & 0xFFFF );
|
||||
|
||||
// Always show branch indicators
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_BRANCH;
|
||||
|
||||
if (nTarget < nBaseAddress)
|
||||
{
|
||||
sprintf( line_.sBranch, "%s", g_sConfigBranchIndicatorUp[ g_iConfigDisasmBranchType ] );
|
||||
}
|
||||
else
|
||||
if (nTarget > nBaseAddress)
|
||||
{
|
||||
sprintf( line_.sBranch, "%s", g_sConfigBranchIndicatorDown[ g_iConfigDisasmBranchType ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf( line_.sBranch, "%s", g_sConfigBranchIndicatorEqual[ g_iConfigDisasmBranchType ] );
|
||||
}
|
||||
}
|
||||
// intentional re-test AM_R ...
|
||||
|
||||
// if ((iOpmode >= AM_A) && (iOpmode <= AM_NA))
|
||||
if ((iOpmode == AM_A ) || // Absolute
|
||||
(iOpmode == AM_Z ) || // Zeropage
|
||||
(iOpmode == AM_AX ) || // Absolute, X
|
||||
(iOpmode == AM_AY ) || // Absolute, Y
|
||||
(iOpmode == AM_ZX ) || // Zeropage, X
|
||||
(iOpmode == AM_ZY ) || // Zeropage, Y
|
||||
(iOpmode == AM_R ) || // Relative
|
||||
(iOpmode == AM_IZX) || // Indexed (Zeropage Indirect, X)
|
||||
(iOpmode == AM_IAX) || // Indexed (Absolute Indirect, X)
|
||||
(iOpmode == AM_NZY) || // Indirect (Zeropage) Index, Y
|
||||
(iOpmode == AM_NZ ) || // Indirect (Zeropage)
|
||||
(iOpmode == AM_NA )) //(Indirect Absolute)
|
||||
{
|
||||
line_.nTarget = nTarget;
|
||||
|
||||
const char* pTarget = NULL;
|
||||
const char* pSymbol = 0;
|
||||
|
||||
pSymbol = FindSymbolFromAddress( nTarget );
|
||||
|
||||
// Data Assembler
|
||||
if (pData && (!pData->bSymbolLookup))
|
||||
pSymbol = 0;
|
||||
|
||||
// Try exact match first
|
||||
if (pSymbol)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
||||
pTarget = pSymbol;
|
||||
}
|
||||
|
||||
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
|
||||
{
|
||||
pSymbol = FindSymbolFromAddress( nTarget - 1 );
|
||||
if (pSymbol)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_OFFSET;
|
||||
pTarget = pSymbol;
|
||||
line_.nTargetOffset = +1; // U FA82 LDA $3F1 BREAK-1
|
||||
}
|
||||
}
|
||||
|
||||
// Old Offset search: (Search +1 First) nTarget-1, (Search -1 Second) nTarget+1
|
||||
// Problem: U D038 shows as A.TRACE+1
|
||||
// New Offset search: (Search -1 First) nTarget+1, (Search +1 Second) nTarget+1
|
||||
// Problem: U D834, D87E shows as P.MUL-1, instead of P.ADD+1
|
||||
// 2.6.2.31 Fixed: address table was bailing on first possible match. U D000 -> da STOP+1, instead of END-1
|
||||
// 2.7.0.0: Try to match nTarget-1, nTarget+1, AND if we have both matches
|
||||
// Then we need to decide which one to show. If we have pData then pick this one.
|
||||
// TODO: Do we need to let the user decide which one they want searched first?
|
||||
// nFirstTarget = g_bDebugConfig_DisasmMatchSymbolOffsetMinus1First ? nTarget-1 : nTarget+1;
|
||||
// nSecondTarget = g_bDebugConfig_DisasmMatchSymbolOffsetMinus1First ? nTarget+1 : nTarget-1;
|
||||
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL) || pData)
|
||||
{
|
||||
pSymbol = FindSymbolFromAddress( nTarget + 1 );
|
||||
if (pSymbol)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_OFFSET;
|
||||
pTarget = pSymbol;
|
||||
line_.nTargetOffset = -1; // U FA82 LDA $3F3 BREAK+1
|
||||
}
|
||||
}
|
||||
|
||||
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
|
||||
{
|
||||
pTarget = FormatAddress( nTarget, (iOpmode != AM_R) ? nOpbyte : 3 ); // GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
|
||||
}
|
||||
|
||||
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
|
||||
{
|
||||
int nAbsTargetOffset = (line_.nTargetOffset > 0) ? line_.nTargetOffset : - line_.nTargetOffset;
|
||||
sprintf( line_.sTargetOffset, "%d", nAbsTargetOffset );
|
||||
}
|
||||
sprintf( line_.sTarget, "%s", pTarget );
|
||||
|
||||
|
||||
// Indirect / Indexed
|
||||
int nTargetPartial;
|
||||
int nTargetPartial2;
|
||||
int nTargetPointer;
|
||||
WORD nTargetValue = 0; // de-ref
|
||||
_6502_GetTargets( nBaseAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, NULL );
|
||||
GetTargets_IgnoreDirectJSRJMP(iOpcode, nTargetPointer); // For *direct* JSR/JMP, don't show 'addr16:byte char'
|
||||
|
||||
if (nTargetPointer != NO_6502_TARGET)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_POINTER;
|
||||
|
||||
nTargetValue = *(mem + nTargetPointer) | (*(mem + ((nTargetPointer + 1) & 0xffff)) << 8);
|
||||
|
||||
// if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
|
||||
// sprintf( sTargetValue_, "%04X", nTargetValue ); // & 0xFFFF
|
||||
|
||||
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
|
||||
sprintf( line_.sTargetPointer, "%04X", nTargetPointer & 0xFFFF );
|
||||
|
||||
if (iOpcode != OPCODE_JMP_NA && iOpcode != OPCODE_JMP_IAX)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_VALUE;
|
||||
if (g_iConfigDisasmTargets & DISASM_TARGET_VAL)
|
||||
sprintf( line_.sTargetValue, "%02X", nTargetValue & 0xFF );
|
||||
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
|
||||
line_.nImmediate = (BYTE) nTargetValue;
|
||||
|
||||
unsigned _char = FormatCharTxtCtrl( FormatCharTxtHigh( line_.nImmediate, NULL ), NULL );
|
||||
sprintf( line_.sImmediate, "%c", _char );
|
||||
|
||||
// if (ConsoleColorIsEscapeMeta( nImmediate_ ))
|
||||
#if OLD_CONSOLE_COLOR
|
||||
if (ConsoleColorIsEscapeMeta( _char ))
|
||||
sprintf( line_.sImmediate, "%c%c", _char, _char );
|
||||
else
|
||||
sprintf( line_.sImmediate, "%c", _char );
|
||||
#endif
|
||||
}
|
||||
|
||||
// if (iOpmode == AM_NA ) // Indirect Absolute
|
||||
// sprintf( sTargetValue_, "%04X", nTargetPointer & 0xFFFF );
|
||||
// else
|
||||
// // sprintf( sTargetValue_, "%02X", nTargetValue & 0xFF );
|
||||
// sprintf( sTargetValue_, "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
|
||||
}
|
||||
}
|
||||
else
|
||||
if (iOpmode == AM_M)
|
||||
{
|
||||
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, (unsigned)nTarget );
|
||||
sprintf( line_.sTarget, "%02X", (unsigned)nTarget );
|
||||
|
||||
if (iOpmode == AM_M)
|
||||
{
|
||||
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
|
||||
line_.nImmediate = (BYTE) nTarget;
|
||||
unsigned _char = FormatCharTxtCtrl( FormatCharTxtHigh( line_.nImmediate, NULL ), NULL );
|
||||
|
||||
sprintf( line_.sImmediate, "%c", _char );
|
||||
#if OLD_CONSOLE_COLOR
|
||||
if (ConsoleColorIsEscapeMeta( _char ))
|
||||
sprintf( line_.sImmediate, "%c%c", _char, _char );
|
||||
else
|
||||
sprintf( line_.sImmediate, "%c", _char );
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sprintf( line_.sAddress, "%04X", nBaseAddress );
|
||||
|
||||
// Opcode Bytes
|
||||
FormatOpcodeBytes( nBaseAddress, line_ );
|
||||
|
||||
// Data Disassembler
|
||||
if( pData )
|
||||
{
|
||||
line_.iNoptype = pData->eElementType;
|
||||
line_.iNopcode = pData->iDirective;
|
||||
strcpy( line_.sMnemonic, g_aAssemblerDirectives[ line_.iNopcode ].m_pMnemonic );
|
||||
|
||||
FormatNopcodeBytes( nBaseAddress, line_ );
|
||||
} else { // Regular 6502/65C02 opcode -> mnemonic
|
||||
strcpy( line_.sMnemonic, g_aOpcodes[ line_.iOpcode ].sMnemonic );
|
||||
}
|
||||
|
||||
int nSpaces = strlen( line_.sOpCodes );
|
||||
while (nSpaces < (int)nMinBytesLen)
|
||||
{
|
||||
strcat( line_.sOpCodes, " " );
|
||||
nSpaces++;
|
||||
}
|
||||
|
||||
return bDisasmFormatFlags;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
const char* FormatAddress( WORD nAddress, int nBytes )
|
||||
{
|
||||
// There is no symbol for this nAddress
|
||||
static TCHAR sSymbol[8] = TEXT("");
|
||||
switch (nBytes)
|
||||
{
|
||||
case 2: wsprintf(sSymbol,TEXT("$%02X"),(unsigned)nAddress); break;
|
||||
case 3: wsprintf(sSymbol,TEXT("$%04X"),(unsigned)nAddress); break;
|
||||
// TODO: FIXME: Can we get called with nBytes == 16 ??
|
||||
default: sSymbol[0] = 0; break; // clear since is static
|
||||
}
|
||||
return sSymbol;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
void FormatOpcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ )
|
||||
{
|
||||
int nOpbyte = line_.nOpbyte;
|
||||
|
||||
char *pDst = line_.sOpCodes;
|
||||
int nMaxOpBytes = nOpbyte;
|
||||
if ( nMaxOpBytes > MAX_OPCODES) // 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
|
||||
nMaxOpBytes = MAX_OPCODES;
|
||||
|
||||
for( int iByte = 0; iByte < nMaxOpBytes; iByte++ )
|
||||
{
|
||||
BYTE nMem = mem[(nBaseAddress+iByte)&0xFFFF];
|
||||
sprintf( pDst, "%02X", nMem ); // sBytes+strlen(sBytes)
|
||||
pDst += 2;
|
||||
|
||||
// TODO: If Disassembly_IsDataAddress() don't show spaces...
|
||||
if (g_bConfigDisasmOpcodeSpaces)
|
||||
{
|
||||
strcat( pDst, " " );
|
||||
pDst++; // 2.5.3.3 fix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Formats Target string with bytes,words, string, etc...
|
||||
//===========================================================================
|
||||
void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ )
|
||||
{
|
||||
char *pDst = line_.sTarget;
|
||||
const char *pSrc = 0;
|
||||
DWORD nStartAddress = line_.pDisasmData->nStartAddress;
|
||||
DWORD nEndAddress = line_.pDisasmData->nEndAddress ;
|
||||
// int nDataLen = nEndAddress - nStartAddress + 1 ;
|
||||
int nDisplayLen = nEndAddress - nBaseAddress + 1 ; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes()
|
||||
int len = nDisplayLen;
|
||||
|
||||
for( int iByte = 0; iByte < line_.nOpbyte; )
|
||||
{
|
||||
BYTE nTarget8 = *(LPBYTE)(mem + nBaseAddress + iByte);
|
||||
WORD nTarget16 = *(LPWORD)(mem + nBaseAddress + iByte);
|
||||
|
||||
switch( line_.iNoptype )
|
||||
{
|
||||
case NOP_BYTE_1:
|
||||
case NOP_BYTE_2:
|
||||
case NOP_BYTE_4:
|
||||
case NOP_BYTE_8:
|
||||
sprintf( pDst, "%02X", nTarget8 ); // sBytes+strlen(sBytes)
|
||||
pDst += 2;
|
||||
iByte++;
|
||||
if( line_.iNoptype == NOP_BYTE_1)
|
||||
if( iByte < line_.nOpbyte )
|
||||
{
|
||||
*pDst++ = ',';
|
||||
}
|
||||
break;
|
||||
case NOP_WORD_1:
|
||||
case NOP_WORD_2:
|
||||
case NOP_WORD_4:
|
||||
sprintf( pDst, "%04X", nTarget16 ); // sBytes+strlen(sBytes)
|
||||
pDst += 4;
|
||||
iByte+= 2;
|
||||
if( iByte < line_.nOpbyte )
|
||||
{
|
||||
*pDst++ = ',';
|
||||
}
|
||||
break;
|
||||
case NOP_ADDRESS:
|
||||
// Nothing to do, already handled :-)
|
||||
iByte += 2;
|
||||
break;
|
||||
case NOP_STRING_APPLESOFT:
|
||||
iByte = line_.nOpbyte;
|
||||
strncpy( pDst, (const char*)(mem + nBaseAddress), iByte );
|
||||
pDst += iByte;
|
||||
*pDst = 0;
|
||||
case NOP_STRING_APPLE:
|
||||
iByte = line_.nOpbyte; // handle all bytes of text
|
||||
pSrc = (const char*)mem + nStartAddress;
|
||||
|
||||
if (len > (MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
|
||||
{
|
||||
if (len > MAX_IMMEDIATE_LEN) // no; need extra characters for ellipsis?
|
||||
len = (MAX_IMMEDIATE_LEN - 3); // ellipsis = true
|
||||
|
||||
// DISPLAY: text_longer_18...
|
||||
FormatCharCopy( pDst, pSrc, len ); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
|
||||
if( nDisplayLen > len ) // ellipsis
|
||||
{
|
||||
*pDst++ = '.';
|
||||
*pDst++ = '.';
|
||||
*pDst++ = '.';
|
||||
}
|
||||
} else { // DISPLAY: "max_18_char"
|
||||
*pDst++ = '"';
|
||||
pDst = FormatCharCopy( pDst, pSrc, len ); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
||||
*pDst++ = '"';
|
||||
}
|
||||
|
||||
*pDst = 0;
|
||||
break;
|
||||
default:
|
||||
#if _DEBUG // Unhandled data disassembly!
|
||||
int *FATAL = 0;
|
||||
*FATAL = 0xDEADC0DE;
|
||||
#endif
|
||||
iByte++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void FormatDisassemblyLine( const DisasmLine_t & line, char * sDisassembly, const int nBufferSize )
|
||||
{
|
||||
//> Address Seperator Opcodes Label Mnemonic Target [Immediate] [Branch]
|
||||
//
|
||||
// Data Disassembler
|
||||
// Label Directive [Immediate]
|
||||
const char * pMnemonic = g_aOpcodes[ line.iOpcode ].sMnemonic;
|
||||
|
||||
sprintf( sDisassembly, "%s:%s %s "
|
||||
, line.sAddress
|
||||
, line.sOpCodes
|
||||
, pMnemonic
|
||||
);
|
||||
|
||||
/*
|
||||
if (line.bTargetIndexed || line.bTargetIndirect)
|
||||
{
|
||||
strcat( sDisassembly, "(" );
|
||||
}
|
||||
|
||||
if (line.bTargetImmediate)
|
||||
strcat( sDisassembly, "#$" );
|
||||
|
||||
if (line.bTargetValue)
|
||||
strcat( sDisassembly, line.sTarget );
|
||||
|
||||
if (line.bTargetIndirect)
|
||||
{
|
||||
if (line.bTargetX)
|
||||
strcat( sDisassembly, ", X" );
|
||||
if (line.bTargetY)
|
||||
strcat( sDisassembly, ", Y" );
|
||||
}
|
||||
|
||||
if (line.bTargetIndexed || line.bTargetIndirect)
|
||||
{
|
||||
strcat( sDisassembly, ")" );
|
||||
}
|
||||
|
||||
if (line.bTargetIndirect)
|
||||
{
|
||||
if (line.bTargetY)
|
||||
strcat( sDisassembly, ", Y" );
|
||||
}
|
||||
*/
|
||||
char sTarget[ 32 ];
|
||||
|
||||
if (line.bTargetValue || line.bTargetRelative || line.bTargetImmediate)
|
||||
{
|
||||
if (line.bTargetRelative)
|
||||
strcpy( sTarget, line.sTargetValue );
|
||||
else
|
||||
if (line.bTargetImmediate)
|
||||
{
|
||||
strcat( sDisassembly, "#" );
|
||||
strncpy( sTarget, line.sTarget, sizeof(sTarget) );
|
||||
sTarget[sizeof(sTarget)-1] = 0;
|
||||
}
|
||||
else
|
||||
sprintf( sTarget, g_aOpmodes[ line.iOpmode ].m_sFormat, line.nTarget );
|
||||
|
||||
strcat( sDisassembly, "$" );
|
||||
strcat( sDisassembly, sTarget );
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
||||
{
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
// use the new Debugger Font (Apple Font)
|
||||
#define USE_APPLE_FONT 1
|
||||
|
||||
// Test Colors & Glyphs
|
||||
#define DEBUG_APPLE_FONT 0
|
||||
|
||||
// Win32 Debugger Font
|
||||
|
||||
enum ConsoleFontSize_e
|
||||
|
@ -53,16 +47,6 @@
|
|||
void DrawConsoleLine ( const conchar_t * pText, int y);
|
||||
void DrawConsoleCursor ();
|
||||
|
||||
int GetDisassemblyLine( const WORD nOffset, DisasmLine_t & line_ );
|
||||
// , int iOpcode, int iOpmode, int nOpbytes
|
||||
// char *sAddress_, char *sOpCodes_,
|
||||
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_, char *sTargetValue_,
|
||||
// char * sImmediate_, char & nImmediate_, char *sBranch_ );
|
||||
WORD DrawDisassemblyLine ( int line, const WORD offset );
|
||||
void FormatDisassemblyLine( const DisasmLine_t & line, char *sDisassembly_, const int nBufferSize );
|
||||
void FormatOpcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ );
|
||||
void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ );
|
||||
|
||||
//
|
||||
|
||||
extern HDC GetDebuggerMemDC(void);
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
|
||||
// Variables
|
||||
extern SymbolTable_t g_aSymbols[ NUM_SYMBOL_TABLES ];
|
||||
extern bool g_bSymbolsDisplayMissingFile;
|
||||
|
||||
// Prototypes
|
||||
|
||||
Update_t _CmdSymbolsClear ( SymbolTable_Index_e eSymbolTable );
|
||||
Update_t _CmdSymbolsCommon ( int nArgs, SymbolTable_Index_e eSymbolTable );
|
||||
Update_t _CmdSymbolsListTables (int nArgs, int bSymbolTables );
|
||||
Update_t _CmdSymbolsUpdate ( int nArgs, int bSymbolTables );
|
||||
|
||||
|
@ -15,3 +15,9 @@
|
|||
// SymbolOffset
|
||||
int ParseSymbolTable ( const std::string & pFileName, SymbolTable_Index_e eWhichTableToLoad, int nSymbolOffset = 0 );
|
||||
|
||||
// Symbol Table / Memory
|
||||
bool FindAddressFromSymbol(const char* pSymbol, WORD* pAddress_ = NULL, int* iTable_ = NULL);
|
||||
WORD GetAddressFromSymbol(const char* symbol); // HACK: returns 0 if symbol not found
|
||||
void SymbolUpdate(SymbolTable_Index_e eSymbolTable, const char* pSymbolName, WORD nAddrss, bool bRemoveSymbol, bool bUpdateSymbol);
|
||||
const char* FindSymbolFromAddress(WORD nAdress, int* iTable_ = NULL);
|
||||
const char* GetSymbol(WORD nAddress, int nBytes);
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
// use the new Debugger Font (Apple Font)
|
||||
#define USE_APPLE_FONT 1
|
||||
|
||||
// Test Colors & Glyphs
|
||||
#define DEBUG_APPLE_FONT 0
|
||||
|
||||
// Addressing _____________________________________________________________________________________
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue