/* 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, 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 * * Author: Copyright (C) 2006, Michael Pohoreski */ #include "StdAfx.h" #pragma hdrstop #include // Public _________________________________________________________________________________________ const int DISPLAY_HEIGHT = 384; // 368; // DISPLAY_LINES * g_nFontHeight; FontConfig_t g_aFontConfig[ NUM_FONTS ]; // Private ________________________________________________________________________________________ // Disassembly /* * 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 */ TCHAR g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = TEXT(" ^\x35"); TCHAR g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = TEXT(" =\x33"); TCHAR g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = TEXT(" v\x36"); // Drawing // Width const int DISPLAY_WIDTH = 560; #define SCREENSPLIT1 356 // Horizontal Column (pixels?) of Stack & Regs // #define SCREENSPLIT2 456 // Horizontal Column (pixels?) of BPs, Watches & Mem const int SCREENSPLIT2 = 456-7; // moved left one "char" to show PC in breakpoint: const int DISPLAY_BP_COLUMN = SCREENSPLIT2; const int DISPLAY_MINI_CONSOLE = SCREENSPLIT1 - 6; // - 1 chars const int DISPLAY_DISASM_RIGHT = SCREENSPLIT1 - 6; // - 1 char const int DISPLAY_FLAG_COLUMN = SCREENSPLIT1 + 63; const int DISPLAY_MINIMEM_COLUMN = SCREENSPLIT2 + 7; const int DISPLAY_REGS_COLUMN = SCREENSPLIT1; const int DISPLAY_STACK_COLUMN = SCREENSPLIT1; const int DISPLAY_TARGETS_COLUMN = SCREENSPLIT1; const int DISPLAY_WATCHES_COLUMN = SCREENSPLIT2; const int DISPLAY_ZEROPAGE_COLUMN= SCREENSPLIT1; const int MAX_DISPLAY_STACK_LINES = 8; // Height // const int DISPLAY_LINES = 24; // FIXME: Should be pixels // 304 = bottom of disassembly // 368 = bottom console // 384 = 16 * 24 very bottom const int DEFAULT_HEIGHT = 16; static HDC g_hDC = 0; static void SetupColorsHiLoBits ( HDC dc, bool bHiBit, bool bLoBit, const int iBackground, const int iForeground, const int iColorHiBG , /*const int iColorHiFG, const int iColorLoBG , */const int iColorLoFG ); static char ColorizeSpecialChar( HDC hDC, TCHAR * sText, BYTE nData, const MemoryView_e iView, const int iTxtBackground = BG_INFO , const int iTxtForeground = FG_DISASM_CHAR, const int iHighBackground = BG_INFO_CHAR, const int iHighForeground = FG_INFO_CHAR_HI, const int iLowBackground = BG_INFO_CHAR, const int iLowForeground = FG_INFO_CHAR_LO ); char FormatCharTxtAsci ( const BYTE b, bool * pWasAsci_ ); int FormatDisassemblyLine( WORD nOffset, int iMode, int nOpBytes, char *sAddress_, char *sOpCodes_, char *sTarget_, char *sTargetOffset_, int & nTargetOffset_, char * sImmediate_, char & nImmediate_, char *sBranch_ ); void DrawSubWindow_Code ( int iWindow ); void DrawSubWindow_IO (Update_t bUpdate); void DrawSubWindow_Source1 (Update_t bUpdate); void DrawSubWindow_Source2 (Update_t bUpdate); void DrawSubWindow_Symbols (Update_t bUpdate); void DrawSubWindow_ZeroPage (Update_t bUpdate); void DrawWindowBottom ( Update_t bUpdate, int iWindow ); // Utility ________________________________________________________________________________________ //=========================================================================== bool CanDrawDebugger() { if (g_bDebuggerViewingAppleOutput) return false; if ((mode == MODE_DEBUG) || (mode == MODE_STEPPING)) return true; return false; } //=========================================================================== int DebugDrawText ( LPCTSTR pText, RECT & rRect ) { int nLen = _tcslen( pText ); ExtTextOut( g_hDC, rRect.left, rRect.top, ETO_CLIPPED | ETO_OPAQUE, &rRect, pText, nLen, NULL ); return nLen; } // Also moves cursor 'non proportional' font width, using FONT_INFO //=========================================================================== int DebugDrawTextFixed ( LPCTSTR pText, RECT & rRect ) { int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg; int nChars = DebugDrawText( pText, rRect ); rRect.left += (nFontWidth * nChars); return nChars; } //=========================================================================== int DebugDrawTextLine ( LPCTSTR pText, RECT & rRect ) { int nChars = DebugDrawText( pText, rRect ); rRect.top += g_nFontHeight; rRect.bottom += g_nFontHeight; return nChars; } // Moves cursor 'proportional' font width //=========================================================================== int DebugDrawTextHorz ( LPCTSTR pText, RECT & rRect ) { int nFontWidth = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nFontWidthAvg; SIZE size; int nChars = DebugDrawText( pText, rRect ); if (GetTextExtentPoint32( g_hDC, pText, nChars, &size )) { rRect.left += size.cx; } else { rRect.left += (nFontWidth * nChars); } return nChars; } //=========================================================================== char FormatCharTxtAsci ( const BYTE b, bool * pWasAsci_ ) { if (pWasAsci_) *pWasAsci_ = false; char c = (b & 0x7F); if (b <= 0x7F) { if (pWasAsci_) { *pWasAsci_ = true; } } return c; } //=========================================================================== 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 formatting flags returned //=========================================================================== int FormatDisassemblyLine( WORD nBaseAddress, int iMode, int nOpBytes, char *sAddress_, char *sOpCodes_, char *sTarget_, char *sTargetOffset_, int & nTargetOffset_, char * sImmediate_, char & nImmediate_, char *sBranch_ ) { const int nMaxOpcodes = 3; unsigned int nMinBytesLen = (nMaxOpcodes * (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; nTargetOffset_ = 0; // if (g_aOpmodes[ iMode ]._sFormat[0]) if ((iMode != AM_IMPLIED) && (iMode != AM_1) && (iMode != AM_2) && (iMode != AM_3)) { nTarget = *(LPWORD)(mem+nBaseAddress+1); if (nOpBytes == 2) nTarget &= 0xFF; if (iMode == AM_R) // Relative ADDR_REL) { nTarget = nBaseAddress+2+(int)(signed char)nTarget; // Always show branch indicators // if ((nBaseAddress == regs.pc) && CheckJump(nAddress)) bDisasmFormatFlags |= DISASM_BRANCH_INDICATOR; if (nTarget < nBaseAddress) { wsprintf( sBranch_, TEXT(" %c"), g_sConfigBranchIndicatorUp[ g_iConfigDisasmBranchType ] ); } else if (nTarget > nBaseAddress) { wsprintf( sBranch_, TEXT(" %c"), g_sConfigBranchIndicatorDown[ g_iConfigDisasmBranchType ] ); } else { wsprintf( sBranch_, TEXT("%c "), g_sConfigBranchIndicatorEqual[ g_iConfigDisasmBranchType ] ); } } // if (_tcsstr(g_aOpmodes[ iMode ]._sFormat,TEXT("%s"))) // if ((iMode >= ADDR_ABS) && (iMode <= ADDR_IABS)) if ((iMode == ADDR_ABS ) || (iMode == ADDR_ZP ) || (iMode == ADDR_ABSX) || (iMode == ADDR_ABSY) || (iMode == ADDR_ZP_X) || (iMode == ADDR_ZP_Y) || (iMode == ADDR_REL ) || (iMode == ADDR_INDX) || (iMode == ADDR_ABSIINDX) || (iMode == ADDR_INDY) || (iMode == ADDR_ABS ) || (iMode == ADDR_IZPG) || (iMode == ADDR_IABS)) { LPCTSTR pTarget = NULL; LPCTSTR pSymbol = FindSymbolFromAddress( nTarget ); if (pSymbol) { bDisasmFormatFlags |= DISASM_TARGET_SYMBOL; pTarget = pSymbol; } if (! (bDisasmFormatFlags & DISASM_TARGET_SYMBOL)) { pSymbol = FindSymbolFromAddress( nTarget - 1 ); if (pSymbol) { bDisasmFormatFlags |= DISASM_TARGET_SYMBOL; bDisasmFormatFlags |= DISASM_TARGET_OFFSET; pTarget = pSymbol; nTargetOffset_ = +1; // U FA82 LDA #3F1 BREAK+1 } } if (! (bDisasmFormatFlags & DISASM_TARGET_SYMBOL)) { pSymbol = FindSymbolFromAddress( nTarget + 1 ); if (pSymbol) { bDisasmFormatFlags |= DISASM_TARGET_SYMBOL; bDisasmFormatFlags |= DISASM_TARGET_OFFSET; pTarget = pSymbol; nTargetOffset_ = -1; // U FA82 LDA #3F3 BREAK-1 } } if (! (bDisasmFormatFlags & DISASM_TARGET_SYMBOL)) { pTarget = FormatAddress( nTarget, nOpBytes ); } // wsprintf( sTarget, g_aOpmodes[ iMode ]._sFormat, pTarget ); if (bDisasmFormatFlags & DISASM_TARGET_OFFSET) { int nAbsTargetOffset = (nTargetOffset_ > 0) ? nTargetOffset_ : -nTargetOffset_; wsprintf( sTargetOffset_, "%d", nAbsTargetOffset ); } wsprintf( sTarget_, "%s", pTarget ); } else if (iMode == AM_M) { // wsprintf( sTarget, g_aOpmodes[ iMode ]._sFormat, (unsigned)nTarget ); wsprintf( sTarget_, "%02X", (unsigned)nTarget ); if (iMode == ADDR_IMM) { bDisasmFormatFlags |= DISASM_IMMEDIATE_CHAR; nImmediate_ = (BYTE) nTarget; wsprintf( sImmediate_, "%c", FormatCharTxtCtrl( FormatCharTxtHigh( nImmediate_, NULL ), NULL ) ); } } } wsprintf( sAddress_, "%04X", nBaseAddress ); // Opcode Bytes TCHAR *pDst = sOpCodes_; for( int iBytes = 0; iBytes < nOpBytes; iBytes++ ) { BYTE nMem = (unsigned)*(mem+nBaseAddress+iBytes); wsprintf( pDst, TEXT("%02X"), nMem ); // sBytes+_tcslen(sBytes) pDst += 2; if (g_bConfigDisasmOpcodeSpaces) { _tcscat( pDst, TEXT(" " ) ); } pDst++; } while (_tcslen(sOpCodes_) < nMinBytesLen) { _tcscat( sOpCodes_, TEXT(" ") ); } return bDisasmFormatFlags; } //=========================================================================== void SetupColorsHiLoBits ( HDC hDC, bool bHighBit, bool bCtrlBit, const int iBackground, const int iForeground, const int iColorHiBG , const int iColorHiFG, const int iColorLoBG , const int iColorLoFG ) { // 4 cases: // Hi Lo Background Foreground -> just map Lo -> FG, Hi -> BG // 0 0 normal normal BG_INFO FG_DISASM_CHAR (dark cyan bright cyan) // 0 1 normal LoFG BG_INFO FG_DISASM_OPCODE (dark cyan yellow) // 1 0 HiBG normal BG_INFO_CHAR FG_DISASM_CHAR (mid cyan bright cyan) // 1 1 HiBG LoFG BG_INFO_CHAR FG_DISASM_OPCODE (mid cyan yellow) SetBkColor( hDC, DebuggerGetColor( iBackground )); SetTextColor( hDC, DebuggerGetColor( iForeground )); if (bHighBit) { SetBkColor( hDC, DebuggerGetColor( iColorHiBG )); SetTextColor( hDC, DebuggerGetColor( iColorHiFG )); // was iForeground } if (bCtrlBit) { SetBkColor( hDC, DebuggerGetColor( iColorLoBG )); SetTextColor( hDC, DebuggerGetColor( iColorLoFG )); } } // To flush out color bugs... swap: iAsciBackground & iHighBackground //=========================================================================== char ColorizeSpecialChar( HDC hDC, TCHAR * sText, BYTE nData, const MemoryView_e iView, const int iAsciBackground /*= 0 */, const int iTextForeground /*= FG_DISASM_CHAR */, const int iHighBackground /*= BG_INFO_CHAR*/, const int iHighForeground /*= FG_INFO_CHAR_HI*/, const int iCtrlBackground /*= BG_INFO_CHAR*/, const int iCtrlForeground /*= FG_INFO_CHAR_LO*/ ) { bool bHighBit = false; bool bAsciBit = false; bool bCtrlBit = false; int iTextBG = iAsciBackground; int iHighBG = iHighBackground; int iCtrlBG = iCtrlBackground; int iTextFG = iTextForeground; int iHighFG = iHighForeground; int iCtrlFG = iCtrlForeground; BYTE nByte = FormatCharTxtHigh( nData, & bHighBit ); char nChar = FormatCharTxtCtrl( nByte, & bCtrlBit ); switch (iView) { case MEM_VIEW_ASCII: iHighBG = iTextBG; iCtrlBG = iTextBG; break; case MEM_VIEW_APPLE: iHighBG = iTextBG; if (!bHighBit) { iTextBG = iCtrlBG; } if (bCtrlBit) { iTextFG = iCtrlFG; if (bHighBit) { iHighFG = iTextFG; } } bCtrlBit = false; break; default: break; } if (sText) wsprintf( sText, TEXT("%c"), nChar ); if (hDC) { SetupColorsHiLoBits( hDC, bHighBit, bCtrlBit , iTextBG, iTextFG // FG_DISASM_CHAR , iHighBG, iHighFG // BG_INFO_CHAR , iCtrlBG, iCtrlFG // FG_DISASM_OPCODE ); } return nChar; } // Main Windows ___________________________________________________________________________________ //=========================================================================== void DrawBreakpoints (HDC dc, int line) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; RECT rect; rect.left = DISPLAY_BP_COLUMN; rect.top = (line * g_nFontHeight); rect.right = DISPLAY_WIDTH; rect.bottom = rect.top + g_nFontHeight; const int MAX_BP_LEN = 16; TCHAR sText[16] = TEXT("Breakpoints"); // TODO: Move to BP1 SetBkColor(dc, DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); //COLOR_STATIC DebugDrawText( sText, rect ); rect.top += g_nFontHeight; rect.bottom += g_nFontHeight; int iBreakpoint; for (iBreakpoint = 0; iBreakpoint < NUM_BREAKPOINTS; iBreakpoint++ ) { Breakpoint_t *pBP = &g_aBreakpoints[iBreakpoint]; WORD nLength = pBP->nLength; #if DEBUG_FORCE_DISPLAY nLength = 2; #endif if (nLength) { bool bSet = pBP->bSet; bool bEnabled = pBP->bEnabled; WORD nAddress1 = pBP->nAddress; WORD nAddress2 = nAddress1 + nLength - 1; RECT rect2; rect2 = rect; SetBkColor( dc, DebuggerGetColor( BG_INFO )); SetTextColor( dc, DebuggerGetColor( FG_INFO_BULLET ) ); wsprintf( sText, TEXT("%d"), iBreakpoint+1 ); DebugDrawTextFixed( sText, rect2 ); SetTextColor( dc, DebuggerGetColor( FG_INFO_OPERATOR ) ); _tcscpy( sText, TEXT(":") ); DebugDrawTextFixed( sText, rect2 ); #if DEBUG_FORCE_DISPLAY pBP->eSource = (BreakpointSource_t) iBreakpoint; #endif SetTextColor( dc, DebuggerGetColor( FG_INFO_REG ) ); int nRegLen = DebugDrawTextFixed( g_aBreakpointSource[ pBP->eSource ], rect2 ); // Pad to 2 chars if (nRegLen < 2) // (g_aBreakpointSource[ pBP->eSource ][1] == 0) // HACK: Avoid strlen() rect2.left += g_aFontConfig[ FONT_INFO ]._nFontWidthAvg; SetBkColor( dc, DebuggerGetColor( BG_INFO )); SetTextColor( dc, DebuggerGetColor( FG_INFO_BULLET ) ); #if DEBUG_FORCE_DISPLAY if (iBreakpoint < 3) pBP->eOperator = (BreakpointOperator_t)(iBreakpoint * 2); else pBP->eOperator = (BreakpointOperator_t)(iBreakpoint-3 + BP_OP_READ); #endif DebugDrawTextFixed( g_aBreakpointSymbols [ pBP->eOperator ], rect2 ); DebugColors_e iForeground; DebugColors_e iBackground = BG_INFO; if (bSet) { if (bEnabled) { iBackground = BG_DISASM_BP_S_C; // iForeground = FG_DISASM_BP_S_X; iForeground = FG_DISASM_BP_S_C; } else { iForeground = FG_DISASM_BP_0_X; } } else { iForeground = FG_INFO_TITLE; } SetBkColor( dc, DebuggerGetColor( iBackground ) ); SetTextColor( dc, DebuggerGetColor( iForeground ) ); #if DEBUG_FORCE_DISPLAY int iColor = R8 + (iBreakpoint*2); COLORREF nColor = gaColorPalette[ iColor ]; if (iBreakpoint >= 4) { SetBkColor ( dc, DebuggerGetColor( BG_DISASM_BP_S_C ) ); nColor = DebuggerGetColor( FG_DISASM_BP_S_C ); } SetTextColor( dc, nColor ); #endif wsprintf( sText, TEXT("%04X"), nAddress1 ); DebugDrawTextFixed( sText, rect2 ); if (nLength > 1) { SetBkColor( dc, DebuggerGetColor( BG_INFO ) ); SetTextColor( dc, DebuggerGetColor( FG_INFO_OPERATOR ) ); // if (g_bConfigDisasmOpcodeSpaces) // { // DebugDrawTextHorz( TEXT(" "), rect2 ); // rect2.left += g_nFontWidthAvg; // } DebugDrawTextFixed( TEXT("-"), rect2 ); // rect2.left += g_nFontWidthAvg; // if (g_bConfigDisasmOpcodeSpaces) // TODO: Might have to remove spaces, for BPIO... addr-addr xx // { // rect2.left += g_nFontWidthAvg; // } SetBkColor( dc, DebuggerGetColor( iBackground ) ); SetTextColor( dc, DebuggerGetColor( iForeground ) ); #if DEBUG_FORCE_DISPLAY iColor++; COLORREF nColor = gaColorPalette[ iColor ]; if (iBreakpoint >= 4) { nColor = DebuggerGetColor( BG_INFO ); SetBkColor( dc, nColor ); nColor = DebuggerGetColor( FG_DISASM_BP_S_X ); } SetTextColor( dc, nColor ); #endif wsprintf( sText, TEXT("%04X"), nAddress2 ); DebugDrawTextFixed( sText, rect2 ); } // Bugfix: Rest of line is still breakpoint background color SetBkColor(dc, DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); //COLOR_STATIC DebugDrawTextHorz( TEXT(" "), rect2 ); } rect.top += g_nFontHeight; rect.bottom += g_nFontHeight; } } //=========================================================================== void DrawConsoleInput( HDC dc ) { g_hDC = dc; SetTextColor( g_hDC, DebuggerGetColor( FG_CONSOLE_INPUT )); SetBkColor( g_hDC, DebuggerGetColor( BG_CONSOLE_INPUT )); DrawConsoleLine( g_aConsoleInput, 0 ); } //=========================================================================== int GetConsoleLineHeightPixels() { int nHeight = nHeight = g_aFontConfig[ FONT_CONSOLE ]._nFontHeight; // _nLineHeight; // _nFontHeight; if (g_iFontSpacing == FONT_SPACING_CLASSIC) { nHeight++; // "Classic" Height/Spacing } else if (g_iFontSpacing == FONT_SPACING_CLEAN) { nHeight++; } else if (g_iFontSpacing == FONT_SPACING_COMPRESSED) { // default case handled } return nHeight; } //=========================================================================== int GetConsoleTopPixels( int y ) { int nLineHeight = GetConsoleLineHeightPixels(); int nTop = DISPLAY_HEIGHT - ((y + 1) * nLineHeight); return nTop; } //=========================================================================== void DrawConsoleLine( LPCSTR pText, int y ) { if (y < 0) return; // int nHeight = WindowGetHeight( g_iWindowThis ); int nLineHeight = GetConsoleLineHeightPixels(); RECT rect; rect.left = 0; // rect.top = (g_nTotalLines - y) * nFontHeight; // DISPLAY_HEIGHT - (y * nFontHeight); // ((g_nTotalLines - y) * g_nFontHeight; // 368 = 23 lines * 16 pixels/line // MAX_DISPLAY_CONSOLE_LINES rect.top = GetConsoleTopPixels( y ); rect.bottom = rect.top + nLineHeight; //g_nFontHeight; // Default: (356-14) = 342 pixels ~= 48 chars (7 pixel width) // rect.right = SCREENSPLIT1-14; // rect.right = (g_nConsoleDisplayWidth * g_nFontWidthAvg) + (g_nFontWidthAvg - 1); int nMiniConsoleRight = DISPLAY_MINI_CONSOLE; // (g_nConsoleDisplayWidth * g_nFontWidthAvg) + (g_nFontWidthAvg * 2); // +14 int nFullConsoleRight = DISPLAY_WIDTH; int nRight = g_bConsoleFullWidth ? nFullConsoleRight : nMiniConsoleRight; rect.right = nRight; DebugDrawText( pText, rect ); } //=========================================================================== WORD DrawDisassemblyLine (HDC dc, int iLine, WORD nBaseAddress, LPTSTR text) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return 0; const int nMaxAddressLen = 40; const int nMaxOpcodes = 3; int iOpcode; int iOpmode; int nOpbytes; iOpcode = _6502GetOpmodeOpbytes( nBaseAddress, iOpmode, nOpbytes ); TCHAR sAddress [ 5]; TCHAR sOpcodes [(nMaxOpcodes*3)+1] = TEXT(""); TCHAR sTarget [nMaxAddressLen] = TEXT(""); TCHAR sTargetOffset[ 4 ] = TEXT(""); // +/- 255, realistically +/-1 int nTargetOffset; char nImmediate = 0; TCHAR sImmediate[ 4 ]; // 'c' TCHAR sBranch [ 4 ]; // ^ bool bTargetIndirect = false; bool bTargetX = false; bool bTargetY = false; if ((iOpmode >= ADDR_INDX) && (iOpmode <= ADDR_IABS)) bTargetIndirect = true; if ((iOpmode == ADDR_ABSX) || (iOpmode == ADDR_ZP_X) || (iOpmode == ADDR_INDX) || (iOpmode == ADDR_ABSIINDX)) bTargetX = true; if ((iOpmode == ADDR_ABSY) || (iOpmode == ADDR_ZP_Y)) bTargetY = true; int bDisasmFormatFlags = FormatDisassemblyLine( nBaseAddress, iOpmode, nOpbytes, sAddress, sOpcodes, sTarget, sTargetOffset, nTargetOffset, sImmediate, nImmediate, sBranch ); //> Address Seperator Opcodes Label Mnemonic Target [Immediate] [Branch] // //> xxxx: xx xx xx LABEL MNEMONIC 'E' = //> ^ ^ ^ ^ ^ //> 6 17 27 41 46 const int nDefaultFontWidth = 7; // g_aFontConfig[FONT_DISASM_DEFAULT]._nFontWidth or g_nFontWidthAvg int X_OPCODE = 6 * nDefaultFontWidth; int X_LABEL = 17 * nDefaultFontWidth; int X_INSTRUCTION = 27 * nDefaultFontWidth; int X_IMMEDIATE = 41 * nDefaultFontWidth; int X_BRANCH = 46 * nDefaultFontWidth; const int DISASM_SYMBOL_LEN = 9; if (dc) { int nFontHeight = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nLineHeight; // _nFontHeight; // g_nFontHeight RECT linerect; linerect.left = 0; linerect.top = iLine * nFontHeight; linerect.right = DISPLAY_DISASM_RIGHT; // HACK: MAGIC #: 14 -> g_nFontWidthAvg linerect.bottom = linerect.top + nFontHeight; // BOOL bp = g_nBreakpoints && CheckBreakpoint(nBaseAddress,nBaseAddress == regs.pc); bool bBreakpointActive; bool bBreakpointEnable; GetBreakpointInfo( nBaseAddress, bBreakpointActive, bBreakpointEnable ); bool bAddressAtPC = (nBaseAddress == regs.pc); DebugColors_e iBackground = BG_DISASM_1; DebugColors_e iForeground = FG_DISASM_MNEMONIC; // FG_DISASM_TEXT; bool bCursorLine = false; if (((! g_bDisasmCurBad) && (iLine == g_nDisasmCurLine)) || (g_bDisasmCurBad && (iLine == 0))) { bCursorLine = true; // Breakpoint, if (bBreakpointActive) { if (bBreakpointEnable) { iBackground = BG_DISASM_BP_S_C; iForeground = FG_DISASM_BP_S_C; } else { iBackground = BG_DISASM_BP_0_C; iForeground = FG_DISASM_BP_0_C; } } else if (bAddressAtPC) { iBackground = BG_DISASM_PC_C; iForeground = FG_DISASM_PC_C; } else { iBackground = BG_DISASM_C; iForeground = FG_DISASM_C; // HACK? Sync Cursor back up to Address // The cursor line may of had to be been moved, due to Disasm Singularity. g_nDisasmCurAddress = nBaseAddress; } } else { if (iLine & 1) { iBackground = BG_DISASM_1; } else { iBackground = BG_DISASM_2; } // This address has a breakpoint, but the cursor is not on it (atm) if (bBreakpointActive) { if (bBreakpointEnable) { iForeground = FG_DISASM_BP_S_X; // Red (old Yellow) } else { iForeground = FG_DISASM_BP_0_X; // Yellow } } else if (bAddressAtPC) { iBackground = BG_DISASM_PC_X; iForeground = FG_DISASM_PC_X; } else { iForeground = FG_DISASM_MNEMONIC; } } SetBkColor( dc, DebuggerGetColor( iBackground ) ); SetTextColor( dc, DebuggerGetColor( iForeground ) ); // Address if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_ADDRESS ) ); DebugDrawTextHorz( (LPCTSTR) sAddress, linerect ); // Address Seperator if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR ) ); if (g_bConfigDisasmAddressColon) DebugDrawTextHorz( TEXT(":"), linerect ); // Opcodes linerect.left = X_OPCODE; if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPCODE ) ); // DebugDrawTextHorz( TEXT(" "), linerect ); DebugDrawTextHorz( (LPCTSTR) sOpcodes, linerect ); // DebugDrawTextHorz( TEXT(" "), linerect ); // Label linerect.left = X_LABEL; LPCSTR pSymbol = FindSymbolFromAddress( nBaseAddress ); if (pSymbol) { if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_SYMBOL ) ); DebugDrawTextHorz( pSymbol, linerect ); } // linerect.left += (g_nFontWidthAvg * DISASM_SYMBOL_LEN); // DebugDrawTextHorz( TEXT(" "), linerect ); // Instruction linerect.left = X_INSTRUCTION; if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( iForeground ) ); LPCTSTR pMnemonic = g_aOpcodes[ iOpcode ].sMnemonic; DebugDrawTextHorz( pMnemonic, linerect ); DebugDrawTextHorz( TEXT(" "), linerect ); // Target if (iOpmode == ADDR_IMM) { if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR )); DebugDrawTextHorz( TEXT("#$"), linerect ); } if (bTargetIndirect) { if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR )); DebugDrawTextHorz( TEXT("("), linerect ); } char *pTarget = sTarget; if (*pTarget == '$') { pTarget++; if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR )); DebugDrawTextHorz( TEXT("$"), linerect ); } if (! bCursorLine) { if (bDisasmFormatFlags & DISASM_TARGET_SYMBOL) { SetTextColor( dc, DebuggerGetColor( FG_DISASM_SYMBOL ) ); } else { if (bDisasmFormatFlags & DISASM_IMMEDIATE_CHAR) { SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPCODE ) ); } else { SetTextColor( dc, DebuggerGetColor( FG_DISASM_TARGET ) ); } } } DebugDrawTextHorz( pTarget, linerect ); // DebugDrawTextHorz( TEXT(" "), linerect ); // Target Offset +/- if (bDisasmFormatFlags & DISASM_TARGET_OFFSET) { if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR )); if (nTargetOffset > 0) DebugDrawTextHorz( TEXT("+" ), linerect ); if (nTargetOffset < 0) DebugDrawTextHorz( TEXT("-" ), linerect ); if (! bCursorLine) { SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPCODE )); // Technically, not a hex number, but decimal } DebugDrawTextHorz( sTargetOffset, linerect ); } // Indirect Target Regs if (bTargetIndirect || bTargetX || bTargetY) { if (! bCursorLine) SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR )); if (bTargetX) DebugDrawTextHorz( TEXT(",X"), linerect ); if (bTargetY) DebugDrawTextHorz( TEXT(",Y"), linerect ); if (bTargetIndirect) DebugDrawTextHorz( TEXT(")"), linerect ); if (iOpmode == ADDR_INDY) DebugDrawTextHorz( TEXT(",Y"), linerect ); } // Immediate Char linerect.left = X_IMMEDIATE; if (bDisasmFormatFlags & DISASM_IMMEDIATE_CHAR) { if (! bCursorLine) { SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR ) ); } DebugDrawTextHorz( TEXT("'"), linerect ); // TEXT(" '") if (! bCursorLine) { ColorizeSpecialChar( dc, NULL, nImmediate, MEM_VIEW_ASCII, iBackground ); // iBackground, FG_INFO_CHAR_HI, FG_DISASM_CHAR, FG_INFO_CHAR_LO ); } DebugDrawTextHorz( sImmediate, linerect ); SetBkColor( dc, DebuggerGetColor( iBackground ) ); // Hack: Colorize can "color bleed to EOL" if (! bCursorLine) { SetTextColor( dc, DebuggerGetColor( FG_DISASM_OPERATOR ) ); } DebugDrawTextHorz( TEXT("'"), linerect ); } // Branch Indicator linerect.left = X_BRANCH; if (bDisasmFormatFlags & DISASM_BRANCH_INDICATOR) { if (! bCursorLine) { SetTextColor( dc, DebuggerGetColor( FG_DISASM_BRANCH ) ); } if (g_iConfigDisasmBranchType == DISASM_BRANCH_FANCY) SelectObject( dc, g_aFontConfig[ FONT_DISASM_BRANCH ]._hFont ); // g_hFontWebDings DebugDrawText( sBranch, linerect ); if (g_iConfigDisasmBranchType) SelectObject( dc, g_aFontConfig[ FONT_DISASM_DEFAULT ]._hFont ); // g_hFontDisasm } } return nOpbytes; } // Optionally copy the flags to pText_ //=========================================================================== void DrawFlags (HDC dc, int line, WORD nRegFlags, LPTSTR pFlagNames_) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; TCHAR sFlagNames[ _6502_NUM_FLAGS+1 ] = TEXT(""); // = TEXT("NVRBDIZC"); // copy from g_aFlagNames TCHAR sText[2] = TEXT("?"); RECT rect; if (dc) { rect.left = DISPLAY_FLAG_COLUMN; rect.top = line * g_nFontHeight; rect.right = rect.left + 9; rect.bottom = rect.top + g_nFontHeight; SetBkColor(dc, DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA } int iFlag = 0; int nFlag = _6502_NUM_FLAGS; while (nFlag--) { iFlag = BP_SRC_FLAG_C + (_6502_NUM_FLAGS - nFlag - 1); bool bSet = (nRegFlags & 1); if (dc) { // sText[0] = g_aFlagNames[ MAX_FLAGS - iFlag - 1]; // mnemonic[iFlag]; // mnemonic is reversed sText[0] = g_aBreakpointSource[ iFlag ][0]; if (bSet) { SetBkColor( dc, DebuggerGetColor( BG_INFO_INVERSE )); SetTextColor( dc, DebuggerGetColor( FG_INFO_INVERSE )); } else { SetBkColor(dc, DebuggerGetColor( BG_INFO )); SetTextColor( dc, DebuggerGetColor( FG_INFO_TITLE )); } DebugDrawText( sText, rect ); rect.left -= 9; // HACK: Font Width rect.right -= 9; // HACK: Font Width } if (pFlagNames_) { if (! bSet) //(nFlags & 1)) { sFlagNames[nFlag] = TEXT('.'); } else { sFlagNames[nFlag] = g_aBreakpointSource[ iFlag ][0]; } } nRegFlags >>= 1; } if (pFlagNames_) _tcscpy(pFlagNames_,sFlagNames); } //=========================================================================== void DrawMemory (HDC hDC, int line, int iMemDump ) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; MemoryDump_t* pMD = &g_aMemDump[ iMemDump ]; USHORT nAddr = pMD->nAddress; DEVICE_e eDevice = pMD->eDevice; MemoryView_e iView = pMD->eView; SS_CARD_MOCKINGBOARD SS_MB; if ((eDevice == DEV_SY6522) || (eDevice == DEV_AY8910)) MB_GetSnapshot(&SS_MB, 4+(nAddr>>1)); // Slot4 or Slot5 int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg; RECT rect; rect.left = DISPLAY_MINIMEM_COLUMN - nFontWidth; rect.top = (line * g_nFontHeight); rect.right = DISPLAY_WIDTH; rect.bottom = rect.top + g_nFontHeight; const int MAX_MEM_VIEW_TXT = 16; TCHAR sText[ MAX_MEM_VIEW_TXT * 2 ]; TCHAR sData[ MAX_MEM_VIEW_TXT * 2 ]; TCHAR sType [ 4 ] = TEXT("Mem"); TCHAR sAddress[ 8 ] = TEXT(""); int iForeground = FG_INFO_OPCODE; int iBackground = BG_INFO; if (eDevice == DEV_SY6522) { // wsprintf(sData,TEXT("Mem at SY#%d"), nAddr); wsprintf( sAddress,TEXT("SY#%d"), nAddr ); } else if(eDevice == DEV_AY8910) { // wsprintf(sData,TEXT("Mem at AY#%d"), nAddr); wsprintf( sAddress,TEXT("AY#%d"), nAddr ); } else { wsprintf( sAddress,TEXT("%04X"),(unsigned)nAddr); if (iView == MEM_VIEW_HEX) wsprintf( sType, TEXT("HEX") ); else if (iView == MEM_VIEW_ASCII) wsprintf( sType, TEXT("ASCII") ); else wsprintf( sType, TEXT("TEXT") ); } RECT rect2; rect2 = rect; SetTextColor( hDC, DebuggerGetColor( FG_INFO_TITLE )); SetBkColor( hDC, DebuggerGetColor( BG_INFO )); DebugDrawTextFixed( sType, rect2 ); SetTextColor( hDC, DebuggerGetColor( FG_INFO_OPERATOR )); DebugDrawTextFixed( TEXT(" at " ), rect2 ); SetTextColor( hDC, DebuggerGetColor( FG_INFO_ADDRESS )); DebugDrawTextLine( sAddress, rect2 ); rect.top = rect2.top; rect.bottom = rect2.bottom; sData[0] = 0; WORD iAddress = nAddr; if( (eDevice == DEV_SY6522) || (eDevice == DEV_AY8910) ) { iAddress = 0; } int nLines = 4; int nCols = 4; if (iView != MEM_VIEW_HEX) { nCols = MAX_MEM_VIEW_TXT; } rect.right = DISPLAY_WIDTH; SetTextColor( hDC, DebuggerGetColor( FG_INFO_OPCODE )); for (int iLine = 0; iLine < nLines; iLine++ ) { RECT rect2; rect2 = rect; if (iView == MEM_VIEW_HEX) { wsprintf( sText, TEXT("%04X"), iAddress ); SetTextColor( hDC, DebuggerGetColor( FG_INFO_ADDRESS )); DebugDrawTextFixed( sText, rect2 ); SetTextColor( hDC, DebuggerGetColor( FG_INFO_OPERATOR )); DebugDrawTextFixed( TEXT(":"), rect2 ); } for (int iCol = 0; iCol < nCols; iCol++) { bool bHiBit = false; bool bLoBit = false; SetBkColor ( hDC, DebuggerGetColor( iBackground )); SetTextColor( hDC, DebuggerGetColor( iForeground )); // .12 Bugfix: DrawMemory() should draw memory byte for IO address: ML1 C000 // if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END)) // { // wsprintf( sText, TEXT("IO ") ); // } // else if (eDevice == DEV_SY6522) { wsprintf( sText, TEXT("%02X "), (unsigned) ((BYTE*)&SS_MB.Unit[nAddr & 1].RegsSY6522)[iAddress] ); } else if (eDevice == DEV_AY8910) { wsprintf( sText, TEXT("%02X "), (unsigned)SS_MB.Unit[nAddr & 1].RegsAY8910[iAddress] ); } else { BYTE nData = (unsigned)*(LPBYTE)(mem+iAddress); sText[0] = 0; char c = nData; if (iView == MEM_VIEW_HEX) { if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END)) { SetTextColor( hDC, DebuggerGetColor( FG_INFO_IO_BYTE )); } wsprintf(sText, TEXT("%02X "), nData ); } else { // .12 Bugfix: DrawMemory() should draw memory byte for IO address: ML1 C000 if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END)) iBackground = BG_INFO_IO_BYTE; ColorizeSpecialChar( hDC, sText, nData, iView, iBackground ); } } int nChars = DebugDrawTextFixed( sText, rect2 ); // DebugDrawTextFixed() iAddress++; } rect.top += g_nFontHeight; // TODO/FIXME: g_nFontHeight; rect.bottom += g_nFontHeight; // TODO/FIXME: g_nFontHeight; sData[0] = 0; } } //=========================================================================== void DrawRegister (HDC dc, int line, LPCTSTR name, const int nBytes, const WORD nValue, int iSource ) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; RECT rect; rect.left = DISPLAY_REGS_COLUMN; rect.top = line * g_nFontHeight; rect.right = rect.left + 40; // TODO:FIXME: g_nFontWidthAvg * rect.bottom = rect.top + g_nFontHeight; if ((PARAM_REG_A == iSource) || (PARAM_REG_X == iSource) || (PARAM_REG_Y == iSource) || (PARAM_REG_PC == iSource) || (PARAM_REG_SP == iSource)) { SetTextColor(dc, DebuggerGetColor( FG_INFO_REG )); } else { SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); } SetBkColor(dc, DebuggerGetColor( BG_INFO )); DebugDrawText( name, rect ); unsigned int nData = nValue; int nOffset = 6; TCHAR sValue[8]; if (PARAM_REG_SP == iSource) { WORD nStackDepth = _6502_STACK_END - nValue; wsprintf( sValue, "%02X", nStackDepth ); int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg; rect.left += (2 * nFontWidth) + (nFontWidth >> 1); // 2.5 looks a tad nicer then 2 // ## = Stack Depth (in bytes) SetTextColor(dc, DebuggerGetColor( FG_INFO_OPERATOR )); // FG_INFO_OPCODE, FG_INFO_TITLE DebugDrawText( sValue, rect ); } if (nBytes == 2) { wsprintf(sValue,TEXT("%04X"), nData); } else { rect.left = DISPLAY_REGS_COLUMN + 21; // HACK: MAGIC #: 21 // +3 chars rect.right = SCREENSPLIT2; SetTextColor(dc, DebuggerGetColor( FG_INFO_OPERATOR )); DebugDrawTextFixed( TEXT("'"), rect ); // DebugDrawTextFixed ColorizeSpecialChar( dc, sValue, nData, MEM_VIEW_ASCII ); // MEM_VIEW_APPLE for inverse background little hard on the eyes DebugDrawTextFixed( sValue, rect ); // DebugDrawTextFixed() SetBkColor(dc, DebuggerGetColor( BG_INFO )); SetTextColor(dc, DebuggerGetColor( FG_INFO_OPERATOR )); DebugDrawTextFixed( TEXT("'"), rect ); // DebugDrawTextFixed() wsprintf(sValue,TEXT(" %02X"), nData ); } // Needs to be far enough over, since 4 chars of ZeroPage symbol also calls us rect.left = DISPLAY_REGS_COLUMN + (nOffset * g_aFontConfig[ FONT_INFO ]._nFontWidthAvg); // HACK: MAGIC #: 40 rect.right = SCREENSPLIT2; if ((PARAM_REG_PC == iSource) || (PARAM_REG_SP == iSource)) // Stack Pointer is target address, but doesn't look as good. { SetTextColor(dc, DebuggerGetColor( FG_INFO_ADDRESS )); } else { SetTextColor(dc, DebuggerGetColor( FG_INFO_OPCODE )); // FG_DISASM_OPCODE } DebugDrawText( sValue, rect ); } //=========================================================================== void DrawSourceLine( int iSourceLine, RECT &rect ) { TCHAR sLine[ CONSOLE_WIDTH ]; ZeroMemory( sLine, CONSOLE_WIDTH ); if ((iSourceLine >=0) && (iSourceLine < g_AssemblerSourceBuffer.GetNumLines() )) { char * pSource = g_AssemblerSourceBuffer.GetLine( iSourceLine ); // int nLenSrc = _tcslen( pSource ); // if (nLenSrc >= CONSOLE_WIDTH) // bool bStop = true; TextConvertTabsToSpaces( sLine, pSource, CONSOLE_WIDTH-1 ); // bugfix 2,3,1,15: fence-post error, buffer over-run // int nLenTab = _tcslen( sLine ); } else { _tcscpy( sLine, TEXT(" ")); } DebugDrawText( sLine, rect ); rect.top += g_nFontHeight; // iSourceLine++; } //=========================================================================== void DrawStack (HDC dc, int line) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; unsigned nAddress = regs.sp; #if DEBUG_FORCE_DISPLAY nAddress = 0x100; #endif int iStack = 0; while (iStack < MAX_DISPLAY_STACK_LINES) { nAddress++; RECT rect; rect.left = DISPLAY_STACK_COLUMN; rect.top = (iStack+line) * g_nFontHeight; rect.right = DISPLAY_STACK_COLUMN + 40; // TODO/FIXME/HACK MAGIC #: g_nFontWidthAvg * rect.bottom = rect.top + g_nFontHeight; SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); // [COLOR_STATIC SetBkColor(dc, DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA TCHAR sText[8] = TEXT(""); if (nAddress <= _6502_STACK_END) { wsprintf(sText,TEXT("%04X"),nAddress); } DebugDrawText( sText, rect ); rect.left = DISPLAY_STACK_COLUMN + 40; // TODO/FIXME/HACK MAGIC #: g_nFontWidthAvg * rect.right = SCREENSPLIT2; SetTextColor(dc, DebuggerGetColor( FG_INFO_OPCODE )); // COLOR_FG_DATA_TEXT if (nAddress <= _6502_STACK_END) { wsprintf(sText,TEXT("%02X"),(unsigned)*(LPBYTE)(mem+nAddress)); } DebugDrawText( sText, rect ); iStack++; } } //=========================================================================== void DrawTargets (HDC dc, int line) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; int aTarget[2]; Get6502Targets( &aTarget[0],&aTarget[1], NULL ); RECT rect; int iAddress = 2; while (iAddress--) { // .6 Bugfix: DrawTargets() should draw target byte for IO address: R PC FB33 // if ((aTarget[iAddress] >= _6502_IO_BEGIN) && (aTarget[iAddress] <= _6502_IO_END)) // aTarget[iAddress] = NO_6502_TARGET; TCHAR sAddress[8] = TEXT(""); TCHAR sData[8] = TEXT(""); #if DEBUG_FORCE_DISPLAY if (aTarget[iAddress] == NO_6502_TARGET) aTarget[iAddress] = 0; #endif if (aTarget[iAddress] != NO_6502_TARGET) { wsprintf(sAddress,TEXT("%04X"),aTarget[iAddress]); if (iAddress) wsprintf(sData,TEXT("%02X"),*(LPBYTE)(mem+aTarget[iAddress])); else wsprintf(sData,TEXT("%04X"),*(LPWORD)(mem+aTarget[iAddress])); } rect.left = DISPLAY_TARGETS_COLUMN; rect.top = (line+iAddress) * g_nFontHeight; int nColumn = DISPLAY_TARGETS_COLUMN + 40; // TODO/FIXME/HACK MAGIC #: g_nFontWidthAvg * rect.right = nColumn; rect.bottom = rect.top + g_nFontHeight; if (iAddress == 0) SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); // Temp Address else SetTextColor(dc, DebuggerGetColor( FG_INFO_ADDRESS )); // Target Address SetBkColor(dc, DebuggerGetColor( BG_INFO )); DebugDrawText( sAddress, rect ); rect.left = nColumn; // SCREENSPLIT1+40; // + 40 rect.right = SCREENSPLIT2; if (iAddress == 0) SetTextColor(dc, DebuggerGetColor( FG_INFO_ADDRESS )); // Temp Target else SetTextColor(dc, DebuggerGetColor( FG_INFO_OPCODE )); // Target Bytes DebugDrawText( sData, rect ); } } //=========================================================================== void DrawWatches (HDC dc, int line) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; RECT rect; rect.left = DISPLAY_WATCHES_COLUMN; rect.top = (line * g_nFontHeight); rect.right = DISPLAY_WIDTH; rect.bottom = rect.top + g_nFontHeight; TCHAR sText[16] = TEXT("Watches"); SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); SetBkColor(dc, DebuggerGetColor( BG_INFO )); DebugDrawTextLine( sText, rect ); int iWatch; for (iWatch = 0; iWatch < MAX_WATCHES; iWatch++ ) { #if DEBUG_FORCE_DISPLAY if (true) #else if (g_aWatches[iWatch].bEnabled) #endif { RECT rect2 = rect; wsprintf( sText,TEXT("%d"),iWatch+1 ); SetTextColor( dc, DebuggerGetColor( FG_INFO_BULLET )); DebugDrawTextFixed( sText, rect2 ); wsprintf( sText,TEXT(":") ); SetTextColor( dc, DebuggerGetColor( FG_INFO_OPERATOR )); DebugDrawTextFixed( sText, rect2 ); wsprintf( sText,TEXT(" %04X"), g_aWatches[iWatch].nAddress ); SetTextColor( dc, DebuggerGetColor( FG_INFO_ADDRESS )); DebugDrawTextFixed( sText, rect2 ); wsprintf(sText,TEXT(" %02X"),(unsigned)*(LPBYTE)(mem+g_aWatches[iWatch].nAddress)); SetTextColor(dc, DebuggerGetColor( FG_INFO_OPCODE )); DebugDrawTextFixed( sText, rect2 ); } rect.top += g_nFontHeight; // HACK: rect.bottom += g_nFontHeight; // HACK: } } //=========================================================================== void DrawZeroPagePointers(HDC dc, int line) { if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA)))) return; for(int iZP = 0; iZP < MAX_ZEROPAGE_POINTERS; iZP++) { RECT rect; rect.left = DISPLAY_ZEROPAGE_COLUMN; rect.top = (line+iZP) * g_nFontHeight; rect.right = SCREENSPLIT2; // TODO/FIXME: rect.bottom = rect.top + g_nFontHeight; TCHAR sText[8] = TEXT(" "); SetTextColor(dc, DebuggerGetColor( FG_INFO_TITLE )); // COLOR_STATIC SetBkColor(dc, DebuggerGetColor( BG_INFO )); DebugDrawText( sText, rect ); Breakpoint_t *pZP = &g_aZeroPagePointers[iZP]; bool bEnabled = pZP->bEnabled; #if DEBUG_FORCE_DISPLAY bEnabled = true; #endif if (bEnabled) // if (g_aZeroPagePointers[iZP].bSet) // TODO: Only list enanbled ones { const UINT nSymbolLen = 4; char szZP[nSymbolLen+1]; BYTE nZPAddr1 = (g_aZeroPagePointers[iZP].nAddress ) & 0xFF; // +MJP missig: "& 0xFF", or "(BYTE) ..." BYTE nZPAddr2 = (g_aZeroPagePointers[iZP].nAddress+1) & 0xFF; // Get nZPAddr1 last (for when neither symbol is not found - GetSymbol() return ptr to static buffer) const char* pszSymbol2 = GetSymbol(nZPAddr2, 2); // 2:8-bit value (if symbol not found) const char* pszSymbol1 = GetSymbol(nZPAddr1, 2); // 2:8-bit value (if symbol not found) if( (strlen(pszSymbol1)==1) && (strlen(pszSymbol2)==1) ) { sprintf(szZP, "%s%s", pszSymbol1, pszSymbol2); } else { memcpy(szZP, pszSymbol1, nSymbolLen); szZP[nSymbolLen] = 0; } WORD nZPPtr = (WORD)mem[ nZPAddr1 ] | ((WORD)mem[ nZPAddr2 ]<< 8); DrawRegister(dc, line+iZP, szZP, 2, nZPPtr); } } } // Sub Windows ____________________________________________________________________________________ //=========================================================================== void DrawSubWindow_Console (Update_t bUpdate) { if (! CanDrawDebugger()) return; SelectObject( g_hDC, g_aFontConfig[ FONT_CONSOLE ]._hFont ); // static TCHAR sConsoleBlank[ CONSOLE_WIDTH ]; if ((bUpdate & UPDATE_CONSOLE_INPUT) || (bUpdate & UPDATE_CONSOLE_DISPLAY)) { SetTextColor( g_hDC, DebuggerGetColor( FG_CONSOLE_OUTPUT )); // COLOR_FG_CONSOLE SetBkColor( g_hDC, DebuggerGetColor( BG_CONSOLE_OUTPUT )); // COLOR_BG_CONSOLE // int nLines = MIN(g_nConsoleDisplayTotal - g_iConsoleDisplayStart, g_nConsoleDisplayHeight); int iLine = g_iConsoleDisplayStart + CONSOLE_FIRST_LINE; for (int y = 0; y < g_nConsoleDisplayHeight ; y++ ) { if (iLine <= (g_nConsoleDisplayTotal + CONSOLE_FIRST_LINE)) { DrawConsoleLine( g_aConsoleDisplay[ iLine ], y+1 ); } iLine++; // else // DrawConsoleLine( sConsoleBlank, y ); } DrawConsoleInput( g_hDC ); } } //=========================================================================== void DrawSubWindow_Data (Update_t bUpdate) { HDC hDC = g_hDC; int iBackground; const int nMaxOpcodes = WINDOW_DATA_BYTES_PER_LINE; TCHAR sAddress [ 5]; assert( CONSOLE_WIDTH > WINDOW_DATA_BYTES_PER_LINE ); TCHAR sOpcodes [ CONSOLE_WIDTH ] = TEXT(""); TCHAR sImmediate[ 4 ]; // 'c' const int nDefaultFontWidth = 7; // g_aFontConfig[FONT_DISASM_DEFAULT]._nFontWidth or g_nFontWidthAvg int X_OPCODE = 6 * nDefaultFontWidth; int X_CHAR = (6 + (nMaxOpcodes*3)) * nDefaultFontWidth; int iMemDump = 0; MemoryDump_t* pMD = &g_aMemDump[ iMemDump ]; USHORT nAddress = pMD->nAddress; DEVICE_e eDevice = pMD->eDevice; MemoryView_e iView = pMD->eView; if (!pMD->bActive) return; int iByte; WORD iAddress = nAddress; int iLine; int nLines = g_nDisasmWinHeight; for (iLine = 0; iLine < nLines; iLine++ ) { iAddress = nAddress; // Format wsprintf( sAddress, TEXT("%04X"), iAddress ); sOpcodes[0] = 0; for ( iByte = 0; iByte < nMaxOpcodes; iByte++ ) { BYTE nData = (unsigned)*(LPBYTE)(mem + iAddress + iByte); wsprintf( &sOpcodes[ iByte * 3 ], TEXT("%02X "), nData ); } sOpcodes[ nMaxOpcodes * 3 ] = 0; int nFontHeight = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nLineHeight; // Draw RECT rect; rect.left = 0; rect.top = iLine * nFontHeight; rect.right = DISPLAY_DISASM_RIGHT; rect.bottom = rect.top + nFontHeight; if (iLine & 1) { iBackground = BG_DATA_1; } else { iBackground = BG_DATA_2; } SetBkColor( hDC, DebuggerGetColor( iBackground ) ); SetTextColor( hDC, DebuggerGetColor( FG_DISASM_ADDRESS ) ); DebugDrawTextHorz( (LPCTSTR) sAddress, rect ); SetTextColor( hDC, DebuggerGetColor( FG_DISASM_OPERATOR ) ); if (g_bConfigDisasmAddressColon) DebugDrawTextHorz( TEXT(":"), rect ); rect.left = X_OPCODE; SetTextColor( hDC, DebuggerGetColor( FG_DATA_BYTE ) ); DebugDrawTextHorz( (LPCTSTR) sOpcodes, rect ); rect.left = X_CHAR; // Seperator SetTextColor( hDC, DebuggerGetColor( FG_DISASM_OPERATOR )); DebugDrawTextHorz( (LPCSTR) TEXT(" | " ), rect ); // Plain Text SetTextColor( hDC, DebuggerGetColor( FG_DISASM_CHAR ) ); MemoryView_e eView = pMD->eView; if ((eView != MEM_VIEW_ASCII) && (eView != MEM_VIEW_APPLE)) eView = MEM_VIEW_ASCII; iAddress = nAddress; for (iByte = 0; iByte < nMaxOpcodes; iByte++ ) { BYTE nImmediate = (unsigned)*(LPBYTE)(mem + iAddress); int iTextBackground = iBackground; if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END)) { iTextBackground = BG_INFO_IO_BYTE; } ColorizeSpecialChar( hDC, sImmediate, (BYTE) nImmediate, eView, iBackground ); DebugDrawTextHorz( (LPCSTR) sImmediate, rect ); iAddress++; } /* // Colorized Text iAddress = nAddress; for (iByte = 0; iByte < nMaxOpcodes; iByte++ ) { BYTE nImmediate = (unsigned)*(LPBYTE)(membank + iAddress); int iTextBackground = iBackground; // BG_INFO_CHAR; //pMD->eView == MEM_VIEW_HEX if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END)) iTextBackground = BG_INFO_IO_BYTE; ColorizeSpecialChar( hDC, sImmediate, (BYTE) nImmediate, MEM_VIEW_APPLE, iBackground ); DebugDrawTextHorz( (LPCSTR) sImmediate, rect ); iAddress++; } SetBkColor( hDC, DebuggerGetColor( iBackground ) ); // Hack, colorize Char background "spills over to EOL" DebugDrawTextHorz( (LPCSTR) TEXT(" " ), rect ); */ SetBkColor( hDC, DebuggerGetColor( iBackground ) ); // HACK: Colorize() can "spill over" to EOL SetTextColor( hDC, DebuggerGetColor( FG_DISASM_OPERATOR )); DebugDrawTextHorz( (LPCSTR) TEXT(" | " ), rect ); nAddress += nMaxOpcodes; } } // DrawRegisters(); //=========================================================================== void DrawSubWindow_Info( int iWindow ) { if (g_iWindowThis == WINDOW_CONSOLE) return; const TCHAR **sReg = g_aBreakpointSource; DrawStack(g_hDC,0); DrawTargets(g_hDC,9); DrawRegister(g_hDC,12, sReg[ BP_SRC_REG_A ] , 1, regs.a , PARAM_REG_A ); DrawRegister(g_hDC,13, sReg[ BP_SRC_REG_X ] , 1, regs.x , PARAM_REG_X ); DrawRegister(g_hDC,14, sReg[ BP_SRC_REG_Y ] , 1, regs.y , PARAM_REG_Y ); DrawRegister(g_hDC,15, sReg[ BP_SRC_REG_PC] , 2, regs.pc, PARAM_REG_PC ); DrawRegister(g_hDC,16, sReg[ BP_SRC_REG_S ] , 2, regs.sp, PARAM_REG_SP ); DrawFlags(g_hDC,17,regs.ps,NULL); DrawZeroPagePointers(g_hDC,19); #if defined(SUPPORT_Z80_EMU) && defined(OUTPUT_Z80_REGS) DrawRegister(g_hDC,19,TEXT("AF"),2,*(WORD*)(membank+REG_AF)); DrawRegister(g_hDC,20,TEXT("BC"),2,*(WORD*)(membank+REG_BC)); DrawRegister(g_hDC,21,TEXT("DE"),2,*(WORD*)(membank+REG_DE)); DrawRegister(g_hDC,22,TEXT("HL"),2,*(WORD*)(membank+REG_HL)); DrawRegister(g_hDC,23,TEXT("IX"),2,*(WORD*)(membank+REG_IX)); #endif #if DEBUG_FORCE_DISPLAY if (true) #else if (g_nBreakpoints) #endif DrawBreakpoints(g_hDC,0); #if DEBUG_FORCE_DISPLAY if (true) #else if (g_nWatches) #endif DrawWatches(g_hDC,7); #if DEBUG_FORCE_DISPLAY if (true) #else if (g_aMemDump[0].bActive) #endif DrawMemory(g_hDC, 14, 0 ); // g_aMemDump[0].nAddress, g_aMemDump[0].eDevice); #if DEBUG_FORCE_DISPLAY if (true) #else if (g_aMemDump[1].bActive) #endif DrawMemory(g_hDC, 19, 1 ); // g_aMemDump[1].nAddress, g_aMemDump[1].eDevice); } //=========================================================================== void DrawSubWindow_IO (Update_t bUpdate) { } //=========================================================================== void DrawSubWindow_Source (Update_t bUpdate) { } //=========================================================================== void DrawSubWindow_Source2 (Update_t bUpdate) { // if (! g_bSourceLevelDebugging) // return; SetTextColor( g_hDC, DebuggerGetColor( FG_SOURCE )); int iSource = g_iSourceDisplayStart; int nLines = g_nDisasmWinHeight; int y = g_nDisasmWinHeight; int nHeight = g_nDisasmWinHeight; if (g_aWindowConfig[ g_iWindowThis ].bSplit) // HACK: Split Window Height is odd, so bottom window gets +1 height nHeight++; RECT rect; rect.top = (y * g_nFontHeight); rect.bottom = rect.top + (nHeight * g_nFontHeight); rect.left = 0; rect.right = DISPLAY_DISASM_RIGHT; // HACK: MAGIC #: 7 // Draw Title TCHAR sTitle[ CONSOLE_WIDTH ]; TCHAR sText [ CONSOLE_WIDTH ]; _tcscpy( sTitle, TEXT(" Source: ")); _tcsncpy( sText, g_aSourceFileName, g_nConsoleDisplayWidth - _tcslen( sTitle ) - 1 ); _tcscat( sTitle, sText ); SetBkColor( g_hDC, DebuggerGetColor( BG_SOURCE_TITLE )); SetTextColor( g_hDC, DebuggerGetColor( FG_SOURCE_TITLE )); DebugDrawText( sTitle, rect ); rect.top += g_nFontHeight; // Draw Source Lines int iBackground; int iForeground; int iSourceCursor = 2; // (g_nDisasmWinHeight / 2); int iSourceLine = FindSourceLine( regs.pc ); if (iSourceLine == NO_SOURCE_LINE) { iSourceCursor = NO_SOURCE_LINE; } else { iSourceLine -= iSourceCursor; if (iSourceLine < 0) iSourceLine = 0; } for( int iLine = 0; iLine < nLines; iLine++ ) { if (iLine != iSourceCursor) { iBackground = BG_SOURCE_1; if (iLine & 1) iBackground = BG_SOURCE_2; iForeground = FG_SOURCE; } else { // Hilighted cursor line iBackground = BG_DISASM_PC_X; // _C iForeground = FG_DISASM_PC_X; // _C } SetBkColor( g_hDC, DebuggerGetColor( iBackground )); SetTextColor( g_hDC, DebuggerGetColor( iForeground )); DrawSourceLine( iSourceLine, rect ); iSourceLine++; } } //=========================================================================== void DrawSubWindow_Symbols (Update_t bUpdate) { } //=========================================================================== void DrawSubWindow_ZeroPage (Update_t bUpdate) { } //=========================================================================== void DrawWindow_Code( Update_t bUpdate ) { DrawSubWindow_Code( g_iWindowThis ); // DrawWindowTop( g_iWindowThis ); DrawWindowBottom( bUpdate, g_iWindowThis ); DrawSubWindow_Info( g_iWindowThis ); } //=========================================================================== void DrawWindow_Console( Update_t bUpdate ) { // Nothing to do, except draw background, since text handled by DrawSubWindow_Console() RECT viewportrect; viewportrect.left = 0; viewportrect.top = 0; viewportrect.right = DISPLAY_WIDTH; viewportrect.bottom = DISPLAY_HEIGHT - DEFAULT_HEIGHT; // 368 = 23 lines // TODO/FIXME // TODO/FIXME: COLOR_BG_CODE -> g_iWindowThis, once all tab backgrounds are listed first in g_aColors ! SetBkColor(g_hDC, DebuggerGetColor( BG_DISASM_2 )); // COLOR_BG_CODE // Can't use DebugDrawText, since we don't ned the CLIPPED flag // TODO: add default param OPAQUE|CLIPPED ExtTextOut( g_hDC ,0,0 ,ETO_OPAQUE ,&viewportrect ,TEXT("") ,0 ,NULL ); } //=========================================================================== void DrawWindow_Data( Update_t bUpdate ) { DrawSubWindow_Data( g_iWindowThis ); DrawSubWindow_Info( g_iWindowThis ); } //=========================================================================== void DrawWindow_IO( Update_t bUpdate ) { DrawSubWindow_IO( g_iWindowThis ); DrawSubWindow_Info( g_iWindowThis ); } //=========================================================================== void DrawWindow_Source( Update_t bUpdate ) { DrawSubWindow_Source( g_iWindowThis ); DrawSubWindow_Info( g_iWindowThis ); } //=========================================================================== void DrawWindow_Symbols( Update_t bUpdate ) { DrawSubWindow_Symbols( g_iWindowThis ); DrawSubWindow_Info( g_iWindowThis ); } void DrawWindow_ZeroPage( Update_t bUpdate ) { DrawSubWindow_ZeroPage( g_iWindowThis ); DrawSubWindow_Info( g_iWindowThis ); } //=========================================================================== void DrawWindowBackground_Main( int g_iWindowThis ) { RECT viewportrect; viewportrect.left = 0; viewportrect.top = 0; viewportrect.right = SCREENSPLIT1 - 6; // HACK: MAGIC #: 14 -> 6 -> (g_nFonWidthAvg-1) viewportrect.bottom = DISPLAY_HEIGHT - DEFAULT_HEIGHT; // 368 = 23 lines // TODO/FIXME // g_nFontHeight * g_nDisasmWinHeight; // 304 // TODO/FIXME: COLOR_BG_CODE -> g_iWindowThis, once all tab backgrounds are listed first in g_aColors ! SetBkColor(g_hDC, DebuggerGetColor( BG_DISASM_1 )); // COLOR_BG_CODE // Can't use DebugDrawText, since we don't need CLIPPED ExtTextOut(g_hDC,0,0,ETO_OPAQUE,&viewportrect,TEXT(""),0,NULL); } //=========================================================================== void DrawWindowBackground_Info( int g_iWindowThis ) { RECT viewportrect; viewportrect.top = 0; viewportrect.left = SCREENSPLIT1 - 6; // 14 // HACK: MAGIC #: 14 -> (g_nFontWidthAvg-1) viewportrect.right = 560; viewportrect.bottom = DISPLAY_HEIGHT; //g_nFontHeight * MAX_DISPLAY_INFO_LINES; // 384 SetBkColor(g_hDC, DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA // Can't use DebugDrawText, since we don't need CLIPPED ExtTextOut(g_hDC,0,0,ETO_OPAQUE,&viewportrect,TEXT(""),0,NULL); } //=========================================================================== void UpdateDisplay (Update_t bUpdate) { g_hDC = FrameGetDC(); SelectObject( g_hDC, g_aFontConfig[ FONT_INFO ]._hFont ); // g_hFontDebugger SetTextAlign(g_hDC,TA_TOP | TA_LEFT); if ((bUpdate & UPDATE_BREAKPOINTS) || (bUpdate & UPDATE_DISASM) || (bUpdate & UPDATE_FLAGS) || (bUpdate & UPDATE_MEM_DUMP) || (bUpdate & UPDATE_REGS) || (bUpdate & UPDATE_STACK) || (bUpdate & UPDATE_SYMBOLS) || (bUpdate & UPDATE_TARGETS) || (bUpdate & UPDATE_WATCH) || (bUpdate & UPDATE_ZERO_PAGE)) { bUpdate |= UPDATE_BACKGROUND; bUpdate |= UPDATE_CONSOLE_INPUT; } if (bUpdate & UPDATE_BACKGROUND) { if (g_iWindowThis != WINDOW_CONSOLE) { DrawWindowBackground_Main( g_iWindowThis ); DrawWindowBackground_Info( g_iWindowThis ); } } switch( g_iWindowThis ) { case WINDOW_CODE: DrawWindow_Code( bUpdate ); break; case WINDOW_CONSOLE: DrawWindow_Console( bUpdate ); break; case WINDOW_DATA: DrawWindow_Data( bUpdate ); break; case WINDOW_IO: DrawWindow_IO( bUpdate ); case WINDOW_SOURCE: DrawWindow_Source( bUpdate ); case WINDOW_SYMBOLS: DrawWindow_Symbols( bUpdate ); break; case WINDOW_ZEROPAGE: DrawWindow_ZeroPage( bUpdate ); default: break; } if ((bUpdate & UPDATE_CONSOLE_DISPLAY) || (bUpdate & UPDATE_CONSOLE_INPUT)) DrawSubWindow_Console( bUpdate ); FrameReleaseDC(); g_hDC = 0; } //=========================================================================== void DrawWindowBottom ( Update_t bUpdate, int iWindow ) { if (! g_aWindowConfig[ iWindow ].bSplit) return; WindowSplit_t * pWindow = &g_aWindowConfig[ iWindow ]; // if (pWindow->eBot == WINDOW_DATA) // { // DrawWindow_Data( bUpdate, false ); // } if (pWindow->eBot == WINDOW_SOURCE) DrawSubWindow_Source2( bUpdate ); } //=========================================================================== void DrawSubWindow_Code ( int iWindow ) { int nLines = g_nDisasmWinHeight; // Check if we have a bad disasm // BUG: This still doesn't catch all cases // G FB53, SPACE, PgDn * // Note: DrawDisassemblyLine() has kludge. // DisasmCalcTopFromCurAddress( false ); // These should be functionally equivalent. // DisasmCalcTopFromCurAddress(); // DisasmCalcBotFromTopAddress(); SelectObject( g_hDC, g_aFontConfig[ FONT_DISASM_DEFAULT ]._hFont ); // g_hFontDisasm WORD nAddress = g_nDisasmTopAddress; // g_nDisasmCurAddress; for (int iLine = 0; iLine < nLines; iLine++ ) { nAddress += DrawDisassemblyLine( g_hDC, iLine, nAddress, NULL); } SelectObject( g_hDC, g_aFontConfig[ FONT_INFO ]._hFont ); // g_hFontDebugger }