diff --git a/AppleWin/source/Debugger_DisassemblerData.cpp b/AppleWin/source/Debugger_DisassemblerData.cpp new file mode 100644 index 00000000..3a5374f1 --- /dev/null +++ b/AppleWin/source/Debugger_DisassemblerData.cpp @@ -0,0 +1,367 @@ +/* +AppleWin : An Apple //e emulator for Windows + +/* Description: Data Blocks shown in Disassembler + * + * Author: Copyright (C) 2009 Michael Pohoreski + */ + +#include "StdAfx.h" +#pragma hdrstop + +// Disassembler Data ______________________________________________________________________________ + +// __ Debugger Interaface ____________________________________________________________________________ + +//=========================================================================== +WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_) +{ + WORD nAddress = 0; + WORD nAddress2 = 0; + WORD nEnd = 0; + int nLen = 0; + + if( nArgs < 2 ) + { + nAddress = g_nDisasmCurAddress; + } + else + { + RangeType_t eRange = Range_Get( nAddress, nAddress2, iArg); + if ((eRange == RANGE_HAS_END) || + (eRange == RANGE_HAS_LEN)) + { + Range_CalcEndLen( eRange, nAddress, nAddress2, nEnd, nLen ); + //dArg = 2; + } + else + { + nAddress = g_aArgs[ 2 ].nValue; + } + } + + if (!nLen) + { + nLen = 1; + } + + tData_.nStartAddress = nAddress; + tData_.nEndAddress = nAddress + nLen; + + char *pSymbolName = ""; + if( nArgs ) + { + pSymbolName = g_aArgs[ 1 ].sArg; + SymbolTable_Index_e eSymbolTable = SYMBOLS_ASSEMBLY; + // bRemoveSymbol = false // use arg[2] + // bUpdateSymbol = true // add the symbol to the table + SymbolUpdate( eSymbolTable, pSymbolName, nAddress, false, true ); + // Note: need to call ConsoleUpdate(), as may print symbol has been updated + } + else + { + // TODO: 'DB' with no args, should define D_# DB $XX + } + + strcpy( tData_.sSymbol, pSymbolName ); + + return nAddress; +} + +// Undefine Data +//=========================================================================== +Update_t CmdDisasmDataDefCode (int nArgs) +{ + // treat memory (bytes) as code + if (! ((nArgs <= 2) || (nArgs == 4))) + { + return Help_Arg_1( CMD_DISASM_CODE ); + } + + DisasmData_t tData; + int iArg = 2; + WORD nAddress = _CmdDefineByteRange( nArgs, iArg, tData ); + + // Need to iterate through all blocks + // DB TEST1 300:320 + // DB TEST2 310:330 + // DB TEST3 320:340 + // !DB 300 + + DisasmData_t *pData = Disassembly_IsDataAddress( nAddress ); + if( pData ) + { + // Need to split the data +// *pData = tData; + Disassembly_AddData( tData ); + } + else + { + Disassembly_DelData( tData ); + } + + return UPDATE_DISASM | ConsoleUpdate(); +} + +// List the data blocks +//=========================================================================== +Update_t CmdDisasmDataList (int nArgs) +{ + // Need to iterate through all blocks + DisasmData_t* pData = NULL; + char sText[ CONSOLE_WIDTH ]; + while( pData = Disassembly_Enumerate( pData ) ) + { + // `TEST `300`:`320 + sprintf( sText, "%s%s %s%04X%s:%s%04X\n" + , CHC_SYMBOL + , pData->sSymbol + , CHC_ADDRESS + , pData->nStartAddress + , CHC_ARG_SEP + , pData->nEndAddress + ); + ConsolePrint( sText ); + } + + return UPDATE_DISASM | ConsoleUpdate(); +} + +// Common code +//=========================================================================== +Update_t _CmdDisasmDataDefByteX (int nArgs) +{ + // DB + // DB symbol + // DB symbol address + // symbol range:range + int iCmd = NOP_BYTE_1 - g_aArgs[0].nValue; + + if (! ((nArgs <= 2) || (nArgs == 4))) + { + return Help_Arg_1( CMD_DEFINE_DATA_BYTE1 + iCmd ); + } + + DisasmData_t tData; + int iArg = 2; + WORD nAddress = _CmdDefineByteRange( nArgs, iArg, tData ); + + tData.iDirective = FIRST_M_DIRECTIVE + ASM_M_DEFINE_BYTE; + tData.eElementType = NOP_BYTE_1 + iCmd; + tData.bSymbolLookup = false; + tData.nTargetAddress = 0; + + // Already exists, so update + DisasmData_t *pData = Disassembly_IsDataAddress( nAddress ); + if( pData ) + { + *pData = tData; + } + else + Disassembly_AddData( tData ); + + return UPDATE_DISASM | ConsoleUpdate(); +} + +//=========================================================================== +Update_t _CmdDisasmDataDefWordX (int nArgs) +{ + // DW + // DW symbol + // DW symbol address + // symbol range:range + int iCmd = NOP_WORD_1 - g_aArgs[0].nValue; + + if (! ((nArgs <= 2) || (nArgs == 4))) + { + return Help_Arg_1( CMD_DEFINE_DATA_WORD1 + iCmd ); + } + + DisasmData_t tData; + int iArg = 2; + WORD nAddress = _CmdDefineByteRange( nArgs, iArg, tData ); + + tData.iDirective = FIRST_M_DIRECTIVE + ASM_M_DEFINE_WORD; + tData.eElementType = NOP_WORD_1 + iCmd; + tData.bSymbolLookup = false; + tData.nTargetAddress = 0; + + // Already exists, so update + DisasmData_t *pData = Disassembly_IsDataAddress( nAddress ); + if( pData ) + { + *pData = tData; + } + else + Disassembly_AddData( tData ); + + return UPDATE_DISASM | ConsoleUpdate(); +} + +//=========================================================================== +Update_t CmdDisasmDataDefAddress8H (int nArgs) +{ + return UPDATE_DISASM; +} + +//=========================================================================== +Update_t CmdDisasmDataDefAddress8L (int nArgs) +{ + return UPDATE_DISASM; +} + +//=========================================================================== +Update_t CmdDisasmDataDefAddress16 (int nArgs) +{ + return UPDATE_DISASM; +} + +Update_t CmdDisasmDataDefByte1 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_BYTE_1; + return _CmdDisasmDataDefByteX( nArgs ); +} + +Update_t CmdDisasmDataDefByte2 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_BYTE_2; + return _CmdDisasmDataDefByteX( nArgs ); +} + +Update_t CmdDisasmDataDefByte4 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_BYTE_4; + return _CmdDisasmDataDefByteX( nArgs ); +} + +Update_t CmdDisasmDataDefByte8 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_BYTE_8; + return _CmdDisasmDataDefByteX( nArgs ); +} + +Update_t CmdDisasmDataDefWord1 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_WORD_1; + return _CmdDisasmDataDefWordX( nArgs ); +} + +Update_t CmdDisasmDataDefWord2 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_WORD_2; + return _CmdDisasmDataDefWordX( nArgs ); +} + +Update_t CmdDisasmDataDefWord4 ( int nArgs ) +{ + g_aArgs[0].nValue = NOP_WORD_4; + return _CmdDisasmDataDefWordX( nArgs ); +} + +Update_t CmdDisasmDataDefString ( int nArgs ) +{ + return UPDATE_DISASM; +} + +// __ Disassembler View Interface ____________________________________________________________________ + +/// @param pCurrent NULL start a new serch, or continue enumerating +//=========================================================================== +DisasmData_t* Disassembly_Enumerate( DisasmData_t *pCurrent ) +{ + DisasmData_t *pData = NULL; // bIsNopcode = false + int nDataTargets = g_aDisassemblerData.size(); + + if( pCurrent ) + { + pCurrent++; + pData = & g_aDisassemblerData[ nDataTargets ]; + if( pCurrent < pData ) + return pCurrent; + else + return NULL; + } + else + { + pData = & g_aDisassemblerData[ 0 ]; + if( nDataTargets ) + return pData; + else + return NULL; + } +} + +// returns NULL if address has no data associated with it +//=========================================================================== +DisasmData_t* Disassembly_IsDataAddress ( WORD nAddress ) +{ + DisasmData_t *pData = NULL; // bIsNopcode = false + int nDataTargets = g_aDisassemblerData.size(); + + if( nDataTargets ) + { + // TODO: Replace with binary search -- should store data in sorted order, via start address + pData = & g_aDisassemblerData[ 0 ]; + for( int iTarget = 0; iTarget < nDataTargets; iTarget++ ) + { + if( (nAddress >= pData->nStartAddress) && (nAddress < pData->nEndAddress) ) + { + return pData; + } + pData++; + } + pData = NULL; // bIsNopCode = false + } + return pData; +} + +//=========================================================================== +void Disassembly_AddData( DisasmData_t tData) +{ + g_aDisassemblerData.push_back( tData ); +} + +//=========================================================================== +void Disassembly_GetData ( WORD nBaseAddress, const DisasmData_t *pData, DisasmLine_t & line_ ) +{ + line_.ClearFlags(); + + line_.iNoptype = pData->eElementType; + switch( pData->eElementType ) + { + case NOP_BYTE_1: + line_.nOpbyte = 1; + break; + case NOP_BYTE_2: + line_.nOpbyte = 2; + break; + case NOP_WORD_1: + line_.nOpbyte= 2; + break; + case NOP_WORD_2: + line_.nOpbyte= 4; + break; + case NOP_STRING_APPLESOFT: + // scan memory for high byte + line_.nOpbyte = 8; + break; + default: + line_.nOpbyte = 1; + break; + } + + FormatOpcodeBytes( nBaseAddress, line_ ); + + //pMnemonic = g_aOpcodes[ iOpcode ].sMnemonic; + line_.iNopcode = pData->iDirective; + strcpy( line_.sMnemonic, g_aAssemblerDirectives[ line_.iNopcode ].m_pMnemonic ); + + FormatNopcodeBytes( nBaseAddress, line_ ); +} + +//=========================================================================== +void Disassembly_DelData( DisasmData_t tData) +{ + // g_aDisassemblerData.erase( ); +} + diff --git a/AppleWin/source/Debugger_DisassemblerData.h b/AppleWin/source/Debugger_DisassemblerData.h new file mode 100644 index 00000000..8d83b3fc --- /dev/null +++ b/AppleWin/source/Debugger_DisassemblerData.h @@ -0,0 +1,55 @@ +#ifndef DEBUGGER_DISASSEMBLERDATA_H +#define DEBUGGER_DISASSEMBLERDATA_H + + enum NopcodeType_e + { + NOP_BYTE_1 // 1 bytes/line + ,NOP_BYTE_2 // 2 bytes/line + ,NOP_BYTE_4 // 4 bytes/line + ,NOP_BYTE_8 // 8 bytes/line + ,NOP_WORD_1 // 1 words/line + ,NOP_WORD_2 // 2 words/line + ,NOP_WORD_4 // 4 words/line + ,NOP_ADDRESS// 1 word/line + ,NOP_HEX + ,NOP_CHAR + ,NOP_STRING_ASCII + ,NOP_STRING_APPLE + ,NOP_STRING_APPLESOFT + ,NOP_FAC + ,NUM_NOPCODE_TYPES + }; + + // Disassembler Data + // type symbol[start:end] + struct DisasmData_t + { + char sSymbol[ MAX_SYMBOLS_LEN+1 ]; + WORD iDirective ; // Assembler directive -> nopcode + WORD nStartAddress; // link to block [start,end) + WORD nEndAddress ; + WORD nArraySize ; // Total bytes +// WORD nBytePerRow ; // 1, 8 + char eElementType; // + + // with symbol lookup + char bSymbolLookup ; + WORD nTargetAddress; + }; + + Update_t _CmdDisasmDataDefByteX (int nArgs); + Update_t _CmdDisasmDataDefWordX (int nArgs); + +// Data Disassembler ______________________________________________________________________________ + + int Disassembly_FindOpcode( WORD nAddress ); + DisasmData_t* Disassembly_IsDataAddress( WORD nAddress ); + + void Disassembly_AddData( DisasmData_t tData); + void Disassembly_GetData ( WORD nBaseAddress, const DisasmData_t *pData_, DisasmLine_t & line_ ); + void Disassembly_DelData( DisasmData_t tData); + DisasmData_t* Disassembly_Enumerate( DisasmData_t *pCurrent = NULL ); + + extern vector g_aDisassemblerData; + +#endif diff --git a/AppleWin/source/Debugger_Range.cpp b/AppleWin/source/Debugger_Range.cpp new file mode 100644 index 00000000..c0dd270c --- /dev/null +++ b/AppleWin/source/Debugger_Range.cpp @@ -0,0 +1,123 @@ +/* +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 +Copyright (C) 2006-2009, Tom Charlesworth, Michael Pohoreski + +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 Utility Range + * + * Author: Copyright (C) 2006-2009 Michael Pohoreski + */ + +#include "StdAfx.h" +#pragma hdrstop + +// Util - Range _______________________________________________________________ + + +//=========================================================================== +bool Range_CalcEndLen( const RangeType_t eRange + , const WORD & nAddress1, const WORD & nAddress2 + , WORD & nAddressEnd_, int & nAddressLen_ ) +{ + bool bValid = false; + + if (eRange == RANGE_HAS_LEN) + { + // BSAVE 2000,0 Len=0 End=n/a + // BSAVE 2000,1 Len=1 End=2000 + // 0,FFFF [,) + // End = FFFE = Len-1 + // Len = FFFF + nAddressLen_ = nAddress2; + int nTemp = nAddress1 + nAddressLen_ - 1; + if (nTemp > _6502_MEM_END) + nTemp = _6502_MEM_END; + nAddressEnd_ = nTemp; + bValid = true; + } + else + if (eRange == RANGE_HAS_END) + { + // BSAVE 2000:2000 Len=0, End=n/a + // BSAVE 2000:2001 Len=1, End=2000 + // 0:FFFF [,] + // End = FFFF + // Len = 10000 = End+1 + nAddressEnd_ = nAddress2; + nAddressLen_ = nAddress2 - nAddress1 + 1; + bValid = true; + } + + return bValid; +} + + +//=========================================================================== +RangeType_t Range_Get( WORD & nAddress1_, WORD & nAddress2_, const int iArg ) // =1 +{ + nAddress1_ = (unsigned) g_aArgs[ iArg ].nValue; + if (nAddress1_ > _6502_MEM_END) + nAddress1_ = _6502_MEM_END; + + nAddress2_ = 0; + int nTemp = 0; + + RangeType_t eRange = RANGE_MISSING_ARG_2; + + if (g_aArgs[ iArg + 1 ].eToken == TOKEN_COMMA) + { + // 0,FFFF [,) // Note the mathematical range + // End = FFFE = Len-1 + // Len = FFFF + eRange = RANGE_HAS_LEN; + nTemp = g_aArgs[ iArg + 2 ].nValue; + nAddress2_ = nTemp; + } + else + if (g_aArgs[ iArg + 1 ].eToken == TOKEN_COLON) + { + // 0:FFFF [,] // Note the mathematical range + // End = FFFF + // Len = 10000 = End+1 + eRange = RANGE_HAS_END; + nTemp = g_aArgs[ iArg + 2 ].nValue; + + // i.e. + // FFFF:D000 + // 1 2 Temp + // FFFF D000 + // FFFF + // D000 + if (nAddress1_ > nTemp) + { + nAddress2_ = nAddress1_; + nAddress1_ = nTemp; + } + else + nAddress2_ = nTemp; + } + + // .17 Bug Fix: D000,FFFF -> D000,CFFF (nothing searched!) +// if (nTemp > _6502_MEM_END) +// nTemp = _6502_MEM_END; + + return eRange; +} diff --git a/AppleWin/source/Debugger_Range.h b/AppleWin/source/Debugger_Range.h new file mode 100644 index 00000000..7663ef87 --- /dev/null +++ b/AppleWin/source/Debugger_Range.h @@ -0,0 +1,4 @@ + RangeType_t Range_Get( WORD & nAddress1_, WORD &nAddress2_, const int iArg = 1 ); + bool Range_CalcEndLen( const RangeType_t eRange + , const WORD & nAddress1, const WORD & nAddress2 + , WORD & nAddressEnd_, int & nAddressLen_ );