//=========================================================================== WORD GetAddressFromSymbol (const char* pSymbol) { WORD nAddress; bool bFoundSymbol = FindAddressFromSymbol( pSymbol, & nAddress ); if (! bFoundSymbol) { nAddress = 0; } return nAddress; }
//=========================================================================== 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; }
//=========================================================================== void ArgsRawParse ( void ) { const int BASE = 16; // hex TCHAR *pSrc = NULL; TCHAR *pEnd = NULL; int iArg = 1; Arg_t *pArg = & g_aArgRaw[ iArg ]; int nArg = g_nArgRaw; WORD nAddressArg; WORD nAddressSymbol; WORD nAddressValue; int nParamLen = 0; while (iArg <= nArg) { pSrc = & (pArg->sArg[ 0 ]); nAddressArg = (WORD)(_tcstoul( pSrc, &pEnd, BASE) & _6502_END_MEM_ADDRESS); nAddressValue = nAddressArg; bool bFound = false; if (! (pArg->bType & TYPE_NO_SYM)) { bFound = FindAddressFromSymbol( pSrc, & nAddressSymbol ); if (bFound) { nAddressValue = nAddressSymbol; pArg->bSymbol = true; } } if (! (pArg->bType & TYPE_VALUE)) // already up to date? pArg->nVal1 = nAddressValue; pArg->bType |= TYPE_ADDRESS; iArg++; pArg++; } }
/** @param nArgs Number of raw args. @param bProcessMask Bit-flags of which arg operators to process. Note: The number of args can be changed via: address1,length Length address1:address2 Range address1+delta Delta address1-delta Delta //=========================================================================== */ int ArgsCook ( const int nArgs, const int bProcessMask ) { const int BASE = 16; // hex TCHAR *pSrc = NULL; TCHAR *pEnd2 = NULL; int nArg = nArgs; int iArg = 1; Arg_t *pArg = NULL; Arg_t *pPrev = NULL; Arg_t *pNext = NULL; WORD nAddressArg; WORD nAddressRHS; WORD nAddressSym; WORD nAddressVal; int nParamLen = 0; int nArgsLeft = 0; while (iArg <= nArg) { pArg = & (g_aArgs[ iArg ]); pSrc = & (pArg->sArg[ 0 ]); if (bProcessMask & (1 << TOKEN_DOLLAR)) if (pArg->eToken == TOKEN_DOLLAR) // address { // TODO: Need to flag was a DOLLAR token for assembler pNext = NULL; nArgsLeft = (nArg - iArg); if (nArgsLeft > 0) { pNext = pArg + 1; _Arg_Shift( iArg + 1, nArgs, iArg ); nArg--; iArg--; // inc for start of next loop // Don't do register lookup pArg->bType |= TYPE_NO_REG; } else return ARG_SYNTAX_ERROR; } if (pArg->bType & TYPE_OPERATOR) // prev op type == address? { pPrev = NULL; // pLHS pNext = NULL; // pRHS nParamLen = 0; if (pArg->eToken == TOKEN_HASH) // HASH # immediate nParamLen = 1; nArgsLeft = (nArg - iArg); if (nArgsLeft < nParamLen) { return ARG_SYNTAX_ERROR; } pPrev = pArg - 1; if (nArgsLeft > 0) // These ops take at least 1 argument { pNext = pArg + 1; pSrc = &pNext->sArg[0]; nAddressVal = 0; if (ArgsGetValue( pNext, & nAddressRHS )) nAddressVal = nAddressRHS; bool bFound = FindAddressFromSymbol( pSrc, & nAddressSym ); if (bFound) { nAddressVal = nAddressSym; pArg->bSymbol = true; } if (bProcessMask & (1 << TOKEN_COMMA)) if (pArg->eToken == TOKEN_COMMA) // COMMMA , length { pPrev->nVal2 = nAddressVal; pPrev->eToken = TOKEN_COMMA; pPrev->bType |= TYPE_ADDRESS; pPrev->bType |= TYPE_LENGTH; nParamLen = 2; } if (bProcessMask & (1 << TOKEN_COLON)) if (pArg->eToken == TOKEN_COLON) // COLON : range { pPrev->nVal2 = nAddressVal; pPrev->eToken = TOKEN_COLON; pPrev->bType |= TYPE_ADDRESS; pPrev->bType |= TYPE_RANGE; nParamLen = 2; } if (bProcessMask & (1 << TOKEN_AMPERSAND)) if (pArg->eToken == TOKEN_AMPERSAND) // AND & delta { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } pPrev->nVal1 &= nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_PIPE)) if (pArg->eToken == TOKEN_PIPE) // OR | delta { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } pPrev->nVal1 |= nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_CARET)) if (pArg->eToken == TOKEN_CARET) // XOR ^ delta { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } pPrev->nVal1 ^= nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_PLUS)) if (pArg->eToken == TOKEN_PLUS) // PLUS + delta { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } pPrev->nVal1 += nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_MINUS)) if (pArg->eToken == TOKEN_MINUS) // MINUS - delta { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } pPrev->nVal1 -= nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_PERCENT)) if (pArg->eToken == TOKEN_PERCENT) // PERCENT % delta { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } pPrev->nVal1 %= nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_FSLASH)) if (pArg->eToken == TOKEN_FSLASH) // FORWARD SLASH / delta { if (pNext->eToken == TOKEN_FSLASH) // Comment { nArg = iArg - 1; return nArg; } if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { ArgsGetRegisterValue( pNext, & nAddressRHS ); } if (! nAddressRHS) nAddressRHS = 1; // divide by zero bug pPrev->nVal1 /= nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 2; } if (bProcessMask & (1 << TOKEN_EQUAL)) if (pArg->eToken == TOKEN_EQUAL) // EQUAL = assign { pPrev->nVal1 = nAddressRHS; pPrev->bType |= TYPE_VALUE; // signal already up to date nParamLen = 0; // need token for Smart BreakPoints } if (bProcessMask & (1 << TOKEN_HASH)) if (pArg->eToken == TOKEN_HASH) // HASH # immediate { _Arg_Shift( iArg + nParamLen, nArgs, iArg ); nArg--; pArg->nVal1 = nAddressRHS; pArg->bSymbol = false; pArg->bType = TYPE_VALUE | TYPE_ADDRESS | TYPE_NO_REG | TYPE_NO_SYM; nParamLen = 0; } if (bProcessMask & (1 << TOKEN_LESS_THAN)) if (pArg->eToken == TOKEN_LESS_THAN) // < { nParamLen = 0; } if (bProcessMask & (1 << TOKEN_GREATER_THAN)) if (pArg->eToken == TOKEN_GREATER_THAN) // > { nParamLen = 0; } if (bProcessMask & (1 << TOKEN_EXCLAMATION)) if (pArg->eToken == TOKEN_EXCLAMATION) // NOT_EQUAL ! { if (! ArgsGetImmediateValue( pNext, & nAddressRHS )) { if (! ArgsGetRegisterValue( pNext, & nAddressRHS )) { nAddressRHS = nAddressVal; } } pArg->nVal1 = ~nAddressRHS; pArg->bType |= TYPE_VALUE; // signal already up to date // Don't remove, since "SYM ! symbol" needs token to remove symbol } if (nParamLen) { _Arg_Shift( iArg + nParamLen, nArgs, iArg ); nArg -= nParamLen; iArg = 0; // reset args, to handle multiple operators } } else return ARG_SYNTAX_ERROR; } else // not an operator, try (1) address, (2) symbol lookup { nAddressArg = (WORD)(_tcstoul( pSrc, &pEnd2, BASE) & _6502_END_MEM_ADDRESS); if (! (pArg->bType & TYPE_NO_REG)) { ArgsGetRegisterValue( pArg, & nAddressArg ); } nAddressVal = nAddressArg; bool bFound = false; if (! (pArg->bType & TYPE_NO_SYM)) { bFound = FindAddressFromSymbol( pSrc, & nAddressSym ); if (bFound) { nAddressVal = nAddressSym; pArg->bSymbol = true; } } if (! (pArg->bType & TYPE_VALUE)) // already up to date? pArg->nVal1 = nAddressVal; pArg->bType |= TYPE_ADDRESS; } iArg++; } return nArg; }
//=========================================================================== void SymbolUpdate( SymbolTable_Index_e eSymbolTable, char *pSymbolName, WORD nAddress, bool bRemoveSymbol, bool bUpdateSymbol ) { 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) { char sText[ CONSOLE_WIDTH * 2 ]; sprintf( sText, " Updating %s%s%s from %s$%s%04X%s to %s$%s%04X%s" , CHC_SYMBOL, pSymbolName, CHC_DEFAULT , CHC_ARG_SEP , CHC_ADDRESS, nAddressPrev, CHC_DEFAULT , CHC_ARG_SEP , CHC_ADDRESS, nAddress, CHC_DEFAULT ); ConsolePrint( sText ); } } } else { if (bRemoveSymbol) { ConsoleBufferPush( TEXT(" Symbol not in table." ) ); } } if (bUpdateSymbol) { #if _DEBUG const char* pSymbol = FindSymbolFromAddress( nAddress, &iTable ); { // Found another symbol for this address. Harmless. // TODO: Probably should check if same name? } #endif g_aSymbols[ eSymbolTable ][ nAddress ] = pSymbolName; // Tell user symbol was added char sText[ CONSOLE_WIDTH * 2 ]; sprintf( sText, " Added symbol: %s%s%s %s$%s%04X%s" , CHC_SYMBOL, pSymbolName, CHC_DEFAULT , CHC_ARG_SEP , CHC_ADDRESS, nAddress, CHC_DEFAULT ); ConsolePrint( sText ); } } }
//=========================================================================== int ParseSymbolTable( TCHAR *pFileName, SymbolTable_Index_e eSymbolTableWrite, int nSymbolOffset ) { int nSymbolsLoaded = 0; if (! pFileName) return nSymbolsLoaded; //#if _UNICODE // TCHAR sFormat1[ MAX_SYMBOLS_LEN ]; // TCHAR sFormat2[ MAX_SYMBOLS_LEN ]; // wsprintf( sFormat1, "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s" // wsprintf( sFormat2, "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x" // ascii char sFormat1[ MAX_SYMBOLS_LEN ]; char sFormat2[ MAX_SYMBOLS_LEN ]; sprintf( sFormat1, "%%x %%%ds", MAX_SYMBOLS_LEN ); // i.e. "%x %13s" sprintf( sFormat2, "%%%ds %%x", MAX_SYMBOLS_LEN ); // i.e. "%13s %x" FILE *hFile = fopen(pFileName,"rt"); if( !hFile && g_bSymbolsDisplayMissingFile ) { ConsoleDisplayError( "Symbol File not found:" ); Print_Current_Path(); nSymbolsLoaded = -1; // HACK: ERROR: FILE NOT EXIST } bool bDupSymbolHeader = false; if( hFile ) { while( !feof(hFile) ) { // 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 ] = ""; if( !fgets(szLine, MAX_LINE-1, hFile) ) // Get next line { //ConsolePrint("<<EOF"); break; } if(strstr(szLine, "$") == NULL) { sscanf(szLine, sFormat1, &nAddress, sName); } else { char* p = strstr(szLine, "="); // Optional if(p) *p = ' '; p = strstr(szLine, "$"); if(p) *p = ' '; p = strstr(szLine, ";"); // Optional if(p) *p = 0; p = strstr(szLine, " "); // 1st space between name & value 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 } sscanf(szLine, sFormat2, sName, &nAddress); } // SymbolOffset nAddress += nSymbolOffset; if( (nAddress > _6502_MEM_END) || (sName[0] == 0) ) continue; #if 1 // _DEBUG // If updating symbol, print duplicate symbols WORD nAddressPrev; int iTable; bool bExists = FindAddressFromSymbol( sName, &nAddressPrev, &iTable ); if( bExists ) { char sText[ CONSOLE_WIDTH * 3 ]; if( !bDupSymbolHeader ) { bDupSymbolHeader = true; sprintf( sText, " %sDup Symbol Name%s (%s%s%s) %s" , CHC_ERROR , CHC_DEFAULT , CHC_STRING , g_aSymbolTableNames[ iTable ] , CHC_DEFAULT , pFileName ); ConsolePrint( sText ); } sprintf( sText, " %s$%s%04X %s%-31s%s" , CHC_ARG_SEP , CHC_ADDRESS , nAddress , CHC_SYMBOL , sName , CHC_DEFAULT ); ConsolePrint( sText ); } #endif g_aSymbols[ eSymbolTableWrite ] [ (WORD) nAddress ] = sName; nSymbolsLoaded++; } fclose(hFile); } return nSymbolsLoaded; }