2010-12-18 15:04:12 +00:00
/*
AppleWin : An Apple //e emulator for Windows
Copyright ( C ) 1994 - 1996 , Michael O ' Brien
Copyright ( C ) 1999 - 2001 , Oliver Schmidt
Copyright ( C ) 2002 - 2005 , Tom Charlesworth
2014-08-28 18:13:02 +00:00
Copyright ( C ) 2006 - 2014 , Tom Charlesworth , Michael Pohoreski
2010-12-18 15:04:12 +00:00
AppleWin is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
AppleWin is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with AppleWin ; if not , write to the Free Software
Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
/* Description: Debugger Symbol Tables
*
* Author : Copyright ( C ) 2006 - 2010 Michael Pohoreski
*/
2010-06-11 15:38:22 +00:00
# include "StdAfx.h"
2014-08-13 20:30:35 +00:00
# include "Debug.h"
2020-11-26 21:50:06 +00:00
# include "../Windows/AppleWin.h"
# include "../Core.h"
2010-06-11 15:38:22 +00:00
2010-12-18 15:12:49 +00:00
// 2.6.2.13 Added: Can now enable/disable selected symbol table(s) !
// Allow the user to disable/enable symbol tables
// xxx1xxx symbol table is active (are displayed in disassembly window, etc.)
// xxx1xxx symbol table is disabled (not displayed in disassembly window, etc.)
2011-01-30 17:39:19 +00:00
// See: CmdSymbolsListTable(), g_bDisplaySymbolTables
int g_bDisplaySymbolTables = ( ( 1 < < NUM_SYMBOL_TABLES ) - 1 ) & ( ~ ( int ) SYMBOL_TABLE_PRODOS ) ; // default to all symbol tables displayed/active
2010-12-18 15:04:12 +00:00
2010-06-11 15:38:22 +00:00
// Symbols ________________________________________________________________________________________
2021-02-10 21:05:00 +00:00
const char * g_sFileNameSymbols [ NUM_SYMBOL_TABLES ] = {
2011-01-30 17:39:19 +00:00
" APPLE2E.SYM "
, " A2_BASIC.SYM "
, " A2_ASM.SYM "
, " A2_USER1.SYM " // "A2_USER.SYM",
, " A2_USER2.SYM "
, " A2_SRC1.SYM " // "A2_SRC.SYM",
, " A2_SRC2.SYM "
, " A2_DOS33.SYM "
, " A2_PRODOS.SYM "
2010-06-11 15:38:22 +00:00
} ;
2019-09-06 16:34:25 +00:00
std : : string g_sFileNameSymbolsUser ;
2010-06-11 15:38:22 +00:00
2021-02-10 21:05:00 +00:00
const char * g_aSymbolTableNames [ NUM_SYMBOL_TABLES ] =
2010-06-11 15:38:22 +00:00
{
2011-01-30 17:39:19 +00:00
" Main "
, " Basic "
, " Asm " // "Assembly",
, " User1 " // User
, " User2 "
, " Src1 "
, " Src2 "
, " DOS33 "
, " ProDOS "
2010-06-11 15:38:22 +00:00
} ;
bool g_bSymbolsDisplayMissingFile = true ;
SymbolTable_t g_aSymbols [ NUM_SYMBOL_TABLES ] ;
int g_nSymbolsLoaded = 0 ; // on Last Load
// Utils _ ________________________________________________________________________________________
2022-04-17 11:12:40 +00:00
std : : string _CmdSymbolsInfoHeader ( int iTable , int nDisplaySize = 0 ) ;
2022-04-20 14:21:30 +00:00
void _PrintCurrentPath ( ) ;
Update_t _PrintSymbolInvalidTable ( ) ;
2014-11-27 18:01:43 +00:00
// Private ________________________________________________________________________________________
//===========================================================================
void _PrintCurrentPath ( )
{
2019-09-06 16:34:25 +00:00
ConsoleDisplayError ( g_sProgramDir . c_str ( ) ) ;
2014-11-27 18:01:43 +00:00
}
Update_t _PrintSymbolInvalidTable ( )
{
// TODO: display the user specified file name
ConsoleBufferPush ( " Invalid symbol table. " ) ;
2022-04-17 11:12:40 +00:00
ConsolePrintFormat ( " Only " CHC_NUM_DEC " %d " CHC_DEFAULT " symbol tables are supported: "
, NUM_SYMBOL_TABLES
2014-11-27 18:01:43 +00:00
) ;
2022-04-17 11:12:40 +00:00
std : : string sText ;
2014-11-27 18:01:43 +00:00
// Similar to _CmdSymbolsInfoHeader()
2022-03-27 19:48:26 +00:00
for ( int iTable = 0 ; iTable < NUM_SYMBOL_TABLES ; iTable + + )
2014-11-27 18:01:43 +00:00
{
2022-04-17 11:12:40 +00:00
sText + = StrFormat ( CHC_USAGE " %s " CHC_ARG_SEP " %c "
, g_aSymbolTableNames [ iTable ]
2014-11-27 18:01:43 +00:00
, ( iTable ! = ( NUM_SYMBOL_TABLES - 1 ) )
? ' , '
: ' . '
) ;
}
2022-04-17 11:12:40 +00:00
// return ConsoleDisplayError( sText.c_str() );
ConsolePrint ( sText . c_str ( ) ) ;
2014-11-27 18:01:43 +00:00
return ConsoleUpdate ( ) ;
}
// Public _________________________________________________________________________________________
2010-12-18 15:04:12 +00:00
2010-06-11 15:38:22 +00:00
//===========================================================================
2022-04-06 19:36:24 +00:00
std : : string const & GetSymbol ( WORD nAddress , int nBytes , std : : string & sAddressBuf )
2010-06-11 15:38:22 +00:00
{
2022-02-26 17:54:06 +00:00
std : : string const * pSymbol = FindSymbolFromAddress ( nAddress ) ;
2010-06-11 15:38:22 +00:00
if ( pSymbol )
2022-02-26 17:54:06 +00:00
return * pSymbol ;
2010-06-11 15:38:22 +00:00
2022-04-06 19:36:24 +00:00
return sAddressBuf = FormatAddress ( nAddress , nBytes ) ;
2010-06-11 15:38:22 +00:00
}
//===========================================================================
int GetSymbolTableFromCommand ( )
{
return ( g_iCommand - CMD_SYMBOLS_ROM ) ;
}
2022-01-04 17:24:52 +00:00
// @param iTable_ Which symbol table the symbol is in if any. If none will be NUM_SYMBOL_TABLES
2010-06-11 15:38:22 +00:00
//===========================================================================
2022-02-26 17:54:06 +00:00
std : : string const * FindSymbolFromAddress ( WORD nAddress , int * iTable_ )
2010-06-11 15:38:22 +00:00
{
// Bugfix/User feature: User symbols should be searched first
int iTable = NUM_SYMBOL_TABLES ;
2022-01-04 17:24:52 +00:00
if ( iTable_ )
{
* iTable_ = iTable ;
}
2010-06-11 15:38:22 +00:00
while ( iTable - - > 0 )
{
2010-12-18 15:04:12 +00:00
if ( ! g_aSymbols [ iTable ] . size ( ) )
continue ;
if ( ! ( g_bDisplaySymbolTables & ( 1 < < iTable ) ) )
continue ;
2014-08-14 19:29:01 +00:00
std : : map < WORD , std : : string > : : iterator iSymbols = g_aSymbols [ iTable ] . find ( nAddress ) ;
2022-03-27 19:48:26 +00:00
if ( g_aSymbols [ iTable ] . find ( nAddress ) ! = g_aSymbols [ iTable ] . end ( ) )
2010-06-11 15:38:22 +00:00
{
2010-12-18 15:04:12 +00:00
if ( iTable_ )
2010-06-11 15:38:22 +00:00
{
2010-12-18 15:04:12 +00:00
* iTable_ = iTable ;
2010-06-11 15:38:22 +00:00
}
2022-02-26 17:54:06 +00:00
return & iSymbols - > second ;
2010-06-11 15:38:22 +00:00
}
}
2022-02-26 17:54:06 +00:00
return NULL ;
2010-06-11 15:38:22 +00:00
}
//===========================================================================
2010-12-19 16:43:51 +00:00
bool FindAddressFromSymbol ( const char * pSymbol , WORD * pAddress_ , int * iTable_ )
2010-06-11 15:38:22 +00:00
{
// Bugfix/User feature: User symbols should be searched first
for ( int iTable = NUM_SYMBOL_TABLES ; iTable - - > 0 ; )
{
if ( ! g_aSymbols [ iTable ] . size ( ) )
continue ;
2010-12-18 15:04:12 +00:00
if ( ! ( g_bDisplaySymbolTables & ( 1 < < iTable ) ) )
continue ;
2010-06-11 15:38:22 +00:00
SymbolTable_t : : iterator iSymbol = g_aSymbols [ iTable ] . begin ( ) ;
while ( iSymbol ! = g_aSymbols [ iTable ] . end ( ) )
{
if ( ! _tcsicmp ( iSymbol - > second . c_str ( ) , pSymbol ) )
{
if ( pAddress_ )
{
* pAddress_ = iSymbol - > first ;
}
if ( iTable_ )
{
* iTable_ = iTable ;
}
return true ;
}
iSymbol + + ;
}
}
return false ;
}
// Symbols ________________________________________________________________________________________
//===========================================================================
2010-12-19 16:43:51 +00:00
WORD GetAddressFromSymbol ( const char * pSymbol )
2010-06-11 15:38:22 +00:00
{
WORD nAddress ;
bool bFoundSymbol = FindAddressFromSymbol ( pSymbol , & nAddress ) ;
if ( ! bFoundSymbol )
{
nAddress = 0 ;
}
return nAddress ;
}
//===========================================================================
bool String2Address ( LPCTSTR pText , WORD & nAddress_ )
{
TCHAR sHexApple [ CONSOLE_WIDTH ] ;
if ( pText [ 0 ] = = ' $ ' )
{
if ( ! TextIsHexString ( pText + 1 ) )
return false ;
_tcscpy ( sHexApple , " 0x " ) ;
_tcsncpy ( sHexApple + 2 , pText + 1 , MAX_SYMBOLS_LEN - 3 ) ;
2018-02-24 15:24:37 +00:00
sHexApple [ 2 + ( MAX_SYMBOLS_LEN - 3 ) - 1 ] = 0 ;
2010-06-11 15:38:22 +00:00
pText = sHexApple ;
}
if ( pText [ 0 ] = = TEXT ( ' 0 ' ) )
{
if ( ( pText [ 1 ] = = TEXT ( ' X ' ) ) | | pText [ 1 ] = = TEXT ( ' x ' ) )
{
if ( ! TextIsHexString ( pText + 2 ) )
return false ;
TCHAR * pEnd ;
nAddress_ = ( WORD ) _tcstol ( pText , & pEnd , 16 ) ;
return true ;
}
if ( TextIsHexString ( pText ) )
{
TCHAR * pEnd ;
nAddress_ = ( WORD ) _tcstol ( pText , & pEnd , 16 ) ;
return true ;
}
}
return false ;
}
//===========================================================================
Update_t CmdSymbols ( int nArgs )
{
if ( ! nArgs )
return CmdSymbolsInfo ( 0 ) ;
Update_t iUpdate = _CmdSymbolsUpdate ( nArgs , SYMBOL_TABLE_USER_1 ) ;
if ( iUpdate ! = UPDATE_NOTHING )
return iUpdate ;
int bSymbolTables = ( 1 < < NUM_SYMBOL_TABLES ) - 1 ;
return _CmdSymbolsListTables ( nArgs , bSymbolTables ) ;
}
//===========================================================================
Update_t CmdSymbolsClear ( int nArgs )
{
2022-01-04 06:15:41 +00:00
SymbolTable_Index_e eSymbolTable = SYMBOLS_USER_1 ;
2010-06-11 15:38:22 +00:00
_CmdSymbolsClear ( eSymbolTable ) ;
return ( UPDATE_DISASM | UPDATE_SYMBOLS ) ;
}
2010-12-18 15:04:12 +00:00
// Format the summary of the specified symbol table
//===========================================================================
2022-04-17 11:12:40 +00:00
std : : string _CmdSymbolsInfoHeader ( int iTable , int nDisplaySize /* = 0 */ )
2010-06-11 15:38:22 +00:00
{
2010-12-18 15:04:12 +00:00
// Common case is to use/calc the table size
bool bActive = ( g_bDisplaySymbolTables & ( 1 < < iTable ) ) ? true : false ;
int nSymbols = nDisplaySize ? nDisplaySize : g_aSymbols [ iTable ] . size ( ) ;
// Short Desc: `MAIN`: `1000`
// // 2.6.2.19 Color for name of symbol table: _CmdPrintSymbol() "SYM HOME" _CmdSymbolsInfoHeader "SYM"
// CHC_STRING and CHC_NUM_DEC are both cyan, using CHC_USAGE instead of CHC_STRING
2022-04-17 11:12:40 +00:00
return StrFormat ( CHC_USAGE " %s " CHC_ARG_SEP " :%s%d " // CHC_DEFAULT
, g_aSymbolTableNames [ iTable ]
2010-12-18 15:04:12 +00:00
, bActive ? CHC_NUM_DEC : CHC_WARNING , nSymbols
2010-06-11 15:38:22 +00:00
) ;
}
//===========================================================================
Update_t CmdSymbolsInfo ( int nArgs )
{
int bDisplaySymbolTables = 0 ;
if ( ! nArgs )
{
// default to all tables
bDisplaySymbolTables = ( 1 < < NUM_SYMBOL_TABLES ) - 1 ;
}
else
{ // Convert Command Index to parameter
int iWhichTable = GetSymbolTableFromCommand ( ) ;
if ( ( iWhichTable < 0 ) | | ( iWhichTable > = NUM_SYMBOL_TABLES ) )
{
2014-11-27 18:01:43 +00:00
return _PrintSymbolInvalidTable ( ) ;
2010-06-11 15:38:22 +00:00
}
bDisplaySymbolTables = ( 1 < < iWhichTable ) ;
}
2022-04-20 14:21:30 +00:00
//sprintf( sText, " Symbols Main: %s%d%s User: %s%d%s Source: %s%d%s"
// "Main:# Basic:# Asm:# User1:# User2:# Src1:# Src2:# Dos:# Prodos:#
2022-04-17 11:12:40 +00:00
std : : string const sIndent = " " ;
2022-04-20 14:21:30 +00:00
std : : string sText = sIndent ; // Indent new line
2010-06-11 15:38:22 +00:00
2022-04-17 10:32:03 +00:00
for ( int iTable = 0 , bTable = 1 ; bTable < = bDisplaySymbolTables ; iTable + + , bTable < < = 1 )
2014-12-01 01:51:11 +00:00
{
2022-04-17 11:12:40 +00:00
if ( ! ! ( bDisplaySymbolTables & bTable ) )
2014-12-01 01:51:11 +00:00
{
2022-04-17 11:12:40 +00:00
std : : string hdr = _CmdSymbolsInfoHeader ( iTable ) ; // 15 chars per table
2014-12-01 01:51:11 +00:00
// 2.8.0.4 BUGFIX: Check for buffer overflow and wrap text
2022-04-17 11:12:40 +00:00
int nLen = ConsoleColor_StringLength ( hdr . c_str ( ) ) ;
int nDst = ConsoleColor_StringLength ( sText . c_str ( ) ) ;
if ( ( nDst + nLen ) > CONSOLE_WIDTH )
2014-12-01 01:51:11 +00:00
{
2022-04-17 11:12:40 +00:00
ConsolePrint ( sText . c_str ( ) ) ;
sText = sIndent ; // Indent new line
2014-12-01 01:51:11 +00:00
}
2022-04-17 11:12:40 +00:00
sText + = hdr ;
2010-06-11 15:38:22 +00:00
}
}
2022-04-17 11:12:40 +00:00
ConsolePrint ( sText . c_str ( ) ) ;
2010-06-11 15:38:22 +00:00
return ConsoleUpdate ( ) ;
}
//===========================================================================
void _CmdPrintSymbol ( LPCTSTR pSymbol , WORD nAddress , int iTable )
{
2010-12-18 15:04:12 +00:00
// 2.6.2.19 Color for name of symbol table: _CmdPrintSymbol() "SYM HOME" _CmdSymbolsInfoHeader "SYM"
// CHC_STRING and CHC_NUM_DEC are both cyan, using CHC_USAGE instead of CHC_STRING
// 2.6.2.20 Changed: Output of found symbol more table friendly. Symbol table name displayed first.
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %s%s%s: $%s%04X %s%s "
2010-12-18 15:04:12 +00:00
, CHC_USAGE , g_aSymbolTableNames [ iTable ]
2010-06-11 15:38:22 +00:00
, CHC_ARG_SEP
2010-12-18 15:04:12 +00:00
, CHC_ADDRESS , nAddress
, CHC_SYMBOL , pSymbol ) ;
2010-06-11 15:38:22 +00:00
// ConsoleBufferPush( sText );
}
// Test if bit-mask to index (equal to number of bit-shifs required to reach table)
//=========================================================================== */
bool _FindSymbolTable ( int bSymbolTables , int iTable )
{
// iTable is enumeration
// bSymbolTables is bit-flags of enabled tables to search
2022-03-27 19:48:26 +00:00
if ( bSymbolTables & ( 1 < < iTable ) )
2010-06-11 15:38:22 +00:00
{
return true ;
}
return false ;
}
// Convert bit-mask to index
//=========================================================================== */
int _GetSymbolTableFromFlag ( int bSymbolTables )
{
int iTable = 0 ;
int bTable = 1 ;
2022-03-27 19:48:26 +00:00
for ( ; bTable < = bSymbolTables ; iTable + + , bTable < < = 1 )
2010-06-11 15:38:22 +00:00
{
2022-03-27 19:48:26 +00:00
if ( bTable & bSymbolTables )
2010-06-11 15:38:22 +00:00
break ;
}
return iTable ;
}
/**
@ param bSymbolTables Bit Flags of which symbol tables to search
//=========================================================================== */
bool _CmdSymbolList_Address2Symbol ( int nAddress , int bSymbolTables )
{
2022-02-26 17:54:06 +00:00
int iTable = 0 ;
std : : string const * pSymbol = FindSymbolFromAddress ( nAddress , & iTable ) ;
2010-06-11 15:38:22 +00:00
if ( pSymbol )
{
if ( _FindSymbolTable ( bSymbolTables , iTable ) )
{
2022-02-26 17:54:06 +00:00
_CmdPrintSymbol ( pSymbol - > c_str ( ) , nAddress , iTable ) ;
2010-06-11 15:38:22 +00:00
return true ;
}
}
return false ;
}
//===========================================================================
bool _CmdSymbolList_Symbol2Address ( LPCTSTR pSymbol , int bSymbolTables )
{
int iTable ;
WORD nAddress ;
bool bFoundSymbol = FindAddressFromSymbol ( pSymbol , & nAddress , & iTable ) ;
if ( bFoundSymbol )
{
if ( _FindSymbolTable ( bSymbolTables , iTable ) )
{
_CmdPrintSymbol ( pSymbol , nAddress , iTable ) ;
}
}
return bFoundSymbol ;
}
// LIST is normally an implicit "LIST *", but due to the numbers of symbols
// only look up symbols the user specifies
//===========================================================================
Update_t CmdSymbolsList ( int nArgs )
{
int bSymbolTables = ( 1 < < NUM_SYMBOL_TABLES ) - 1 ; // default to all
return _CmdSymbolsListTables ( nArgs , bSymbolTables ) ;
}
//===========================================================================
Update_t _CmdSymbolsListTables ( int nArgs , int bSymbolTables )
{
if ( ! nArgs )
{
return Help_Arg_1 ( CMD_SYMBOLS_LIST ) ;
}
/*
Test Cases
SYM 0 RESET FA6F $ FA59
$ 0000 LOC0
$ FA6F RESET
$ FA6F INITAN
$ FA59 OLDBRK
SYM B
SYMBOL B = $ 2000
SYM B
*/
2022-03-27 19:48:26 +00:00
for ( int iArgs = 1 ; iArgs < = nArgs ; iArgs + + )
2010-06-11 15:38:22 +00:00
{
WORD nAddress = g_aArgs [ iArgs ] . nValue ;
LPCTSTR pSymbol = g_aArgs [ iArgs ] . sArg ;
// Dump all symbols for this table
2022-03-27 19:48:26 +00:00
if ( g_aArgRaw [ iArgs ] . eToken = = TOKEN_STAR )
2010-06-11 15:38:22 +00:00
{
// int iWhichTable = (g_iCommand - CMD_SYMBOLS_MAIN);
// bDisplaySymbolTables = (1 << iWhichTable);
int iTable = 0 ;
int bTable = 1 ;
2022-03-27 19:48:26 +00:00
for ( ; bTable < = bSymbolTables ; iTable + + , bTable < < = 1 )
2010-06-11 15:38:22 +00:00
{
2022-03-27 19:48:26 +00:00
if ( bTable & bSymbolTables )
2010-06-11 15:38:22 +00:00
{
int nSymbols = g_aSymbols [ iTable ] . size ( ) ;
if ( nSymbols )
{
SymbolTable_t : : iterator iSymbol = g_aSymbols [ iTable ] . begin ( ) ;
while ( iSymbol ! = g_aSymbols [ iTable ] . end ( ) )
{
const char * pSymbol = iSymbol - > second . c_str ( ) ;
unsigned short nAddress = iSymbol - > first ;
_CmdPrintSymbol ( pSymbol , nAddress , iTable ) ;
+ + iSymbol ;
}
}
2022-04-17 11:12:40 +00:00
ConsolePrint ( _CmdSymbolsInfoHeader ( iTable ) . c_str ( ) ) ;
2010-06-11 15:38:22 +00:00
}
}
}
else
if ( nAddress )
{ // Have address, do symbol lookup first
if ( ! _CmdSymbolList_Symbol2Address ( pSymbol , bSymbolTables ) )
{
// nope, ok, try as address
if ( ! _CmdSymbolList_Address2Symbol ( nAddress , bSymbolTables ) )
{
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " Address not found: %s$%s%04X%s "
2010-06-11 15:38:22 +00:00
, CHC_ARG_SEP
, CHC_ADDRESS , nAddress , CHC_DEFAULT ) ;
}
}
}
else
{ // Have symbol, do address lookup
if ( ! _CmdSymbolList_Symbol2Address ( pSymbol , bSymbolTables ) )
{ // nope, ok, try as address
if ( String2Address ( pSymbol , nAddress ) )
{
if ( ! _CmdSymbolList_Address2Symbol ( nAddress , bSymbolTables ) )
{
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %sSymbol not found: %s%s%s "
2010-12-18 15:04:12 +00:00
, CHC_ERROR , CHC_SYMBOL , pSymbol , CHC_DEFAULT
2010-06-11 15:38:22 +00:00
) ;
}
}
else
{
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %sSymbol not found: %s%s%s "
2010-12-18 15:04:12 +00:00
, CHC_ERROR , CHC_SYMBOL , pSymbol , CHC_DEFAULT
2010-06-11 15:38:22 +00:00
) ;
}
}
}
}
return ConsoleUpdate ( ) ;
}
//===========================================================================
2019-09-06 16:34:25 +00:00
int ParseSymbolTable ( const std : : string & pPathFileName , SymbolTable_Index_e eSymbolTableWrite , int nSymbolOffset )
2010-06-11 15:38:22 +00:00
{
2014-12-01 02:58:15 +00:00
bool bFileDisplayed = false ;
2022-01-05 23:42:34 +00:00
const int nMaxLen = MIN ( DISASM_DISPLAY_MAX_TARGET_LEN , MAX_SYMBOLS_LEN ) ;
2017-08-24 16:40:28 +00:00
2010-06-11 15:38:22 +00:00
int nSymbolsLoaded = 0 ;
2019-09-06 16:34:25 +00:00
if ( pPathFileName . empty ( ) )
2010-06-11 15:38:22 +00:00
return nSymbolsLoaded ;
2022-04-06 19:36:24 +00:00
std : : string sFormat1 = StrFormat ( " %%x %%%ds " , MAX_SYMBOLS_LEN ) ; // i.e. "%x %13s"
std : : string sFormat2 = StrFormat ( " %%%ds %%x " , MAX_SYMBOLS_LEN ) ; // i.e. "%13s %x"
2010-06-11 15:38:22 +00:00
2019-09-06 16:34:25 +00:00
FILE * hFile = fopen ( pPathFileName . c_str ( ) , " rt " ) ;
2010-06-11 15:38:22 +00:00
2022-03-27 19:48:26 +00:00
if ( ! hFile & & g_bSymbolsDisplayMissingFile )
2010-06-11 15:38:22 +00:00
{
2014-11-27 18:01:43 +00:00
// TODO: print filename! Bug #242 Help file (.chm) description for "Symbols" #242
2010-06-11 15:38:22 +00:00
ConsoleDisplayError ( " Symbol File not found: " ) ;
2014-11-27 18:01:43 +00:00
_PrintCurrentPath ( ) ;
2010-06-11 15:38:22 +00:00
nSymbolsLoaded = - 1 ; // HACK: ERROR: FILE NOT EXIST
}
bool bDupSymbolHeader = false ;
2022-03-27 19:48:26 +00:00
if ( hFile )
2010-06-11 15:38:22 +00:00
{
2022-03-27 19:48:26 +00:00
while ( ! feof ( hFile ) )
2010-06-11 15:38:22 +00:00
{
// Support 2 types of symbols files:
// 1) AppleWin:
// . 0000 SYMBOL
// . FFFF SYMBOL
// 2) ACME:
// . SYMBOL =$0000; Comment
// . SYMBOL =$FFFF; Comment
//
DWORD nAddress = _6502_MEM_END + 1 ; // default to invalid address
char sName [ MAX_SYMBOLS_LEN + 1 ] = " " ;
const int MAX_LINE = 256 ;
char szLine [ MAX_LINE ] = " " ;
2022-03-27 19:48:26 +00:00
if ( ! fgets ( szLine , MAX_LINE - 1 , hFile ) ) // Get next line
2010-06-11 15:38:22 +00:00
{
//ConsolePrint("<<EOF");
break ;
}
2022-03-27 19:48:26 +00:00
if ( strstr ( szLine , " $ " ) = = NULL )
2010-06-11 15:38:22 +00:00
{
2022-04-06 19:36:24 +00:00
sscanf ( szLine , sFormat1 . c_str ( ) , & nAddress , sName ) ;
2010-06-11 15:38:22 +00:00
}
else
{
char * p = strstr ( szLine , " = " ) ; // Optional
2022-03-27 19:48:26 +00:00
if ( p ) * p = ' ' ;
2010-06-11 15:38:22 +00:00
p = strstr ( szLine , " $ " ) ;
2022-03-27 19:48:26 +00:00
if ( p ) * p = ' ' ;
2010-06-11 15:38:22 +00:00
p = strstr ( szLine , " ; " ) ; // Optional
2022-03-27 19:48:26 +00:00
if ( p ) * p = 0 ;
2010-06-11 15:38:22 +00:00
p = strstr ( szLine , " " ) ; // 1st space between name & value
2019-10-24 19:25:07 +00:00
if ( p )
2010-06-11 15:38:22 +00:00
{
2019-10-24 19:25:07 +00:00
int nLen = p - szLine ;
if ( nLen > MAX_SYMBOLS_LEN )
{
memset ( & szLine [ MAX_SYMBOLS_LEN ] , ' ' , nLen - MAX_SYMBOLS_LEN ) ; // sscanf fails for nAddress if string too long
}
2010-06-11 15:38:22 +00:00
}
2022-04-06 19:36:24 +00:00
sscanf ( szLine , sFormat2 . c_str ( ) , sName , & nAddress ) ;
2010-06-11 15:38:22 +00:00
}
// SymbolOffset
nAddress + = nSymbolOffset ;
2022-03-27 19:48:26 +00:00
if ( ( nAddress > _6502_MEM_END ) | | ( sName [ 0 ] = = 0 ) )
2010-06-11 15:38:22 +00:00
continue ;
2017-08-24 16:40:28 +00:00
// 2.9.0.11 Bug #479
int nLen = strlen ( sName ) ;
2017-08-24 16:47:05 +00:00
if ( nLen > nMaxLen )
2017-08-24 16:40:28 +00:00
{
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %sWarn.: %s%s %s(%s%d %s> %s%d%s) "
2017-08-24 16:40:28 +00:00
, CHC_WARNING
, CHC_SYMBOL
, sName
2022-01-04 06:15:41 +00:00
, CHC_ARG_SEP
, CHC_NUM_DEC
2017-08-24 16:40:28 +00:00
, nLen
2022-01-04 06:15:41 +00:00
, CHC_ARG_SEP
, CHC_NUM_DEC
2017-08-24 16:40:28 +00:00
, nMaxLen
2022-01-04 06:15:41 +00:00
, CHC_ARG_SEP
2017-08-24 16:40:28 +00:00
) ;
ConsoleUpdate ( ) ; // Flush buffered output so we don't ask the user to pause
}
2022-02-26 17:54:06 +00:00
int iTable = 0 ;
2014-12-01 02:58:15 +00:00
// 2.8.0.5 Bug #244 (Debugger) Duplicate symbols for identical memory addresses in APPLE2E.SYM
2022-02-26 17:54:06 +00:00
std : : string const * pSymbolPrev = FindSymbolFromAddress ( ( WORD ) nAddress , & iTable ) ; // don't care which table it is in
2022-03-27 19:48:26 +00:00
if ( pSymbolPrev )
2014-12-01 02:58:15 +00:00
{
2022-03-27 19:48:26 +00:00
if ( ! bFileDisplayed )
2014-12-01 02:58:15 +00:00
{
bFileDisplayed = true ;
// TODO: Must check for buffer overflow !
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %s%s "
2014-12-01 02:58:15 +00:00
, CHC_PATH
2019-09-17 18:17:30 +00:00
, pPathFileName . c_str ( )
2014-12-01 02:58:15 +00:00
) ;
}
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %sInfo.: %s%-16s %saliases %s$%s%04X %s%-12s%s (%s%s%s) " // MAGIC NUMBER: -MAX_SYMBOLS_LEN
2017-08-24 16:37:07 +00:00
, CHC_INFO // 2.9.0.10 was CHC_WARNING, see #479
2014-12-01 02:58:15 +00:00
, CHC_SYMBOL
, sName
, CHC_INFO
, CHC_ARG_SEP
, CHC_ADDRESS
, nAddress
, CHC_SYMBOL
2022-02-26 17:54:06 +00:00
, pSymbolPrev - > c_str ( )
2014-12-01 02:58:15 +00:00
, CHC_DEFAULT
, CHC_STRING
, g_aSymbolTableNames [ iTable ]
, CHC_DEFAULT
) ;
ConsoleUpdate ( ) ; // Flush buffered output so we don't ask the user to pause
/*
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %sWarning: %sAddress already has symbol Name%s (%s%s%s): %s%s "
2014-12-01 02:58:15 +00:00
, CHC_WARNING
, CHC_INFO
, CHC_ARG_SEP
, CHC_STRING
, g_aSymbolTableNames [ iTable ]
, CHC_DEFAULT
, CHC_SYMBOL
, pSymbolPrev
) ;
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %s$%s%04X %s%-31s%s "
2014-12-01 02:58:15 +00:00
, CHC_ARG_SEP
, CHC_ADDRESS
, nAddress
, CHC_SYMBOL
, sName
, CHC_DEFAULT
) ;
*/
}
2022-02-26 17:54:06 +00:00
// If updating symbol, print duplicate symbols
WORD nAddressPrev = 0 ;
2014-12-01 02:58:15 +00:00
bool bExists = FindAddressFromSymbol ( sName , & nAddressPrev , & iTable ) ;
2022-03-27 19:48:26 +00:00
if ( bExists )
2010-06-11 15:38:22 +00:00
{
2022-03-27 19:48:26 +00:00
if ( ! bDupSymbolHeader )
2010-06-11 15:38:22 +00:00
{
bDupSymbolHeader = true ;
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %sDup Symbol Name%s (%s%s%s) %s "
2010-06-11 15:38:22 +00:00
, CHC_ERROR
, CHC_DEFAULT
, CHC_STRING
, g_aSymbolTableNames [ iTable ]
, CHC_DEFAULT
2019-09-17 18:17:30 +00:00
, pPathFileName . c_str ( )
2010-06-11 15:38:22 +00:00
) ;
}
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " %s$%s%04X %s%-31s%s "
2010-06-11 15:38:22 +00:00
, CHC_ARG_SEP
, CHC_ADDRESS
, nAddress
, CHC_SYMBOL
, sName
, CHC_DEFAULT
) ;
}
2014-12-01 02:58:15 +00:00
// else // It is not a bug to have duplicate addresses by different names
2010-06-11 15:38:22 +00:00
g_aSymbols [ eSymbolTableWrite ] [ ( WORD ) nAddress ] = sName ;
2014-12-01 02:58:15 +00:00
nSymbolsLoaded + + ; // TODO: FIXME: BUG: This is the total symbols read, not added
2010-06-11 15:38:22 +00:00
}
fclose ( hFile ) ;
}
return nSymbolsLoaded ;
}
//===========================================================================
Update_t CmdSymbolsLoad ( int nArgs )
{
2019-09-06 16:34:25 +00:00
std : : string sFileName = g_sProgramDir ;
2010-06-11 15:38:22 +00:00
int iSymbolTable = GetSymbolTableFromCommand ( ) ;
if ( ( iSymbolTable < 0 ) | | ( iSymbolTable > = NUM_SYMBOL_TABLES ) )
{
2014-11-27 18:01:43 +00:00
return _PrintSymbolInvalidTable ( ) ;
2010-06-11 15:38:22 +00:00
}
int nSymbols = 0 ;
2014-11-27 17:37:24 +00:00
// Debugger will call us with 0 args on startup as a way to pre-load symbol tables
2010-06-11 15:38:22 +00:00
if ( ! nArgs )
{
2019-09-06 16:34:25 +00:00
sFileName + = g_sFileNameSymbols [ iSymbolTable ] ;
2010-06-11 15:38:22 +00:00
nSymbols = ParseSymbolTable ( sFileName , ( SymbolTable_Index_e ) iSymbolTable ) ;
}
int iArg = 1 ;
if ( iArg < = nArgs )
{
2019-09-06 16:34:25 +00:00
std : : string pFileName ;
2010-06-11 15:38:22 +00:00
2022-03-27 19:48:26 +00:00
if ( g_aArgs [ iArg ] . bType & TYPE_QUOTED_2 )
2010-06-11 15:38:22 +00:00
{
pFileName = g_aArgs [ iArg ] . sArg ;
2019-09-06 16:34:25 +00:00
sFileName = g_sProgramDir + pFileName ;
2010-06-11 15:38:22 +00:00
// Remember File Name of last symbols loaded
2019-09-06 16:34:25 +00:00
g_sFileNameSymbolsUser = pFileName ;
2010-06-11 15:38:22 +00:00
}
// SymbolOffset
// sym load "filename" [,symbol_offset]
unsigned int nOffsetAddr = 0 ;
iArg + + ;
2022-03-27 19:48:26 +00:00
if ( iArg < = nArgs )
2010-06-11 15:38:22 +00:00
{
if ( g_aArgs [ iArg ] . eToken = = TOKEN_COMMA )
{
iArg + + ;
2022-03-27 19:48:26 +00:00
if ( iArg < = nArgs )
2010-06-11 15:38:22 +00:00
{
nOffsetAddr = g_aArgs [ iArg ] . nValue ;
2022-03-27 19:48:26 +00:00
if ( ( nOffsetAddr < _6502_MEM_BEGIN ) | | ( nOffsetAddr > _6502_MEM_END ) )
2010-06-11 15:38:22 +00:00
{
nOffsetAddr = 0 ;
}
}
}
}
2022-03-27 19:48:26 +00:00
if ( ! pFileName . empty ( ) )
2010-06-11 15:38:22 +00:00
{
nSymbols = ParseSymbolTable ( sFileName , ( SymbolTable_Index_e ) iSymbolTable , nOffsetAddr ) ;
}
}
2022-03-27 19:48:26 +00:00
if ( nSymbols > 0 )
2010-06-11 15:38:22 +00:00
{
g_nSymbolsLoaded = nSymbols ;
}
Update_t bUpdateDisplay = UPDATE_DISASM ;
bUpdateDisplay | = ( nSymbols > 0 ) ? UPDATE_SYMBOLS : 0 ;
return bUpdateDisplay ;
}
//===========================================================================
Update_t _CmdSymbolsClear ( SymbolTable_Index_e eSymbolTable )
{
g_aSymbols [ eSymbolTable ] . clear ( ) ;
return UPDATE_SYMBOLS ;
}
//===========================================================================
2021-02-10 21:05:00 +00:00
void SymbolUpdate ( SymbolTable_Index_e eSymbolTable , const char * pSymbolName , WORD nAddress , bool bRemoveSymbol , bool bUpdateSymbol )
2010-06-11 15:38:22 +00:00
{
if ( bRemoveSymbol )
pSymbolName = g_aArgs [ 2 ] . sArg ;
if ( _tcslen ( pSymbolName ) < MAX_SYMBOLS_LEN )
{
WORD nAddressPrev ;
int iTable ;
bool bExists = FindAddressFromSymbol ( pSymbolName , & nAddressPrev , & iTable ) ;
if ( bExists )
{
if ( iTable = = eSymbolTable )
{
if ( bRemoveSymbol )
{
ConsoleBufferPush ( TEXT ( " Removing symbol. " ) ) ;
}
g_aSymbols [ eSymbolTable ] . erase ( nAddressPrev ) ;
if ( bUpdateSymbol )
{
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " Updating %s%s%s from %s$%s%04X%s to %s$%s%04X%s "
2010-06-11 15:38:22 +00:00
, CHC_SYMBOL , pSymbolName , CHC_DEFAULT
, CHC_ARG_SEP
, CHC_ADDRESS , nAddressPrev , CHC_DEFAULT
, CHC_ARG_SEP
, CHC_ADDRESS , nAddress , CHC_DEFAULT
) ;
}
}
}
else
{
if ( bRemoveSymbol )
{
ConsoleBufferPush ( TEXT ( " Symbol not in table. " ) ) ;
}
}
if ( bUpdateSymbol )
{
# if _DEBUG
2022-02-26 17:54:06 +00:00
std : : string const * pSymbol = FindSymbolFromAddress ( nAddress , & iTable ) ;
2010-06-11 15:38:22 +00:00
{
// Found another symbol for this address. Harmless.
// TODO: Probably should check if same name?
}
# endif
g_aSymbols [ eSymbolTable ] [ nAddress ] = pSymbolName ;
2014-08-28 18:13:02 +00:00
// Tell user symbol was added
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " Added symbol: %s%s%s %s$%s%04X%s "
2014-08-28 18:13:02 +00:00
, CHC_SYMBOL , pSymbolName , CHC_DEFAULT
, CHC_ARG_SEP
, CHC_ADDRESS , nAddress , CHC_DEFAULT
) ;
2010-06-11 15:38:22 +00:00
}
}
}
2022-01-04 17:25:51 +00:00
// Syntax:
// sym ! <symbol>
// sym ~ <symbol>
// sym <symbol> =
// sym @ = <addr>
// NOTE: Listing of the symbols is handled via returning UPDATE_NOTHING which is triggered by:
// sym *
2010-06-11 15:38:22 +00:00
//===========================================================================
Update_t _CmdSymbolsUpdate ( int nArgs , int bSymbolTables )
{
bool bRemoveSymbol = false ;
bool bUpdateSymbol = false ;
2022-01-04 17:25:51 +00:00
TCHAR * pSymbolName = g_aArgs [ 1 ] . sArg ;
WORD nAddress = g_aArgs [ 3 ] . nValue ;
if ( ( nArgs = = 2 )
& & ( ( g_aArgs [ 1 ] . eToken = = TOKEN_EXCLAMATION ) | | ( g_aArgs [ 1 ] . eToken = = TOKEN_TILDE ) ) )
2010-06-11 15:38:22 +00:00
bRemoveSymbol = true ;
if ( ( nArgs = = 3 ) & & ( g_aArgs [ 2 ] . eToken = = TOKEN_EQUAL ) )
bUpdateSymbol = true ;
2022-01-04 17:25:51 +00:00
// 2.9.1.7 Added: QoL for automatic symbol names
if ( ( nArgs = = 2 )
& & ( g_aArgRaw [ 1 ] . eToken = = TOKEN_AT ) // NOTE: @ is parsed and evaluated and NOT in the cooked args
& & ( g_aArgs [ 1 ] . eToken = = TOKEN_EQUAL ) )
2010-06-11 15:38:22 +00:00
{
2022-01-04 17:25:51 +00:00
if ( bSymbolTables = = SYMBOL_TABLE_USER_1 )
bSymbolTables = SYMBOL_TABLE_USER_2 ; // Autogenerated symbol names go in table 2 for organization when reverse engineering. Table 1 = known, Table 2 = unknown.
2010-06-11 15:38:22 +00:00
2022-01-04 17:25:51 +00:00
nAddress = g_aArgs [ 2 ] . nValue ;
2022-04-17 10:40:21 +00:00
strncpy_s ( g_aArgs [ 1 ] . sArg , StrFormat ( " _%04X " , nAddress ) . c_str ( ) , _TRUNCATE ) ; // Autogenerated symbol name
2022-01-04 17:25:51 +00:00
bUpdateSymbol = true ;
}
if ( bRemoveSymbol | | bUpdateSymbol )
{
2010-06-11 15:38:22 +00:00
int iTable = _GetSymbolTableFromFlag ( bSymbolTables ) ;
SymbolUpdate ( ( SymbolTable_Index_e ) iTable , pSymbolName , nAddress , bRemoveSymbol , bUpdateSymbol ) ;
return ConsoleUpdate ( ) ;
}
return UPDATE_NOTHING ;
}
//===========================================================================
Update_t _CmdSymbolsCommon ( int nArgs , int bSymbolTables )
{
if ( ! nArgs )
{
return Help_Arg_1 ( g_iCommand ) ;
}
Update_t iUpdate = _CmdSymbolsUpdate ( nArgs , bSymbolTables ) ;
if ( iUpdate ! = UPDATE_NOTHING )
return iUpdate ;
int iArg = 0 ;
while ( iArg + + < = nArgs )
{
int iParam ;
int nParams = FindParam ( g_aArgs [ iArg ] . sArg , MATCH_EXACT , iParam ) ; // MATCH_FUZZY
if ( nParams )
{
if ( iParam = = PARAM_CLEAR )
{
int iTable = _GetSymbolTableFromFlag ( bSymbolTables ) ;
if ( iTable ! = NUM_SYMBOL_TABLES )
{
Update_t iUpdate = _CmdSymbolsClear ( ( SymbolTable_Index_e ) iTable ) ;
2022-02-17 22:12:04 +00:00
ConsolePrintFormat ( " Cleared symbol table: %s%s "
2010-12-18 15:04:12 +00:00
, CHC_STRING , g_aSymbolTableNames [ iTable ]
2010-06-11 15:38:22 +00:00
) ;
iUpdate | = ConsoleUpdate ( ) ;
return iUpdate ;
}
else
{
2010-12-18 15:04:12 +00:00
// Shouldn't have multiple symbol tables selected
// nArgs = _Arg_1( eSymbolsTable );
2010-06-11 15:38:22 +00:00
ConsoleBufferPush ( TEXT ( " Error: Unknown Symbol Table Type " ) ) ;
return ConsoleUpdate ( ) ;
}
}
else
if ( iParam = = PARAM_LOAD )
{
nArgs = _Arg_Shift ( iArg , nArgs ) ;
Update_t bUpdate = CmdSymbolsLoad ( nArgs ) ;
int iTable = _GetSymbolTableFromFlag ( bSymbolTables ) ;
if ( iTable ! = NUM_SYMBOL_TABLES )
{
2022-03-27 19:48:26 +00:00
if ( bUpdate & UPDATE_SYMBOLS )
2010-06-11 15:38:22 +00:00
{
2022-04-17 11:12:40 +00:00
ConsolePrint ( _CmdSymbolsInfoHeader ( iTable , g_nSymbolsLoaded ) . c_str ( ) ) ;
2010-06-11 15:38:22 +00:00
}
}
else
{
ConsoleBufferPush ( TEXT ( " Error: Unknown Symbol Table Type " ) ) ;
}
return ConsoleUpdate ( ) ;
}
else
if ( iParam = = PARAM_SAVE )
{
nArgs = _Arg_Shift ( iArg , nArgs ) ;
return CmdSymbolsSave ( nArgs ) ;
}
2010-12-18 15:04:12 +00:00
else
if ( iParam = = PARAM_ON )
{
g_bDisplaySymbolTables | = bSymbolTables ;
int iTable = _GetSymbolTableFromFlag ( bSymbolTables ) ;
if ( iTable ! = NUM_SYMBOL_TABLES )
{
2022-04-17 11:12:40 +00:00
ConsolePrint ( _CmdSymbolsInfoHeader ( iTable ) . c_str ( ) ) ;
2010-12-18 15:04:12 +00:00
}
return ConsoleUpdate ( ) | UPDATE_DISASM ;
}
else
if ( iParam = = PARAM_OFF )
{
g_bDisplaySymbolTables & = ~ bSymbolTables ;
int iTable = _GetSymbolTableFromFlag ( bSymbolTables ) ;
if ( iTable ! = NUM_SYMBOL_TABLES )
{
2022-04-17 11:12:40 +00:00
ConsolePrint ( _CmdSymbolsInfoHeader ( iTable ) . c_str ( ) ) ;
2010-12-18 15:04:12 +00:00
}
return ConsoleUpdate ( ) | UPDATE_DISASM ;
}
2010-06-11 15:38:22 +00:00
}
else
{
2010-12-18 15:04:12 +00:00
return _CmdSymbolsListTables ( nArgs , bSymbolTables ) ;
2010-06-11 15:38:22 +00:00
}
}
return ConsoleUpdate ( ) ;
}
//===========================================================================
Update_t CmdSymbolsCommand ( int nArgs )
{
if ( ! nArgs )
{
return CmdSymbolsInfo ( 1 ) ;
}
int bSymbolTable = SYMBOL_TABLE_MAIN < < GetSymbolTableFromCommand ( ) ;
2010-12-18 04:17:32 +00:00
return _CmdSymbolsCommon ( nArgs , bSymbolTable ) ; // BUGFIX 2.6.2.12 Hard-coded to SYMMAIN
2010-06-11 15:38:22 +00:00
}
//===========================================================================
Update_t CmdSymbolsSave ( int nArgs )
{
return UPDATE_CONSOLE_DISPLAY ;
}