diff --git a/bin/History.txt b/bin/History.txt index 5f3e6dc5..5ada7b8c 100644 --- a/bin/History.txt +++ b/bin/History.txt @@ -47,11 +47,19 @@ Changes: using uninitialized memory. RNDL/RHND and $620B are initialized to allow Pooyan, and the Beautiful Boot game launcher to run, along with $BFFD..BFFF to allow Copy ][ v5 to boot correctly. -. Debugger (v2.7.0.23): +. Debugger (v2.7.0.29): - Added: TSAVE "filename" to save the text screen to a file. It will auto-detect the current video mode: 40/80 columns. Default filename for 40 columns is: AppleWin_Text40.txt Default filename for 80 columns is: AppleWin_Text80.txt + - Changed: DS to ASC because DS is used as a common "Define Space" assembler directive + + - Added: Experimental "ASC" command to mark up data as Apple text. + using Castle Wolfenstien.DSK + BLOAD ^VOCAB + ASC name1 17DA:17F5 + - Fixed: DB address now auto-defines the symbol D_#### if no symbol is given. + - Added: Help for DB and DW. Fixes: . [Bug #206] Pooyan would freeze due to RNDL/RNDH not initialized to non-zero values on diff --git a/docs/Debugger_Changelog.txt b/docs/Debugger_Changelog.txt index cfdbf9c1..69618169 100644 --- a/docs/Debugger_Changelog.txt +++ b/docs/Debugger_Changelog.txt @@ -1,9 +1,19 @@ /* 2.7.0.# +.29 Added: Help for DB and DW +.28 Added: ASC so it disassemblies intertwined code and data correctly. + Example: + using Castle Wolfenstien.DSK + BLOAD ^VOCAB + ASC name1 17DA:17F5 +.27 Added: DB address now auto-defines the symbol D_#### +.26 Changed: DS to ASC because DS is used as "Define Space" assembler directive +.25 Fixed : DW address so that odd address work. + i.e. DW NEXT1 801 // AppleSoft Basic Line#1 Pointer to Next line .24 Added: TSAVE "filename" to save the text screen to file Default filename for 40 columns is: AppleWin_Text40.txt Default filename for 80 columns is: AppleWin_Text80.txt -.23 Fixed: HanG with Memory Move when memory ends at FFFF, i.e. 2000nEndAddress - pData->nStartAddress + 1; // *inclusive* KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes() + // Data Disassembler + // Smart Disassembly - Data Section + // Assemblyer Directives - Psuedo Mnemonics switch( pData->eElementType ) { - default : nOpbyte_ = 1; iOpmode_ = AM_M; break; case NOP_BYTE_1: nOpbyte_ = 1; iOpmode_ = AM_M; break; case NOP_BYTE_2: nOpbyte_ = 2; iOpmode_ = AM_M; break; case NOP_BYTE_4: nOpbyte_ = 4; iOpmode_ = AM_M; break; @@ -506,13 +506,23 @@ int _6502_GetOpmodeOpbyte ( const int nBaseAddress, int & iOpmode_, int & nOpby case NOP_ADDRESS:nOpbyte_ = 2; iOpmode_ = AM_A; // BUGFIX: 2.6.2.33 Define Address should be shown as Absolute mode, not Indirect Absolute mode. DA BASIC.FPTR D000:D080 // was showing as "da (END-1)" now shows as "da END-1" pData->nTargetAddress = *(LPWORD)(mem+nBaseAddress); break; + case NOP_STRING_APPLE: + iOpmode_ = AM_DATA; + nOpbyte_ = nSlack; + break; case NOP_STRING_APPLESOFT: // TODO: FIXME: scan memory for high byte nOpbyte_ = 8; - iOpmode_ = AM_M; + iOpmode_ = AM_DATA; break; + default: +#if _DEBUG // not implemented! + int *fatal = 0; + *fatal = 0xDEADC0DE; +#endif } - +/* + // REMOVED in v1.25 ... because of AppleSoft Basic: DW NEXT1 801 DW LINE1 803 // Check if we are not element aligned ... nSlack = (nOpbyte_ > 1) ? (nBaseAddress & nOpbyte_-1 ) : 0; if (nSlack) @@ -520,7 +530,7 @@ int _6502_GetOpmodeOpbyte ( const int nBaseAddress, int & iOpmode_, int & nOpby nOpbyte_ = nSlack; iOpmode_ = AM_M; } - +*/ //iOpcode_ = NUM_OPCODES; // Don't have valid opcodes ... we have data ! // iOpcode_ = (int)( pData ); // HACK: pass pData back to caller ... iOpcode_ = 0xEA; // OP_NOP diff --git a/source/Debugger/Debugger_Commands.cpp b/source/Debugger/Debugger_Commands.cpp index 75e1de07..03f69141 100644 --- a/source/Debugger/Debugger_Commands.cpp +++ b/source/Debugger/Debugger_Commands.cpp @@ -1,7 +1,7 @@ /* AppleWin : An Apple //e emulator for Windows -Copyright (C) 2009-2010, Tom Charlesworth, Michael Pohoreski +Copyright (C) 2009-2014, 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 @@ -130,7 +130,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA {TEXT("DW") , CmdDisasmDataDefWord1 , CMD_DEFINE_DATA_WORD1, "Define address array" }, {TEXT("DW2") , CmdDisasmDataDefWord2 , CMD_DEFINE_DATA_WORD2, "Define address array, display 2 words/line" }, {TEXT("DW4") , CmdDisasmDataDefWord4 , CMD_DEFINE_DATA_WORD4, "Define address array, display 4 words/line" }, - {TEXT("DS") , CmdDisasmDataDefString , CMD_DEFINE_DATA_STR , "Define string" }, + {TEXT("ASC") , CmdDisasmDataDefString , CMD_DEFINE_DATA_STR , "Define text string" }, // 2.7.0.26 Changed: DS to ASC because DS is used as "Define Space" assembler directive // {TEXT("DF") , CmdDisasmDataDefFloat , CMD_DEFINE_DATA_FLOAT, "Define AppleSoft (packed) Float" }, // {TEXT("DFX") , CmdDisasmDataDefFloatUnpack , CMD_DEFINE_DATA_FLOAT2,"Define AppleSoft (unpacked) Float" }, // with symbol lookup diff --git a/source/Debugger/Debugger_DisassemblerData.cpp b/source/Debugger/Debugger_DisassemblerData.cpp index 74f3b5e4..cff01e5c 100644 --- a/source/Debugger/Debugger_DisassemblerData.cpp +++ b/source/Debugger/Debugger_DisassemblerData.cpp @@ -1,7 +1,7 @@ /* AppleWin : An Apple //e emulator for Windows -Copyright (C) 2006-2010, Tom Charlesworth, Michael Pohoreski +Copyright (C) 2006-2014, 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 @@ -42,7 +42,11 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_) memset( (void*) &tData_, 0, sizeof(tData_) ); - if( nArgs < 2 ) + // DB address + // DB symbol + // bool bisAddress ... + + if( nArgs < 1 ) { nAddress = g_nDisasmCurAddress; } @@ -53,37 +57,52 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_) (eRange == RANGE_HAS_LEN)) { Range_CalcEndLen( eRange, nAddress, nAddress2, nEnd, nLen ); - //dArg = 2; + nLen--; // Disassembly_IsDataAddress() is *inclusive* // KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes() } else { + if( nArgs > 1 ) nAddress = g_aArgs[ 2 ].nValue; + else + nAddress = g_aArgs[ 1 ].nValue; } } +/* + // Removed so DW 801 works if (!nLen) { nLen = 1; } +*/ tData_.nStartAddress = nAddress; tData_.nEndAddress = nAddress + nLen; // tData_.nArraySize = 0; + char *pSymbolName = ""; - if( nArgs ) + char aSymbolName[ 32 ]; + SymbolTable_Index_e eSymbolTable = SYMBOLS_ASSEMBLY; + + if( nArgs > 1 ) { 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 + // 'DB' with 1 arg + // DB 801 + // auto define D_# DB $XX + sprintf( aSymbolName, "D_%04X", tData_.nStartAddress ); + pSymbolName = aSymbolName; } + // bRemoveSymbol = false // use arg[2] + // bUpdateSymbol = true // add the symbol to the table + SymbolUpdate( eSymbolTable, pSymbolName, nAddress, false, true ); + + // TODO: Note: need to call ConsoleUpdate(), as may print symbol has been updated + strcpy( tData_.sSymbol, pSymbolName ); return nAddress; @@ -115,6 +134,8 @@ Update_t CmdDisasmDataDefCode (int nArgs) // TODO: Do we need to split the data !? //Disassembly_DelData( tData ); pData->iDirective = _NOP_REMOVED; + + // TODO: Remove symbol 'D_FA62' from symbol table! } else { @@ -144,10 +165,13 @@ char* g_aNopcodeTypes[ NUM_NOPCODE_TYPES ] = ,"bmp " }; +// Command: B +// no args // List the data blocks //=========================================================================== Update_t CmdDisasmDataList (int nArgs) { + // Need to iterate through all blocks DisasmData_t* pData = NULL; char sText[ CONSOLE_WIDTH * 2 ]; @@ -170,7 +194,7 @@ Update_t CmdDisasmDataList (int nArgs) , pData->nStartAddress , CHC_ARG_SEP , CHC_ADDRESS - , pData->nEndAddress - 1 + , pData->nEndAddress // Disassembly_IsDataAddress() is *inclusive* // KEEP IN SYNC: _CmdDefineByteRange() CmdDisasmDataList() _6502_GetOpmodeOpbyte() FormatNopcodeBytes() ); ConsolePrint( sText ); } @@ -184,13 +208,14 @@ Update_t CmdDisasmDataList (int nArgs) Update_t _CmdDisasmDataDefByteX (int nArgs) { // DB - // DB symbol + // DB symbol // use current instruction pointer // DB symbol address // DB symbol range:range + // DB address + // To "return to code" use ."X" int iCmd = g_aArgs[0].nValue - NOP_BYTE_1; -// if ((!nArgs) || (nArgs > 2)) - if (! ((nArgs <= 2) || (nArgs == 4))) + if (nArgs > 3) // ! ((nArgs < 2) || (nArgs == 4))) { return Help_Arg_1( CMD_DEFINE_DATA_BYTE1 + iCmd ); } @@ -222,10 +247,16 @@ Update_t _CmdDisasmDataDefByteX (int nArgs) //=========================================================================== Update_t _CmdDisasmDataDefWordX (int nArgs) { - // DW - // DW symbol - // DW symbol address - // DW symbol range:range +/* + Usage: + DW + DW symbol + DW symbol address + DW symbol range:range + DW address Auto-define D_#### where # is the address + Examples: + DW +*/ int iCmd = g_aArgs[0].nValue - NOP_WORD_1; if (! ((nArgs <= 2) || (nArgs == 4))) @@ -301,12 +332,14 @@ Update_t CmdDisasmDataDefAddress16 (int nArgs) return UPDATE_DISASM | ConsoleUpdate(); } +// DB Update_t CmdDisasmDataDefByte1 ( int nArgs ) { g_aArgs[0].nValue = NOP_BYTE_1; return _CmdDisasmDataDefByteX( nArgs ); } +// DB2 Update_t CmdDisasmDataDefByte2 ( int nArgs ) { g_aArgs[0].nValue = NOP_BYTE_2; @@ -325,12 +358,14 @@ Update_t CmdDisasmDataDefByte8 ( int nArgs ) return _CmdDisasmDataDefByteX( nArgs ); } +// DW Update_t CmdDisasmDataDefWord1 ( int nArgs ) { g_aArgs[0].nValue = NOP_WORD_1; return _CmdDisasmDataDefWordX( nArgs ); } +// DW2 Update_t CmdDisasmDataDefWord2 ( int nArgs ) { g_aArgs[0].nValue = NOP_WORD_2; @@ -343,9 +378,31 @@ Update_t CmdDisasmDataDefWord4 ( int nArgs ) return _CmdDisasmDataDefWordX( nArgs ); } +// Command: DS Update_t CmdDisasmDataDefString ( int nArgs ) { - return UPDATE_DISASM; + int iCmd = 0; // Define Ascii, AppleText, MixedText (DOS3.3) + + DisasmData_t tData; + int iArg = 2; + WORD nAddress = _CmdDefineByteRange( nArgs, iArg, tData ); + + tData.iDirective = g_aAssemblerFirstDirective[ g_iAssemblerSyntax ] + ASM_DEFINE_APPLE_TEXT; + + tData.eElementType = (Nopcode_e)( NOP_STRING_APPLE + 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(); } // __ Disassembler View Interface ____________________________________________________________________ @@ -366,7 +423,7 @@ DisasmData_t* Disassembly_Enumerate( DisasmData_t *pCurrent ) { pCurrent++; if (pCurrent <= pEnd) - pData = pCurrent; + pData = pCurrent; } else { pData = pBegin; } @@ -389,7 +446,7 @@ DisasmData_t* Disassembly_IsDataAddress ( WORD nAddress ) { if( pData->iDirective != _NOP_REMOVED ) { - if( (nAddress >= pData->nStartAddress) && (nAddress < pData->nEndAddress) ) + if( (nAddress >= pData->nStartAddress) && (nAddress <= pData->nEndAddress) ) { return pData; } diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index 38a80df2..dd971ff6 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -4,7 +4,7 @@ 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-2010, Tom Charlesworth, Michael Pohoreski +Copyright (C) 2006-2014, 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 @@ -1551,6 +1551,7 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ ) strcpy( line_.sMnemonic, g_aOpcodes[ line_.iOpcode ].sMnemonic ); } + // TODO: BUG! _sOpcOdes overflow! int nSpaces = strlen( line_.sOpCodes ); while (nSpaces < (int)nMinBytesLen) { @@ -1603,6 +1604,12 @@ void FormatOpcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ ) void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ ) { char *pDst = line_.sTarget; + 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); @@ -1643,8 +1650,27 @@ void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ ) strncpy( pDst, (const char*)(mem + nBaseAddress), iByte ); pDst += iByte; *pDst = 0; + case NOP_STRING_APPLE: + iByte = line_.nOpbyte; // handled all bytes of text + if( len > MAX_IMMEDIATE_LEN ) + len = MAX_IMMEDIATE_LEN; + + *pDst++ = '"'; + for( int i = 0; i < len; i++ ) // iNopcode = Length of Data + *pDst++ = *(const char*)(mem + nStartAddress + i) & 0x7F; + *pDst++ = '"'; + + if( nDisplayLen > len ) // ellipsis + { + *pDst++ = '.'; + *pDst++ = '.'; + *pDst++ = '.'; + } + + *pDst = 0; + break; default: -#if _DEBUG +#if _DEBUG // Unhandled data disassembly! int *FATAL = 0; *FATAL = 0xDEADC0DE; #endif diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp index 2dfcde8d..b92223ba 100644 --- a/source/Debugger/Debugger_Help.cpp +++ b/source/Debugger/Debugger_Help.cpp @@ -4,7 +4,7 @@ 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-2010, Tom Charlesworth, Michael Pohoreski +Copyright (C) 2006-2014, 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 @@ -1100,6 +1100,51 @@ Update_t CmdHelpSpecific (int nArgs) ConsoleBufferPush( sText ); */ break; + // Disasm + case CMD_DEFINE_DATA_BYTE1: + sprintf( sTemp, " Usage: %s
| | ", pCommand->m_sName ); + Colorize( sText, sTemp ); + ConsolePrint( sText ); + + ConsoleBufferPush( TEXT(" Tell the diassembler to treat the BYTES as data instead of code." ) ); + + Help_Examples(); + sprintf( sText, "%s %s WNDTOP 22", CHC_EXAMPLE, pCommand->m_sName ); + ConsolePrint( sText ); + sprintf( sText, "%s %s WNDBTM 23", CHC_EXAMPLE, pCommand->m_sName ); + ConsolePrint( sText ); + sprintf( sText, "%s %s WNDTOP // treat as code again", CHC_EXAMPLE, g_aCommands[ CMD_DISASM_CODE ].m_sName ); + ConsolePrint( sText ); + sprintf( sText, "%s %s // list all addresses viewed as data", CHC_EXAMPLE, g_aCommands[ CMD_DISASM_LIST ].m_sName ); + ConsolePrint( sText ); + break; + + case CMD_DEFINE_DATA_WORD1: + // DW // use current debug line + // DW symbol + // DW symbol address + // DW symbol range:range + // DW address + sprintf( sTemp, " Usage: %s
| | ", pCommand->m_sName ); + Colorize( sText, sTemp ); + ConsolePrint( sText ); + + ConsoleBufferPush( TEXT(" Tell the diassembler to treat the WORDS as data instead of code." ) ); + + sprintf( sTemp, " The data is a range of 2-byte pointer data."); + Colorize( sText, sTemp ); + ConsolePrint( sText ); + + Help_Examples(); + sprintf( sText, "%s %s NEXT1 801 // AppleSoft Basic Line#1 Pointer to Next line", CHC_EXAMPLE, pCommand->m_sName ); + ConsolePrint( sText ); + sprintf( sText, "%s %s LINE1 803 // Applesoft Basic Line#1 Line Number", CHC_EXAMPLE, pCommand->m_sName ); + ConsolePrint( sText ); + sprintf( sText, "%s %s NEXT1 // treat as code again", CHC_EXAMPLE, g_aCommands[ CMD_DISASM_CODE ].m_sName ); + ConsolePrint( sText ); + sprintf( sText, "%s %s // list all addresses viewed as data", CHC_EXAMPLE, g_aCommands[ CMD_DISASM_LIST ].m_sName ); + ConsolePrint( sText ); + break; // Memory case CMD_MEMORY_ENTER_BYTE: diff --git a/source/Debugger/Debugger_Symbols.cpp b/source/Debugger/Debugger_Symbols.cpp index dfeee236..0be9fd6f 100644 --- a/source/Debugger/Debugger_Symbols.cpp +++ b/source/Debugger/Debugger_Symbols.cpp @@ -4,7 +4,7 @@ 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-2010, Tom Charlesworth, Michael Pohoreski +Copyright (C) 2006-2014, 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 @@ -793,6 +793,15 @@ void SymbolUpdate( SymbolTable_Index_e eSymbolTable, char *pSymbolName, WORD nAd } #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 ); } } } diff --git a/source/Debugger/Debugger_Types.h b/source/Debugger/Debugger_Types.h index 41f20419..c974e02b 100644 --- a/source/Debugger/Debugger_Types.h +++ b/source/Debugger/Debugger_Types.h @@ -104,7 +104,7 @@ , AM_NZY // 14 Indirect (Zeropage) Indexed, Y , AM_NZ // 15 Indirect (Zeropage) , AM_NA // 16 Indirect (Absolute) i.e. JMP - + , AM_DATA // Not an opcode! Markup as data , NUM_ADDRESSING_MODES , NUM_OPMODES = NUM_ADDRESSING_MODES , AM_I = NUM_ADDRESSING_MODES, // for assemler @@ -888,9 +888,10 @@ enum DisasmText_e { - nMaxAddressLen = 40, + MAX_ADDRESS_LEN = 40, nMaxOpcodes = 3, CHARS_FOR_ADDRESS = 8, // 4 digits + end-of-string + padding + MAX_IMMEDIATE_LEN = 16, // Data Disassembly }; struct DisasmLine_t @@ -914,7 +915,7 @@ const DisasmData_t* pDisasmData; // int nTarget; // address -> string - char sTarget [nMaxAddressLen]; + char sTarget [ MAX_ADDRESS_LEN ]; char sTargetOffset[ CHARS_FOR_ADDRESS ]; // +/- 255, realistically +/-1 int nTargetOffset;