2010-06-11 15:38:22 +00:00
|
|
|
/*
|
|
|
|
AppleWin : An Apple //e emulator for Windows
|
|
|
|
|
|
|
|
Copyright (C) 1994-1996, Michael O'Brien
|
|
|
|
Copyright (C) 1999-2001, Oliver Schmidt
|
|
|
|
Copyright (C) 2002-2005, Tom Charlesworth
|
2014-08-28 18:13:02 +00:00
|
|
|
Copyright (C) 2006-2014, Tom Charlesworth, Michael Pohoreski
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
AppleWin is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
AppleWin is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with AppleWin; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Description: Debugger
|
|
|
|
*
|
2010-12-18 15:29:26 +00:00
|
|
|
* Author: Copyright (C) 2006-2010 Michael Pohoreski
|
2010-06-11 15:38:22 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "StdAfx.h"
|
2014-08-13 20:30:35 +00:00
|
|
|
|
|
|
|
#include "Debug.h"
|
|
|
|
#include "Debugger_Display.h"
|
|
|
|
|
2018-02-24 15:12:40 +00:00
|
|
|
#include "../Applewin.h"
|
|
|
|
#include "../CPU.h"
|
|
|
|
#include "../Frame.h"
|
|
|
|
#include "../Memory.h"
|
|
|
|
#include "../Mockingboard.h"
|
|
|
|
#include "../Video.h"
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2010-12-18 15:29:26 +00:00
|
|
|
// NEW UI debugging - force display ALL meta-info (regs, stack, bp, watches, zp) for debugging purposes
|
2010-06-11 15:38:22 +00:00
|
|
|
#define DEBUG_FORCE_DISPLAY 0
|
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
#define SOFTSWITCH_OLD 0
|
2017-04-27 19:02:09 +00:00
|
|
|
#define SOFTSWITCH_LANGCARD 1
|
2011-01-30 21:41:03 +00:00
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
#if _DEBUG
|
|
|
|
#define DEBUG_FONT_NO_BACKGROUND_CHAR 0
|
|
|
|
#define DEBUG_FONT_NO_BACKGROUND_TEXT 0
|
|
|
|
#define DEBUG_FONT_NO_BACKGROUND_FILL_CON 0
|
|
|
|
#define DEBUG_FONT_NO_BACKGROUND_FILL_INFO 0
|
|
|
|
#define DEBUG_FONT_NO_BACKGROUND_FILL_MAIN 0
|
|
|
|
|
|
|
|
// no top console line
|
|
|
|
#define DEBUG_BACKGROUND 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
//#define WATCH_ZERO_BG BG_DATA_1
|
|
|
|
#define WATCH_ZERO_BG BG_INFO
|
|
|
|
|
|
|
|
#define DISPLAY_MEMORY_TITLE 1
|
|
|
|
// #define DISPLAY_BREAKPOINT_TITLE 1
|
|
|
|
// #define DISPLAY_WATCH_TITLE 1
|
|
|
|
|
2014-12-02 06:01:08 +00:00
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
// Public _________________________________________________________________________________________
|
|
|
|
|
|
|
|
// Font
|
|
|
|
FontConfig_t g_aFontConfig[ NUM_FONTS ];
|
|
|
|
|
|
|
|
// Private ________________________________________________________________________________________
|
|
|
|
|
2014-12-02 06:01:08 +00:00
|
|
|
char g_aDebuggerVirtualTextScreen[ DEBUG_VIRTUAL_TEXT_HEIGHT ][ DEBUG_VIRTUAL_TEXT_WIDTH ];
|
2010-12-18 15:29:26 +00:00
|
|
|
|
|
|
|
// HACK HACK HACK
|
|
|
|
//g_nDisasmWinHeight
|
|
|
|
WindowSplit_t *g_pDisplayWindow = 0; // HACK
|
|
|
|
// HACK
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
// Display - Win32
|
2012-12-29 14:53:52 +00:00
|
|
|
static HDC g_hDebuggerMemDC = NULL;
|
|
|
|
static HBITMAP g_hDebuggerMemBM = NULL;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
HDC g_hConsoleFontDC = NULL;
|
|
|
|
HBRUSH g_hConsoleFontBrush = NULL;
|
|
|
|
HBITMAP g_hConsoleFontBitmap = NULL;
|
|
|
|
|
|
|
|
HBRUSH g_hConsoleBrushFG = NULL;
|
|
|
|
HBRUSH g_hConsoleBrushBG = NULL;
|
|
|
|
|
2010-12-18 15:29:26 +00:00
|
|
|
// NOTE: Keep in sync ConsoleColors_e g_anConsoleColor !
|
2010-06-11 15:38:22 +00:00
|
|
|
COLORREF g_anConsoleColor[ NUM_CONSOLE_COLORS ] =
|
2010-12-18 15:29:26 +00:00
|
|
|
{ // # <Bright Blue Green Red>
|
|
|
|
RGB( 0, 0, 0 ), // 0 0000 K
|
|
|
|
RGB( 255, 32, 32 ), // 1 1001 R
|
|
|
|
RGB( 0, 255, 0 ), // 2 1010 G
|
|
|
|
RGB( 255, 255, 0 ), // 3 1011 Y
|
|
|
|
RGB( 64, 64, 255 ), // 4 1100 B
|
|
|
|
RGB( 255, 0, 255 ), // 5 1101 M Purple/Magenta now used for warnings.
|
|
|
|
RGB( 0, 255, 255 ), // 6 1110 C
|
|
|
|
RGB( 255, 255, 255 ), // 7 1111 W
|
|
|
|
RGB( 255, 128, 0 ), // 8 0011 Orange
|
|
|
|
RGB( 128, 128, 128 ), // 9 0111 Grey
|
|
|
|
|
|
|
|
RGB( 80, 192, 255 ) // Lite Blue
|
2010-06-11 15:38:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// Disassembly
|
|
|
|
/*
|
|
|
|
// Thought about moving MouseText to another location, say high bit, 'A' + 0x80
|
|
|
|
// But would like to keep compatibility with existing CHARSET40
|
|
|
|
// Since we should be able to display all apple chars 0x00 .. 0xFF with minimal processing
|
|
|
|
// Use CONSOLE_COLOR_ESCAPE_CHAR to shift to mouse text
|
|
|
|
* Apple Font
|
|
|
|
K Mouse Text Up Arror
|
|
|
|
H Mouse Text Left Arrow
|
|
|
|
J Mouse Text Down Arrow
|
|
|
|
* 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
|
|
|
|
*/
|
|
|
|
#if USE_APPLE_FONT
|
|
|
|
char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x8B" }; // "`K" 0x4B
|
|
|
|
char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x88" }; // "`H" 0x48
|
|
|
|
char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x8A" }; // "`J" 0x4A
|
|
|
|
#else
|
|
|
|
char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x35" };
|
|
|
|
char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x33" };
|
|
|
|
char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x36" };
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Drawing
|
|
|
|
// Width
|
|
|
|
const int DISPLAY_WIDTH = 560;
|
|
|
|
// New Font = 50.5 char * 7 px/char = 353.5
|
|
|
|
const int DISPLAY_DISASM_RIGHT = 353 ;
|
|
|
|
|
|
|
|
#if USE_APPLE_FONT
|
|
|
|
// Horizontal Column (pixels) of Stack & Regs
|
2011-01-30 21:41:03 +00:00
|
|
|
const int INFO_COL_1 = (51 * CONSOLE_FONT_WIDTH);
|
|
|
|
const int DISPLAY_REGS_COLUMN = INFO_COL_1;
|
|
|
|
const int DISPLAY_FLAG_COLUMN = INFO_COL_1;
|
|
|
|
const int DISPLAY_STACK_COLUMN = INFO_COL_1;
|
|
|
|
const int DISPLAY_TARGETS_COLUMN = INFO_COL_1;
|
|
|
|
const int DISPLAY_ZEROPAGE_COLUMN = INFO_COL_1;
|
2014-12-02 06:01:08 +00:00
|
|
|
const int DISPLAY_SOFTSWITCH_COLUMN = INFO_COL_1 - (CONSOLE_FONT_WIDTH/2) + 1; // 1/2 char width padding around soft switches
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Horizontal Column (pixels) of BPs, Watches & Mem
|
|
|
|
const int INFO_COL_2 = (62 * 7); // nFontWidth
|
|
|
|
const int DISPLAY_BP_COLUMN = INFO_COL_2;
|
|
|
|
const int DISPLAY_WATCHES_COLUMN = INFO_COL_2;
|
|
|
|
const int DISPLAY_MINIMEM_COLUMN = INFO_COL_2;
|
|
|
|
#else
|
2012-12-29 14:53:52 +00:00
|
|
|
const int DISPLAY_CPU_INFO_LEFT_COLUMN = SCREENSPLIT1 // TC: SCREENSPLIT1 is not defined anywhere in the .sln!
|
2011-01-30 21:41:03 +00:00
|
|
|
|
|
|
|
const int DISPLAY_REGS_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
|
|
|
const int DISPLAY_FLAG_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
|
|
|
const int DISPLAY_STACK_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
|
|
|
const int DISPLAY_TARGETS_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
|
|
|
const int DISPLAY_ZEROPAGE_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN;
|
|
|
|
const int DISPLAY_SOFTSWITCH_COLUMN = DISPLAY_CPU_INFO_LEFT_COLUMN - (CONSOLE_FONT_WIDTH/2);
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
const int SCREENSPLIT2 = SCREENSPLIT1 + (12 * 7); // moved left 3 chars to show B. prefix in breakpoint #, W. prefix in watch #
|
|
|
|
const int DISPLAY_BP_COLUMN = SCREENSPLIT2;
|
|
|
|
const int DISPLAY_WATCHES_COLUMN = SCREENSPLIT2;
|
|
|
|
const int DISPLAY_MINIMEM_COLUMN = SCREENSPLIT2; // nFontWidth
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int MAX_DISPLAY_REGS_LINES = 7;
|
|
|
|
int MAX_DISPLAY_STACK_LINES = 8;
|
2011-01-04 17:33:10 +00:00
|
|
|
int MAX_DISPLAY_TARGET_PTR_LINES = 2;
|
2010-06-11 15:38:22 +00:00
|
|
|
int MAX_DISPLAY_ZEROPAGE_LINES = 8;
|
|
|
|
|
|
|
|
// int MAX_DISPLAY_BREAKPOINTS_LINES = 7; // 7
|
|
|
|
// int MAX_DISPLAY_WATCHES_LINES = 8; // 8
|
|
|
|
int MAX_DISPLAY_MEMORY_LINES_1 = 4; // 4
|
|
|
|
int MAX_DISPLAY_MEMORY_LINES_2 = 4; // 4 // 2
|
|
|
|
int g_nDisplayMemoryLines;
|
|
|
|
|
|
|
|
// 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 ( 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( char * 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_ );
|
|
|
|
|
|
|
|
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 );
|
|
|
|
|
2014-12-11 17:41:42 +00:00
|
|
|
char* FormatCharCopy( char *pDst, const char *pSrc, const int nLen );
|
|
|
|
char FormatCharTxtAsci( const BYTE b, bool * pWasAsci_ = NULL );
|
|
|
|
char FormatCharTxtCtrl( const BYTE b, bool * pWasCtrl_ = NULL );
|
|
|
|
char FormatCharTxtHigh( const BYTE b, bool *pWasHi_ = NULL );
|
|
|
|
char FormatChar4Font ( const BYTE b, bool *pWasHi_, bool *pWasLo_ );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/pantdraw_6n77.asp
|
|
|
|
enum WinROP4_e
|
|
|
|
{
|
|
|
|
DSna = 0x00220326,
|
|
|
|
DPSao = 0x00EA02E9,
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
Reverse Polish Notation
|
|
|
|
a Bitwise AND
|
|
|
|
n Bitwise NOT (inverse)
|
|
|
|
o Bitwise OR
|
|
|
|
x Bitwise exclusive OR (XOR)
|
|
|
|
|
|
|
|
Pen(P) 1 1 0 0 Decimal Result
|
|
|
|
Dest(D) 1 0 1 0 Boolean Operation
|
|
|
|
|
|
|
|
R2_BLACK 0 0 0 0 0 0
|
|
|
|
R2_NOTMERGEPEN 0 0 0 1 1 ~(P | D)
|
|
|
|
R2_MASKNOTPEN 0 0 1 0 2 ~P & D
|
|
|
|
R2_NOTCOPYPEN 0 0 1 1 3 ~P
|
|
|
|
R2_MASKPENNOT 0 1 0 0 4 P & ~D
|
|
|
|
R2_NOT 0 1 0 1 5 ~D
|
|
|
|
R2_XORPEN 0 1 1 0 6 P ^ D
|
|
|
|
R2_NOTMASKPEN 0 1 1 1 7 ~(P & D)
|
|
|
|
R2_MASKPEN 1 0 0 0 8 P & D
|
|
|
|
R2_NOTXORPEN 1 0 0 1 9 ~(P ^ D)
|
|
|
|
R2_NOPR2_NOP 1 0 1 0 10 D
|
|
|
|
R2_MERGENOTPEN 1 0 1 1 11 ~P | D
|
|
|
|
R2_COPYPEN 1 1 0 0 12 P (default)
|
|
|
|
R2_MERGEPENNOT 1 1 0 1 13 P | ~D
|
|
|
|
R2_MERGEPEN 1 1 1 0 14 P | D
|
|
|
|
R2_WHITE 1 1 1 1 15 1
|
|
|
|
*/
|
|
|
|
|
|
|
|
#if DEBUG_FONT_ROP
|
|
|
|
const DWORD aROP4[ 256 ] =
|
|
|
|
{
|
|
|
|
0x00000042, // BLACKNESS
|
|
|
|
0x00010289, // DPSoon
|
|
|
|
0x00020C89, // DPSona
|
|
|
|
0x000300AA, // PSon
|
|
|
|
0x00040C88, // SDPona
|
|
|
|
0x000500A9, // DPon
|
|
|
|
0x00060865, // PDSxnon
|
|
|
|
0x000702C5, // PDSaon
|
|
|
|
0x00080F08, // SDPnaa
|
|
|
|
0x00090245, // PDSxon
|
|
|
|
0x000A0329, // DPna
|
|
|
|
0x000B0B2A, // PSDnaon
|
|
|
|
0x000C0324, // SPna
|
|
|
|
0x000D0B25, // PDSnaon
|
|
|
|
0x000E08A5, // PDSonon
|
|
|
|
0x000F0001, // Pn
|
|
|
|
0x00100C85, // PDSona
|
|
|
|
0x001100A6, // DSon NOTSRCERASE
|
|
|
|
0x00120868, // SDPxnon
|
|
|
|
0x001302C8, // SDPaon
|
|
|
|
0x00140869, // DPSxnon
|
|
|
|
0x001502C9, // DPSaon
|
|
|
|
0x00165CCA, // PSDPSanaxx // 16
|
|
|
|
0x00171D54, // SSPxDSxaxn
|
|
|
|
0x00180D59, // SPxPDxa
|
|
|
|
0x00191CC8, // SDPSanaxn
|
|
|
|
0x001A06C5, // PDSPaox
|
|
|
|
0x001B0768, // SDPSxaxn
|
|
|
|
0x001C06CA, // PSDPaox
|
|
|
|
0x001D0766, // DSPDxaxn
|
|
|
|
0x001E01A5, // PDSox
|
|
|
|
0x001F0385, // PDSoan
|
|
|
|
0x00200F09, // DPSnaa
|
|
|
|
0x00210248, // SDPxon
|
|
|
|
0x00220326, // DSna
|
|
|
|
0x00230B24, // SPDnaon
|
|
|
|
0x00240D55, // SPxDSxa
|
|
|
|
0x00251CC5, // PDSPanaxn
|
|
|
|
0x002606C8, // SDPSaox
|
|
|
|
0x00271868, // SDPSxnox
|
|
|
|
0x00280369, // DPSxa
|
|
|
|
0x002916CA, // PSDPSaoxxn
|
|
|
|
0x002A0CC9, // DPSana
|
|
|
|
0x002B1D58, // SSPxPDxaxn
|
|
|
|
0x002C0784, // SPDSoax
|
|
|
|
0x002D060A, // PSDnox
|
|
|
|
0x002E064A, // PSDPxox
|
|
|
|
0x002F0E2A, // PSDnoan
|
|
|
|
0x0030032A, // PSna
|
|
|
|
0x00310B28, // SDPnaon
|
|
|
|
0x00320688, // SDPSoox
|
|
|
|
0x00330008, // Sn // 33 NOTSRCCOPY
|
|
|
|
0x003406C4, // SPDSaox
|
|
|
|
0x00351864, // SPDSxnox
|
|
|
|
0x003601A8, // SDPox
|
|
|
|
0x00370388, // SDPoan
|
|
|
|
0x0038078A, // PSDPoax
|
|
|
|
0x00390604, // SPDnox
|
|
|
|
0x003A0644, // SPDSxox
|
|
|
|
0x003B0E24, // SPDnoan
|
|
|
|
0x003C004A, // PSx
|
|
|
|
0x003D18A4, // SPDSonox
|
|
|
|
0x003E1B24, // SPDSnaox
|
|
|
|
0x003F00EA, // PSan
|
|
|
|
0x00400F0A, // PSDnaa
|
|
|
|
0x00410249, // DPSxon
|
|
|
|
0x00420D5D, // SDxPDxa
|
|
|
|
0x00431CC4, // SPDSanaxn
|
|
|
|
0x00440328, // SDna // 44 SRCERASE
|
|
|
|
0x00450B29, // DPSnaon
|
|
|
|
0x004606C6, // DSPDaox
|
|
|
|
0x0047076A, // PSDPxaxn
|
|
|
|
0x00480368, // SDPxa
|
|
|
|
0x004916C5, // PDSPDaoxxn
|
|
|
|
0x004A0789, // DPSDoax
|
|
|
|
0x004B0605, // PDSnox
|
|
|
|
0x004C0CC8, // SDPana
|
|
|
|
0x004D1954, // SSPxDSxoxn
|
|
|
|
0x004E0645, // PDSPxox
|
|
|
|
0x004F0E25, // PDSnoan
|
|
|
|
0x00500325, // PDna
|
|
|
|
0x00510B26, // DSPnaon
|
|
|
|
0x005206C9, // DPSDaox
|
|
|
|
0x00530764, // SPDSxaxn
|
|
|
|
0x005408A9, // DPSonon
|
|
|
|
0x00550009, // Dn // 55 DSTINVERT
|
|
|
|
0x005601A9, // DPSox
|
|
|
|
0x00570389, // DPSoan
|
|
|
|
0x00580785, // PDSPoax
|
|
|
|
0x00590609, // DPSnox
|
|
|
|
0x005A0049, // DPx // 5A PATINVERT
|
|
|
|
0x005B18A9, // DPSDonox
|
|
|
|
0x005C0649, // DPSDxox
|
|
|
|
0x005D0E29, // DPSnoan
|
|
|
|
0x005E1B29, // DPSDnaox
|
|
|
|
0x005F00E9, // DPan
|
|
|
|
0x00600365, // PDSxa
|
|
|
|
0x006116C6, // DSPDSaoxxn
|
|
|
|
0x00620786, // DSPDoax
|
|
|
|
0x00630608, // SDPnox
|
|
|
|
0x00640788, // SDPSoax
|
|
|
|
0x00650606, // DSPnox
|
|
|
|
0x00660046, // DSx // 66 SRCINVERT
|
|
|
|
0x006718A8, // SDPSonox
|
|
|
|
0x006858A6, // DSPDSonoxxn
|
|
|
|
0x00690145, // PDSxxn
|
|
|
|
0x006A01E9, // DPSax
|
|
|
|
0x006B178A, // PSDPSoaxxn
|
|
|
|
0x006C01E8, // SDPax
|
|
|
|
0x006D1785, // PDSPDoaxxn
|
|
|
|
0x006E1E28, // SDPSnoax
|
|
|
|
0x006F0C65, // PDSxnan
|
|
|
|
0x00700CC5, // PDSana
|
|
|
|
0x00711D5C, // SSDxPDxaxn
|
|
|
|
0x00720648, // SDPSxox
|
|
|
|
0x00730E28, // SDPnoan
|
|
|
|
0x00740646, // DSPDxox
|
|
|
|
0x00750E26, // DSPnoan
|
|
|
|
0x00761B28, // SDPSnaox
|
|
|
|
0x007700E6, // DSan
|
|
|
|
0x007801E5, // PDSax
|
|
|
|
0x00791786, // DSPDSoaxxn
|
|
|
|
0x007A1E29, // DPSDnoax
|
|
|
|
0x007B0C68, // SDPxnan
|
|
|
|
0x007C1E24, // SPDSnoax
|
|
|
|
0x007D0C69, // DPSxnan
|
|
|
|
0x007E0955, // SPxDSxo
|
|
|
|
0x007F03C9, // DPSaan
|
|
|
|
0x008003E9, // DPSaa
|
|
|
|
0x00810975, // SPxDSxon
|
|
|
|
0x00820C49, // DPSxna
|
|
|
|
0x00831E04, // SPDSnoaxn
|
|
|
|
0x00840C48, // SDPxna
|
|
|
|
0x00851E05, // PDSPnoaxn
|
|
|
|
0x008617A6, // DSPDSoaxx
|
|
|
|
0x008701C5, // PDSaxn
|
|
|
|
0x008800C6, // DSa // 88 SRCAND
|
|
|
|
0x00891B08, // SDPSnaoxn
|
|
|
|
0x008A0E06, // DSPnoa
|
|
|
|
0x008B0666, // DSPDxoxn
|
|
|
|
0x008C0E08, // SDPnoa
|
|
|
|
0x008D0668, // SDPSxoxn
|
|
|
|
0x008E1D7C, // SSDxPDxax
|
|
|
|
0x008F0CE5, // PDSanan
|
|
|
|
0x00900C45, // PDSxna
|
|
|
|
0x00911E08, // SDPSnoaxn
|
|
|
|
0x009217A9, // DPSDPoaxx
|
|
|
|
0x009301C4, // SPDaxn
|
|
|
|
0x009417AA, // PSDPSoaxx
|
|
|
|
0x009501C9, // DPSaxn
|
|
|
|
0x00960169, // DPSxx
|
|
|
|
0x0097588A, // PSDPSonoxx
|
|
|
|
0x00981888, // SDPSonoxn
|
|
|
|
0x00990066, // DSxn
|
|
|
|
0x009A0709, // DPSnax
|
|
|
|
0x009B07A8, // SDPSoaxn
|
|
|
|
0x009C0704, // SPDnax
|
|
|
|
0x009D07A6, // DSPDoaxn
|
|
|
|
0x009E16E6, // DSPDSaoxx
|
|
|
|
0x009F0345, // PDSxan
|
|
|
|
0x00A000C9, // DPa
|
|
|
|
0x00A11B05, // PDSPnaoxn
|
|
|
|
0x00A20E09, // DPSnoa
|
|
|
|
0x00A30669, // DPSDxoxn
|
|
|
|
0x00A41885, // PDSPonoxn
|
|
|
|
0x00A50065, // PDxn
|
|
|
|
0x00A60706, // DSPnax
|
|
|
|
0x00A707A5, // PDSPoaxn
|
|
|
|
0x00A803A9, // DPSoa
|
|
|
|
0x00A90189, // DPSoxn
|
|
|
|
0x00AA0029, // D // AA DSTCOPY
|
|
|
|
0x00AB0889, // DPSono
|
|
|
|
0x00AC0744, // SPDSxax
|
|
|
|
0x00AD06E9, // DPSDaoxn
|
|
|
|
0x00AE0B06, // DSPnao
|
|
|
|
0x00AF0229, // DPno
|
|
|
|
0x00B00E05, // PDSnoa
|
|
|
|
0x00B10665, // PDSPxoxn
|
|
|
|
0x00B21974, // SSPxDSxox
|
|
|
|
0x00B30CE8, // SDPanan
|
|
|
|
0x00B4070A, // PSDnax
|
|
|
|
0x00B507A9, // DPSDoaxn
|
|
|
|
0x00B616E9, // DPSDPaoxx
|
|
|
|
0x00B70348, // SDPxan
|
|
|
|
0x00B8074A, // PSDPxax
|
|
|
|
0x00B906E6, // DSPDaoxn
|
|
|
|
0x00BA0B09, // DPSnao
|
|
|
|
0x00BB0226, // DSno // BB MERGEPAINT
|
|
|
|
0x00BC1CE4, // SPDSanax
|
|
|
|
0x00BD0D7D, // SDxPDxan
|
|
|
|
0x00BE0269, // DPSxo
|
|
|
|
0x00BF08C9, // DPSano
|
|
|
|
0x00C000CA, // PSa // C0 MERGECOPY
|
|
|
|
0x00C11B04, // SPDSnaoxn
|
|
|
|
0x00C21884, // SPDSonoxn
|
|
|
|
0x00C3006A, // PSxn
|
|
|
|
0x00C40E04, // SPDnoa
|
|
|
|
0x00C50664, // SPDSxoxn
|
|
|
|
0x00C60708, // SDPnax
|
|
|
|
0x00C707AA, // PSDPoaxn
|
|
|
|
0x00C803A8, // SDPoa
|
|
|
|
0x00C90184, // SPDoxn
|
|
|
|
0x00CA0749, // DPSDxax
|
|
|
|
0x00CB06E4, // SPDSaoxn
|
|
|
|
0x00CC0020, // S // CC SRCCOPY
|
|
|
|
0x00CD0888, // SDPono
|
|
|
|
0x00CE0B08, // SDPnao
|
|
|
|
0x00CF0224, // SPno
|
|
|
|
0x00D00E0A, // PSDnoa
|
|
|
|
0x00D1066A, // PSDPxoxn
|
|
|
|
0x00D20705, // PDSnax
|
|
|
|
0x00D307A4, // SPDSoaxn
|
|
|
|
0x00D41D78, // SSPxPDxax
|
|
|
|
0x00D50CE9, // DPSanan
|
|
|
|
0x00D616EA, // PSDPSaoxx
|
|
|
|
0x00D70349, // DPSxan
|
|
|
|
0x00D80745, // PDSPxax
|
|
|
|
0x00D906E8, // SDPSaoxn
|
|
|
|
0x00DA1CE9, // DPSDanax
|
|
|
|
0x00DB0D75, // SPxDSxan
|
|
|
|
0x00DC0B04, // SPDnao
|
|
|
|
0x00DD0228, // SDno
|
|
|
|
0x00DE0268, // SDPxo
|
|
|
|
0x00DF08C8, // SDPano
|
|
|
|
0x00E003A5, // PDSoa
|
|
|
|
0x00E10185, // PDSoxn
|
|
|
|
0x00E20746, // DSPDxax
|
|
|
|
0x00E306EA, // PSDPaoxn
|
|
|
|
0x00E40748, // SDPSxax
|
|
|
|
0x00E506E5, // PDSPaoxn
|
|
|
|
0x00E61CE8, // SDPSanax
|
|
|
|
0x00E70D79, // SPxPDxan
|
|
|
|
0x00E81D74, // SSPxDSxax
|
|
|
|
0x00E95CE6, // DSPDSanaxxn
|
|
|
|
0x00EA02E9, // DPSao
|
|
|
|
0x00EB0849, // DPSxno
|
|
|
|
0x00EC02E8, // SDPao
|
|
|
|
0x00ED0848, // SDPxno
|
|
|
|
0x00EE0086, // DSo // EE SRCPAINT
|
|
|
|
0x00EF0A08, // SDPnoo
|
|
|
|
0x00F00021, // P // F0 PATCOPY
|
|
|
|
0x00F10885, // PDSono
|
|
|
|
0x00F20B05, // PDSnao
|
|
|
|
0x00F3022A, // PSno
|
|
|
|
0x00F40B0A, // PSDnao
|
|
|
|
0x00F50225, // PDno
|
|
|
|
0x00F60265, // PDSxo
|
|
|
|
0x00F708C5, // PDSano
|
|
|
|
0x00F802E5, // PDSao
|
|
|
|
0x00F90845, // PDSxno
|
|
|
|
0x00FA0089, // DPo
|
|
|
|
0x00FB0A09, // DPSnoo // FB PATPAINT
|
|
|
|
0x00FC008A, // PSo
|
|
|
|
0x00FD0A0A, // PSDnoo
|
|
|
|
0x00FE02A9, // DPSoo
|
|
|
|
0x00FF0062 // _WHITE // FF WHITENESS
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// PATPAINT
|
|
|
|
// MERGECOPY
|
|
|
|
// SRCINVERT
|
|
|
|
// SRCCOPY
|
|
|
|
// 0xAA00EC
|
|
|
|
// 0x00EC02E8
|
|
|
|
|
|
|
|
#if DEBUG_FONT_ROP
|
|
|
|
static iRop4 = 0;
|
|
|
|
#endif
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
//===========================================================================
|
|
|
|
|
|
|
|
HDC GetDebuggerMemDC(void)
|
|
|
|
{
|
|
|
|
if (!g_hDebuggerMemDC)
|
|
|
|
{
|
|
|
|
HDC hFrameDC = FrameGetDC();
|
|
|
|
g_hDebuggerMemDC = CreateCompatibleDC(hFrameDC);
|
2017-10-11 16:38:36 +00:00
|
|
|
g_hDebuggerMemBM = CreateCompatibleBitmap(hFrameDC, GetFrameBufferWidth(), GetFrameBufferHeight());
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject(g_hDebuggerMemDC, g_hDebuggerMemBM);
|
|
|
|
}
|
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
_ASSERT(g_hDebuggerMemDC); // TC: Could this be NULL?
|
2012-12-29 14:53:52 +00:00
|
|
|
return g_hDebuggerMemDC;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ReleaseDebuggerMemDC(void)
|
|
|
|
{
|
|
|
|
if (g_hDebuggerMemDC)
|
|
|
|
{
|
|
|
|
DeleteObject(g_hDebuggerMemBM);
|
|
|
|
g_hDebuggerMemBM = NULL;
|
|
|
|
DeleteDC(g_hDebuggerMemDC);
|
|
|
|
g_hDebuggerMemDC = NULL;
|
|
|
|
FrameReleaseDC();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void StretchBltMemToFrameDC(void)
|
|
|
|
{
|
|
|
|
int nViewportCX, nViewportCY;
|
|
|
|
GetViewportCXCY(nViewportCX, nViewportCY);
|
|
|
|
|
2017-10-11 16:38:36 +00:00
|
|
|
int xdest = IsFullScreen() ? GetFullScreenOffsetX() : 0;
|
|
|
|
int ydest = IsFullScreen() ? GetFullScreenOffsetY() : 0;
|
2016-07-26 21:33:45 +00:00
|
|
|
int wdest = nViewportCX;
|
|
|
|
int hdest = nViewportCY;
|
2016-07-12 21:43:31 +00:00
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
BOOL bRes = StretchBlt(
|
|
|
|
FrameGetDC(), // HDC hdcDest,
|
2016-07-26 21:33:45 +00:00
|
|
|
xdest, ydest, // int nXOriginDest, int nYOriginDest,
|
|
|
|
wdest, hdest, // int nWidthDest, int nHeightDest,
|
2012-12-29 14:53:52 +00:00
|
|
|
GetDebuggerMemDC(), // HDC hdcSrc,
|
|
|
|
0, 0, // int nXOriginSrc, int nYOriginSrc,
|
2017-10-11 16:38:36 +00:00
|
|
|
GetFrameBufferBorderlessWidth(), GetFrameBufferBorderlessHeight(), // int nWidthSrc, int nHeightSrc,
|
2012-12-29 14:53:52 +00:00
|
|
|
SRCCOPY // DWORD dwRop
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
// Font: Apple Text
|
|
|
|
//===========================================================================
|
|
|
|
void DebuggerSetColorFG( COLORREF nRGB )
|
|
|
|
{
|
|
|
|
#if USE_APPLE_FONT
|
|
|
|
if (g_hConsoleBrushFG)
|
|
|
|
{
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( GetDebuggerMemDC(), GetStockObject(NULL_BRUSH) );
|
2010-06-11 15:38:22 +00:00
|
|
|
DeleteObject( g_hConsoleBrushFG );
|
|
|
|
g_hConsoleBrushFG = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hConsoleBrushFG = CreateSolidBrush( nRGB );
|
|
|
|
#else
|
2012-12-29 14:53:52 +00:00
|
|
|
SetTextColor( GetDebuggerMemDC(), nRGB );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//===================================================
|
|
|
|
void DebuggerSetColorBG( COLORREF nRGB, bool bTransparent )
|
|
|
|
{
|
|
|
|
#if USE_APPLE_FONT
|
|
|
|
if (g_hConsoleBrushBG)
|
|
|
|
{
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( GetDebuggerMemDC(), GetStockObject(NULL_BRUSH) );
|
2010-06-11 15:38:22 +00:00
|
|
|
DeleteObject( g_hConsoleBrushBG );
|
|
|
|
g_hConsoleBrushBG = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! bTransparent)
|
|
|
|
{
|
|
|
|
g_hConsoleBrushBG = CreateSolidBrush( nRGB );
|
|
|
|
}
|
|
|
|
#else
|
2012-12-29 14:53:52 +00:00
|
|
|
SetBkColor( GetDebuggerMemDC(), nRGB );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// @param glyph Specifies a native glyph from the 16x16 chars Apple Font Texture.
|
|
|
|
//===========================================================================
|
|
|
|
void PrintGlyph( const int x, const int y, const char glyph )
|
|
|
|
{
|
2012-12-29 14:53:52 +00:00
|
|
|
HDC hDstDC = GetDebuggerMemDC();
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int xDst = x;
|
|
|
|
int yDst = y;
|
|
|
|
|
|
|
|
// 16x8 chars in bitmap
|
|
|
|
int xSrc = (glyph & 0x0F) * CONSOLE_FONT_GRID_X;
|
|
|
|
int ySrc = (glyph >> 4) * CONSOLE_FONT_GRID_Y;
|
|
|
|
|
2014-12-02 06:01:08 +00:00
|
|
|
// BUG #239 - (Debugger) Save debugger "text screen" to clipboard / file
|
|
|
|
// if( g_bDebuggerVirtualTextCapture )
|
|
|
|
//
|
|
|
|
{
|
|
|
|
#if _DEBUG
|
|
|
|
if ((x < 0) || (y < 0))
|
|
|
|
MessageBox( g_hFrameWindow, "X or Y out of bounds!", "PrintGlyph()", MB_OK );
|
|
|
|
#endif
|
|
|
|
int col = x / CONSOLE_FONT_WIDTH ;
|
|
|
|
int row = y / CONSOLE_FONT_HEIGHT;
|
|
|
|
|
|
|
|
// if( !g_bDebuggerCopyInfoPane )
|
|
|
|
// if( col < 50
|
|
|
|
if (x > DISPLAY_DISASM_RIGHT) // INFO_COL_2 // DISPLAY_CPU_INFO_LEFT_COLUMN
|
|
|
|
col++;
|
|
|
|
|
|
|
|
if ((col < DEBUG_VIRTUAL_TEXT_WIDTH)
|
|
|
|
&& (row < DEBUG_VIRTUAL_TEXT_HEIGHT))
|
|
|
|
g_aDebuggerVirtualTextScreen[ row ][ col ] = glyph;
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
#if !DEBUG_FONT_NO_BACKGROUND_CHAR
|
|
|
|
// Background color
|
|
|
|
if (g_hConsoleBrushBG)
|
|
|
|
{
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( hDstDC, g_hConsoleBrushBG );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Draw Background (solid pattern)
|
|
|
|
BitBlt(
|
2012-12-29 14:53:52 +00:00
|
|
|
hDstDC, // hdcDest
|
2010-06-11 15:38:22 +00:00
|
|
|
xDst, yDst, // nXDest, nYDest
|
|
|
|
CONSOLE_FONT_WIDTH, CONSOLE_FONT_HEIGHT, // nWidth, nHeight
|
|
|
|
g_hConsoleFontDC, // hdcSrc
|
|
|
|
0, CONSOLE_FONT_GRID_Y * 2, // nXSrc, nYSrc // FontTexture[2][0] = Solid (Filled) Space
|
|
|
|
PATCOPY // dwRop
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
// SelectObject( hDstDC, GetStockBrush( WHITE_BRUSH ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// http://kkow.net/etep/docs/rop.html
|
|
|
|
// P 1 1 1 1 0 0 0 0 (Pen/Pattern)
|
|
|
|
// S 1 1 0 0 1 1 0 0 (Source)
|
|
|
|
// D 1 0 1 0 1 0 1 0 (Destination)
|
|
|
|
// =================
|
|
|
|
// 0 0 1 0 0 0 1 0 0x22 DSna
|
|
|
|
// 1 1 1 0 1 0 1 0 0xEA DPSao
|
|
|
|
|
|
|
|
// Black = Transparent (DC Background)
|
|
|
|
// White = Opaque (DC Text color)
|
|
|
|
|
|
|
|
#if DEBUG_FONT_ROP
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( hDstDC, g_hConsoleBrushFG );
|
2010-06-11 15:38:22 +00:00
|
|
|
BitBlt(
|
2012-12-29 14:53:52 +00:00
|
|
|
hDstDC,
|
2010-06-11 15:38:22 +00:00
|
|
|
xDst, yDst,
|
|
|
|
DEBUG_FONT_WIDTH, DEBUG_FONT_HEIGHT,
|
|
|
|
g_hDebugFontDC,
|
|
|
|
xSrc, ySrc,
|
|
|
|
aROP4[ iRop4 ]
|
|
|
|
);
|
|
|
|
#else
|
|
|
|
// Use inverted source as mask (AND)
|
|
|
|
// D & ~S -> DSna
|
|
|
|
BitBlt(
|
2012-12-29 14:53:52 +00:00
|
|
|
hDstDC,
|
2010-06-11 15:38:22 +00:00
|
|
|
xDst, yDst,
|
|
|
|
CONSOLE_FONT_WIDTH, CONSOLE_FONT_HEIGHT,
|
|
|
|
g_hConsoleFontDC,
|
|
|
|
xSrc, ySrc,
|
|
|
|
DSna
|
|
|
|
);
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( hDstDC, g_hConsoleBrushFG );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2010-12-18 15:29:26 +00:00
|
|
|
// Use Source as mask to make color Pattern mask (AND), then apply to dest (OR)
|
2010-06-11 15:38:22 +00:00
|
|
|
// D | (P & S) -> DPSao
|
|
|
|
BitBlt(
|
2012-12-29 14:53:52 +00:00
|
|
|
hDstDC,
|
2010-06-11 15:38:22 +00:00
|
|
|
xDst, yDst,
|
|
|
|
CONSOLE_FONT_WIDTH, CONSOLE_FONT_HEIGHT,
|
|
|
|
g_hConsoleFontDC,
|
|
|
|
xSrc, ySrc,
|
|
|
|
DPSao
|
|
|
|
);
|
|
|
|
#endif
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( hDstDC, GetStockObject(NULL_BRUSH) );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DebuggerPrint ( int x, int y, const char *pText )
|
|
|
|
{
|
|
|
|
const int nLeft = x;
|
|
|
|
|
|
|
|
char c;
|
|
|
|
const char *p = pText;
|
|
|
|
|
|
|
|
while (c = *p)
|
|
|
|
{
|
|
|
|
if (c == '\n')
|
|
|
|
{
|
|
|
|
x = nLeft;
|
|
|
|
y += CONSOLE_FONT_HEIGHT;
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
c &= 0x7F;
|
|
|
|
PrintGlyph( x, y, c );
|
|
|
|
x += CONSOLE_FONT_WIDTH;
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DebuggerPrintColor( int x, int y, const conchar_t * pText )
|
|
|
|
{
|
|
|
|
int nLeft = x;
|
|
|
|
|
|
|
|
conchar_t g;
|
|
|
|
const conchar_t *pSrc = pText;
|
|
|
|
|
|
|
|
if( !pText)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (g = (*pSrc))
|
|
|
|
{
|
|
|
|
if (g == '\n')
|
|
|
|
{
|
|
|
|
x = nLeft;
|
|
|
|
y += CONSOLE_FONT_HEIGHT;
|
|
|
|
pSrc++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ConsoleColor_IsColorOrMouse( g ))
|
|
|
|
{
|
|
|
|
if (ConsoleColor_IsColor( g ))
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( ConsoleColor_GetColor( g ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
g = ConsoleChar_GetChar( g );
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintGlyph( x, y, (char) (g & _CONSOLE_COLOR_MASK) );
|
|
|
|
x += CONSOLE_FONT_WIDTH;
|
|
|
|
pSrc++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Utility ________________________________________________________________________________________
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
bool CanDrawDebugger()
|
|
|
|
{
|
2016-11-06 14:23:23 +00:00
|
|
|
if (DebugGetVideoMode(NULL))
|
2010-06-11 15:38:22 +00:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if ((g_nAppMode == MODE_DEBUG) || (g_nAppMode == MODE_STEPPING))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
int PrintText ( const char * pText, RECT & rRect )
|
|
|
|
{
|
|
|
|
#if _DEBUG
|
|
|
|
if (! pText)
|
2013-12-06 21:10:41 +00:00
|
|
|
MessageBox( g_hFrameWindow, "pText = NULL!", "DrawText()", MB_OK );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
int nLen = strlen( pText );
|
|
|
|
|
|
|
|
#if !DEBUG_FONT_NO_BACKGROUND_TEXT
|
2012-12-29 14:53:52 +00:00
|
|
|
FillRect( GetDebuggerMemDC(), &rRect, g_hConsoleBrushBG );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
DebuggerPrint( rRect.left, rRect.top, pText );
|
|
|
|
return nLen;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void PrintTextColor ( const conchar_t *pText, RECT & rRect )
|
|
|
|
{
|
|
|
|
#if !DEBUG_FONT_NO_BACKGROUND_TEXT
|
2012-12-29 14:53:52 +00:00
|
|
|
FillRect( GetDebuggerMemDC(), &rRect, g_hConsoleBrushBG );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
DebuggerPrintColor( rRect.left, rRect.top, pText );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Updates the horizontal cursor
|
|
|
|
//===========================================================================
|
|
|
|
int PrintTextCursorX ( const char * pText, RECT & rRect )
|
|
|
|
{
|
|
|
|
int nChars = 0;
|
|
|
|
if (pText)
|
|
|
|
{
|
|
|
|
nChars = PrintText( pText, rRect );
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nFontWidthAvg;
|
|
|
|
rRect.left += (nFontWidth * nChars);
|
|
|
|
}
|
|
|
|
return nChars;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
int PrintTextCursorY ( const char * pText, RECT & rRect )
|
|
|
|
{
|
|
|
|
int nChars = PrintText( pText, rRect );
|
|
|
|
rRect.top += g_nFontHeight;
|
|
|
|
rRect.bottom += g_nFontHeight;
|
|
|
|
return nChars;
|
|
|
|
}
|
|
|
|
|
2014-12-11 17:41:42 +00:00
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
char* FormatCharCopy( char *pDst, const char *pSrc, const int nLen )
|
|
|
|
{
|
|
|
|
for( int i = 0; i < nLen; i++ )
|
|
|
|
*pDst++ = FormatCharTxtCtrl( *pSrc++ );
|
|
|
|
return pDst;
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
//===========================================================================
|
|
|
|
char FormatCharTxtAsci ( const BYTE b, bool * pWasAsci_ )
|
|
|
|
{
|
|
|
|
if (pWasAsci_)
|
|
|
|
*pWasAsci_ = false;
|
|
|
|
|
|
|
|
char c = (b & 0x7F);
|
|
|
|
if (b <= 0x7F)
|
|
|
|
{
|
|
|
|
if (pWasAsci_)
|
|
|
|
{
|
2014-08-25 22:33:53 +00:00
|
|
|
*pWasAsci_ = true;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
2014-12-11 17:41:42 +00:00
|
|
|
// Note: FormatCharTxtCtrl() and RemapChar()
|
2010-06-11 15:38:22 +00:00
|
|
|
//===========================================================================
|
|
|
|
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_)
|
|
|
|
{
|
2014-08-25 22:33:53 +00:00
|
|
|
*pWasCtrl_ = true;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void SetupColorsHiLoBits ( 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)
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ));
|
|
|
|
|
|
|
|
if (bHighBit)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iColorHiBG ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iColorHiFG )); // was iForeground
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bCtrlBit)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iColorLoBG ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iColorLoFG ));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// To flush out color bugs... swap: iAsciBackground & iHighBackground
|
|
|
|
//===========================================================================
|
|
|
|
char ColorizeSpecialChar( char * 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)
|
|
|
|
sprintf( sText, "%c", nChar );
|
|
|
|
|
|
|
|
#if OLD_CONSOLE_COLOR
|
|
|
|
if (sText)
|
|
|
|
{
|
|
|
|
if (ConsoleColor_IsEscapeMeta( nChar ))
|
|
|
|
sprintf( sText, "%c%c", nChar, nChar );
|
|
|
|
else
|
|
|
|
sprintf( sText, "%c", nChar );
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// if (hDC)
|
|
|
|
{
|
|
|
|
SetupColorsHiLoBits( bHighBit, bCtrlBit
|
|
|
|
, iTextBG, iTextFG // FG_DISASM_CHAR
|
|
|
|
, iHighBG, iHighFG // BG_INFO_CHAR
|
|
|
|
, iCtrlBG, iCtrlFG // FG_DISASM_OPCODE
|
|
|
|
);
|
|
|
|
}
|
|
|
|
return nChar;
|
|
|
|
}
|
|
|
|
|
2017-05-10 16:47:45 +00:00
|
|
|
void ColorizeFlags( bool bSet, int bg_default = BG_INFO, int fg_default = FG_INFO_TITLE )
|
2011-01-30 21:41:03 +00:00
|
|
|
{
|
|
|
|
if (bSet)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO_INVERSE ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_INVERSE ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-05-10 16:47:45 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg_default ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( fg_default ));
|
2011-01-30 21:41:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Main Windows ___________________________________________________________________________________
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawBreakpoints ( 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;
|
|
|
|
char sText[16] = "Breakpoints"; // TODO: Move to BP1
|
|
|
|
|
|
|
|
#if DISPLAY_BREAKPOINT_TITLE
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE )); //COLOR_STATIC
|
|
|
|
PrintText( sText, rect );
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int nBreakpointsDisplayed = 0;
|
|
|
|
|
|
|
|
int iBreakpoint;
|
|
|
|
for (iBreakpoint = 0; iBreakpoint < MAX_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;
|
|
|
|
|
|
|
|
#if DEBUG_FORCE_DISPLAY
|
|
|
|
// if (iBreakpoint < MAX_DISPLAY_BREAKPOINTS_LINES)
|
|
|
|
bSet = true;
|
|
|
|
#endif
|
|
|
|
if (! bSet)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
nBreakpointsDisplayed++;
|
|
|
|
|
|
|
|
// if (nBreakpointsDisplayed > MAX_DISPLAY_BREAKPOINTS_LINES)
|
|
|
|
// break;
|
|
|
|
|
|
|
|
RECT rect2;
|
|
|
|
rect2 = rect;
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ) );
|
|
|
|
sprintf( sText, "B" );
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_BULLET ) );
|
|
|
|
sprintf( sText, "%X ", iBreakpoint );
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ) );
|
|
|
|
// strcpy( sText, "." );
|
|
|
|
// PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
#if DEBUG_FORCE_DISPLAY
|
|
|
|
pBP->eSource = (BreakpointSource_t) iBreakpoint;
|
|
|
|
#endif
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG ) );
|
|
|
|
int nRegLen = PrintTextCursorX( g_aBreakpointSource[ pBP->eSource ], rect2 );
|
|
|
|
|
|
|
|
// Pad to 2 chars
|
|
|
|
if (nRegLen < 2)
|
|
|
|
rect2.left += g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( 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
|
|
|
|
PrintTextCursorX( 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
|
|
|
|
|
|
|
#if DEBUG_FORCE_DISPLAY
|
2010-12-16 06:43:05 +00:00
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int iColor = R8 + iBreakpoint;
|
2010-12-16 06:43:05 +00:00
|
|
|
COLORREF nColor = g_aColorPalette[ iColor ];
|
2010-06-11 15:38:22 +00:00
|
|
|
if (iBreakpoint >= 8)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DISASM_BP_S_C ) );
|
|
|
|
nColor = DebuggerGetColor( FG_DISASM_BP_S_C );
|
|
|
|
}
|
|
|
|
DebuggerSetColorFG( nColor );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sprintf( sText, "%04X", nAddress1 );
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
if (nLength > 1)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ) );
|
|
|
|
|
|
|
|
// if (g_bConfigDisasmOpcodeSpaces)
|
|
|
|
// {
|
|
|
|
// PrintTextCursorX( " ", rect2 );
|
|
|
|
// rect2.left += g_nFontWidthAvg;
|
|
|
|
// }
|
|
|
|
|
|
|
|
PrintTextCursorX( ":", rect2 );
|
|
|
|
// rect2.left += g_nFontWidthAvg;
|
|
|
|
// if (g_bConfigDisasmOpcodeSpaces) // TODO: Might have to remove spaces, for BPIO... addr-addr xx
|
|
|
|
// {
|
|
|
|
// rect2.left += g_nFontWidthAvg;
|
|
|
|
// }
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
|
|
|
#if DEBUG_FORCE_DISPLAY
|
2010-12-16 06:43:05 +00:00
|
|
|
COLORREF nColor = g_aColorPalette[ iColor ];
|
2010-06-11 15:38:22 +00:00
|
|
|
if (iBreakpoint >= 8)
|
|
|
|
{
|
|
|
|
nColor = DebuggerGetColor( BG_INFO );
|
|
|
|
DebuggerSetColorBG( nColor );
|
|
|
|
nColor = DebuggerGetColor( FG_DISASM_BP_S_X );
|
|
|
|
}
|
|
|
|
DebuggerSetColorFG( nColor );
|
|
|
|
#endif
|
|
|
|
sprintf( sText, "%04X", nAddress2 );
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !USE_APPLE_FONT
|
|
|
|
// Windows HACK: Bugfix: Rest of line is still breakpoint background color
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE )); //COLOR_STATIC
|
|
|
|
PrintTextCursorX( " ", rect2 );
|
|
|
|
#endif
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Console ________________________________________________________________________________________
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
int GetConsoleLineHeightPixels()
|
|
|
|
{
|
2016-03-21 23:48:02 +00:00
|
|
|
int nHeight = g_aFontConfig[ FONT_CONSOLE ]._nFontHeight; // _nLineHeight; // _nFontHeight;
|
2010-06-11 15:38:22 +00:00
|
|
|
/*
|
|
|
|
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 DrawConsoleCursor ()
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_CONSOLE_INPUT ));
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_CONSOLE_INPUT ));
|
|
|
|
|
|
|
|
int nWidth = g_aFontConfig[ FONT_CONSOLE ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
int nLineHeight = GetConsoleLineHeightPixels();
|
|
|
|
int y = 0;
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
rect.left = (g_nConsoleInputChars + g_nConsolePromptLen) * nWidth;
|
|
|
|
rect.top = GetConsoleTopPixels( y );
|
|
|
|
rect.bottom = rect.top + nLineHeight; //g_nFontHeight;
|
|
|
|
rect.right = rect.left + nWidth;
|
|
|
|
|
|
|
|
PrintText( g_sConsoleCursor, rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void GetConsoleRect ( const int y, RECT & rect )
|
|
|
|
{
|
|
|
|
int nLineHeight = GetConsoleLineHeightPixels();
|
|
|
|
|
|
|
|
rect.left = 0;
|
|
|
|
rect.top = GetConsoleTopPixels( y );
|
|
|
|
rect.bottom = rect.top + nLineHeight; //g_nFontHeight;
|
|
|
|
|
|
|
|
// int nHeight = WindowGetHeight( g_iWindowThis );
|
|
|
|
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_CONSOLE ]._nFontWidthAvg;
|
|
|
|
int nMiniConsoleRight = g_nConsoleDisplayWidth * nFontWidth;
|
|
|
|
int nFullConsoleRight = DISPLAY_WIDTH;
|
|
|
|
int nRight = g_bConsoleFullWidth ? nFullConsoleRight : nMiniConsoleRight;
|
|
|
|
rect.right = nRight;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawConsoleLine ( const conchar_t * pText, int y )
|
|
|
|
{
|
|
|
|
if (y < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
GetConsoleRect( y, rect );
|
|
|
|
|
|
|
|
// Console background is drawn in DrawWindowBackground_Info
|
|
|
|
PrintTextColor( pText, rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawConsoleInput ()
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_CONSOLE_INPUT ));
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_CONSOLE_INPUT ));
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
GetConsoleRect( 0, rect );
|
|
|
|
|
|
|
|
// Console background is drawn in DrawWindowBackground_Info
|
|
|
|
// DrawConsoleLine( g_aConsoleInput, 0 );
|
|
|
|
PrintText( g_aConsoleInput, rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Disassembly ____________________________________________________________________________________
|
|
|
|
|
|
|
|
|
2010-12-19 17:10:02 +00:00
|
|
|
// Get the data needed to disassemble one line of opcodes. Fills in the DisasmLine info.
|
2010-06-11 15:38:22 +00:00
|
|
|
// Disassembly formatting flags returned
|
|
|
|
// @parama sTargetValue_ indirect/indexed final value
|
|
|
|
//===========================================================================
|
|
|
|
int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|
|
|
// char *sAddress_, char *sOpCodes_,
|
|
|
|
// char *sTarget_, char *sTargetOffset_, int & nTargetOffset_,
|
|
|
|
// char *sTargetPointer_, char *sTargetValue_,
|
|
|
|
// char *sImmediate_, char & nImmediate_, char *sBranch_ )
|
|
|
|
{
|
|
|
|
line_.Clear();
|
|
|
|
|
|
|
|
int iOpcode;
|
|
|
|
int iOpmode;
|
|
|
|
int nOpbyte;
|
|
|
|
|
2014-08-28 23:52:41 +00:00
|
|
|
iOpcode = _6502_GetOpmodeOpbyte( nBaseAddress, iOpmode, nOpbyte, &line_.pDisasmData );
|
|
|
|
const DisasmData_t* pData = line_.pDisasmData; // Disassembly_IsDataAddress( nBaseAddress );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
line_.iOpcode = iOpcode;
|
|
|
|
line_.iOpmode = iOpmode;
|
|
|
|
line_.nOpbyte = nOpbyte;
|
|
|
|
|
|
|
|
#if _DEBUG
|
|
|
|
// if (iLine != 41)
|
|
|
|
// return nOpbytes;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (iOpmode == AM_M)
|
|
|
|
line_.bTargetImmediate = true;
|
|
|
|
|
|
|
|
if ((iOpmode >= AM_IZX) && (iOpmode <= AM_NA))
|
|
|
|
line_.bTargetIndirect = true; // ()
|
|
|
|
|
|
|
|
if ((iOpmode >= AM_IZX) && (iOpmode <= AM_NZY))
|
|
|
|
line_.bTargetIndexed = true; // ()
|
|
|
|
|
|
|
|
if (((iOpmode >= AM_A) && (iOpmode <= AM_ZY)) || line_.bTargetIndirect)
|
|
|
|
line_.bTargetValue = true; // #$
|
|
|
|
|
|
|
|
if ((iOpmode == AM_AX) || (iOpmode == AM_ZX) || (iOpmode == AM_IZX) || (iOpmode == AM_IAX))
|
|
|
|
line_.bTargetX = true; // ,X
|
|
|
|
|
|
|
|
if ((iOpmode == AM_AY) || (iOpmode == AM_ZY) || (iOpmode == AM_NZY))
|
|
|
|
line_.bTargetY = true; // ,Y
|
|
|
|
|
2014-08-28 23:52:41 +00:00
|
|
|
unsigned int nMinBytesLen = (MAX_OPCODES * (2 + g_bConfigDisasmOpcodeSpaces)); // 2 char for byte (or 3 with space)
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int bDisasmFormatFlags = 0;
|
|
|
|
|
|
|
|
// Composite string that has the symbol or target nAddress
|
|
|
|
WORD nTarget = 0;
|
|
|
|
|
|
|
|
if ((iOpmode != AM_IMPLIED) &&
|
|
|
|
(iOpmode != AM_1) &&
|
|
|
|
(iOpmode != AM_2) &&
|
|
|
|
(iOpmode != AM_3))
|
|
|
|
{
|
2010-12-19 17:10:02 +00:00
|
|
|
// Assume target address starts after the opcode ...
|
|
|
|
// BUT in the Assembler Directve / Data Disassembler case for define addr/word
|
|
|
|
// the opcode literally IS the target address!
|
|
|
|
if( pData )
|
|
|
|
{
|
|
|
|
nTarget = pData->nTargetAddress;
|
|
|
|
} else {
|
|
|
|
nTarget = *(LPWORD)(mem+nBaseAddress+1);
|
|
|
|
if (nOpbyte == 2)
|
|
|
|
nTarget &= 0xFF;
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
if (iOpmode == AM_R) // Relative
|
|
|
|
{
|
|
|
|
line_.bTargetRelative = true;
|
|
|
|
|
|
|
|
nTarget = nBaseAddress+2+(int)(signed char)nTarget;
|
|
|
|
|
|
|
|
line_.nTarget = nTarget;
|
|
|
|
sprintf( line_.sTargetValue, "%04X", nTarget & 0xFFFF );
|
|
|
|
|
|
|
|
// Always show branch indicators
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_BRANCH;
|
|
|
|
|
|
|
|
if (nTarget < nBaseAddress)
|
|
|
|
{
|
|
|
|
sprintf( line_.sBranch, "%s", g_sConfigBranchIndicatorUp[ g_iConfigDisasmBranchType ] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (nTarget > nBaseAddress)
|
|
|
|
{
|
|
|
|
sprintf( line_.sBranch, "%s", g_sConfigBranchIndicatorDown[ g_iConfigDisasmBranchType ] );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf( line_.sBranch, "%s", g_sConfigBranchIndicatorEqual[ g_iConfigDisasmBranchType ] );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// intentional re-test AM_R ...
|
|
|
|
|
|
|
|
// if ((iOpmode >= AM_A) && (iOpmode <= AM_NA))
|
|
|
|
if ((iOpmode == AM_A ) || // Absolute
|
|
|
|
(iOpmode == AM_Z ) || // Zeropage
|
|
|
|
(iOpmode == AM_AX ) || // Absolute, X
|
|
|
|
(iOpmode == AM_AY ) || // Absolute, Y
|
|
|
|
(iOpmode == AM_ZX ) || // Zeropage, X
|
|
|
|
(iOpmode == AM_ZY ) || // Zeropage, Y
|
|
|
|
(iOpmode == AM_R ) || // Relative
|
|
|
|
(iOpmode == AM_IZX) || // Indexed (Zeropage Indirect, X)
|
|
|
|
(iOpmode == AM_IAX) || // Indexed (Absolute Indirect, X)
|
|
|
|
(iOpmode == AM_NZY) || // Indirect (Zeropage) Index, Y
|
|
|
|
(iOpmode == AM_NZ ) || // Indirect (Zeropage)
|
2010-12-19 17:10:02 +00:00
|
|
|
(iOpmode == AM_NA )) //(Indirect Absolute)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
|
|
|
line_.nTarget = nTarget;
|
|
|
|
|
2010-12-19 17:10:02 +00:00
|
|
|
const char* pTarget = NULL;
|
|
|
|
const char* pSymbol = 0;
|
|
|
|
|
|
|
|
pSymbol = FindSymbolFromAddress( nTarget );
|
|
|
|
|
|
|
|
// Data Assembler
|
|
|
|
if (pData && (!pData->bSymbolLookup))
|
|
|
|
pSymbol = 0;
|
|
|
|
|
2011-01-04 17:33:10 +00:00
|
|
|
// Try exact match first
|
2010-06-11 15:38:22 +00:00
|
|
|
if (pSymbol)
|
|
|
|
{
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
|
|
|
pTarget = pSymbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
|
|
|
|
{
|
|
|
|
pSymbol = FindSymbolFromAddress( nTarget - 1 );
|
|
|
|
if (pSymbol)
|
|
|
|
{
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_OFFSET;
|
|
|
|
pTarget = pSymbol;
|
|
|
|
line_.nTargetOffset = +1; // U FA82 LDA $3F1 BREAK-1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-22 20:47:29 +00:00
|
|
|
// Old Offset search: (Search +1 First) nTarget-1, (Search -1 Second) nTarget+1
|
|
|
|
// Problem: U D038 shows as A.TRACE+1
|
|
|
|
// New Offset search: (Search -1 First) nTarget+1, (Search +1 Second) nTarget+1
|
|
|
|
// Problem: U D834, D87E shows as P.MUL-1, instead of P.ADD+1
|
|
|
|
// 2.6.2.31 Fixed: address table was bailing on first possible match. U D000 -> da STOP+1, instead of END-1
|
|
|
|
// 2.7.0.0: Try to match nTarget-1, nTarget+1, AND if we have both matches
|
|
|
|
// Then we need to decide which one to show. If we have pData then pick this one.
|
|
|
|
// TODO: Do we need to let the user decide which one they want searched first?
|
|
|
|
// nFirstTarget = g_bDebugConfig_DisasmMatchSymbolOffsetMinus1First ? nTarget-1 : nTarget+1;
|
|
|
|
// nSecondTarget = g_bDebugConfig_DisasmMatchSymbolOffsetMinus1First ? nTarget+1 : nTarget-1;
|
|
|
|
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL) || pData)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
|
|
|
pSymbol = FindSymbolFromAddress( nTarget + 1 );
|
|
|
|
if (pSymbol)
|
|
|
|
{
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_SYMBOL;
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_OFFSET;
|
|
|
|
pTarget = pSymbol;
|
|
|
|
line_.nTargetOffset = -1; // U FA82 LDA $3F3 BREAK+1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
|
|
|
|
{
|
|
|
|
pTarget = FormatAddress( nTarget, nOpbyte );
|
|
|
|
}
|
|
|
|
|
|
|
|
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
|
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
|
|
|
|
{
|
|
|
|
int nAbsTargetOffset = (line_.nTargetOffset > 0) ? line_.nTargetOffset : - line_.nTargetOffset;
|
|
|
|
sprintf( line_.sTargetOffset, "%d", nAbsTargetOffset );
|
|
|
|
}
|
|
|
|
sprintf( line_.sTarget, "%s", pTarget );
|
|
|
|
|
|
|
|
|
|
|
|
// Indirect / Indexed
|
|
|
|
int nTargetPartial;
|
2017-08-04 19:52:17 +00:00
|
|
|
int nTargetPartial2;
|
2010-06-11 15:38:22 +00:00
|
|
|
int nTargetPointer;
|
|
|
|
WORD nTargetValue = 0; // de-ref
|
|
|
|
int nTargetBytes;
|
2017-08-04 19:52:17 +00:00
|
|
|
_6502_GetTargets( nBaseAddress, &nTargetPartial, &nTargetPartial2, &nTargetPointer, &nTargetBytes );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
if (nTargetPointer != NO_6502_TARGET)
|
|
|
|
{
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_POINTER;
|
|
|
|
|
|
|
|
nTargetValue = *(LPWORD)(mem+nTargetPointer);
|
|
|
|
|
|
|
|
// if (((iOpmode >= AM_A) && (iOpmode <= AM_NZ)) && (iOpmode != AM_R))
|
|
|
|
// nTargetBytes refers to size of pointer, not size of value
|
|
|
|
// sprintf( sTargetValue_, "%04X", nTargetValue ); // & 0xFFFF
|
|
|
|
|
|
|
|
if (g_iConfigDisasmTargets & DISASM_TARGET_ADDR)
|
|
|
|
sprintf( line_.sTargetPointer, "%04X", nTargetPointer & 0xFFFF );
|
|
|
|
|
|
|
|
if (iOpmode != AM_NA ) // Indirect Absolute
|
|
|
|
{
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_TARGET_VALUE;
|
|
|
|
if (g_iConfigDisasmTargets & DISASM_TARGET_VAL)
|
|
|
|
sprintf( line_.sTargetValue, "%02X", nTargetValue & 0xFF );
|
|
|
|
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
|
|
|
|
line_.nImmediate = (BYTE) nTargetValue;
|
|
|
|
|
|
|
|
unsigned _char = FormatCharTxtCtrl( FormatCharTxtHigh( line_.nImmediate, NULL ), NULL );
|
|
|
|
sprintf( line_.sImmediate, "%c", _char );
|
|
|
|
|
|
|
|
// if (ConsoleColorIsEscapeMeta( nImmediate_ ))
|
|
|
|
#if OLD_CONSOLE_COLOR
|
|
|
|
if (ConsoleColorIsEscapeMeta( _char ))
|
|
|
|
sprintf( line_.sImmediate, "%c%c", _char, _char );
|
|
|
|
else
|
|
|
|
sprintf( line_.sImmediate, "%c", _char );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// if (iOpmode == AM_NA ) // Indirect Absolute
|
|
|
|
// sprintf( sTargetValue_, "%04X", nTargetPointer & 0xFFFF );
|
|
|
|
// else
|
|
|
|
// // sprintf( sTargetValue_, "%02X", nTargetValue & 0xFF );
|
|
|
|
// sprintf( sTargetValue_, "%04X:%02X", nTargetPointer & 0xFFFF, nTargetValue & 0xFF );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (iOpmode == AM_M)
|
|
|
|
{
|
|
|
|
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, (unsigned)nTarget );
|
|
|
|
sprintf( line_.sTarget, "%02X", (unsigned)nTarget );
|
|
|
|
|
|
|
|
if (iOpmode == AM_M)
|
|
|
|
{
|
|
|
|
bDisasmFormatFlags |= DISASM_FORMAT_CHAR;
|
|
|
|
line_.nImmediate = (BYTE) nTarget;
|
|
|
|
unsigned _char = FormatCharTxtCtrl( FormatCharTxtHigh( line_.nImmediate, NULL ), NULL );
|
|
|
|
|
|
|
|
sprintf( line_.sImmediate, "%c", _char );
|
|
|
|
#if OLD_CONSOLE_COLOR
|
|
|
|
if (ConsoleColorIsEscapeMeta( _char ))
|
|
|
|
sprintf( line_.sImmediate, "%c%c", _char, _char );
|
|
|
|
else
|
|
|
|
sprintf( line_.sImmediate, "%c", _char );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sprintf( line_.sAddress, "%04X", nBaseAddress );
|
|
|
|
|
|
|
|
// Opcode Bytes
|
|
|
|
FormatOpcodeBytes( nBaseAddress, line_ );
|
|
|
|
|
2010-12-19 17:10:02 +00:00
|
|
|
// Data Disassembler
|
|
|
|
if( pData )
|
|
|
|
{
|
|
|
|
line_.iNoptype = pData->eElementType;
|
|
|
|
line_.iNopcode = pData->iDirective;
|
|
|
|
strcpy( line_.sMnemonic, g_aAssemblerDirectives[ line_.iNopcode ].m_pMnemonic );
|
|
|
|
|
|
|
|
FormatNopcodeBytes( nBaseAddress, line_ );
|
|
|
|
} else { // Regular 6502/65C02 opcode -> mnemonic
|
|
|
|
strcpy( line_.sMnemonic, g_aOpcodes[ line_.iOpcode ].sMnemonic );
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
int nSpaces = strlen( line_.sOpCodes );
|
|
|
|
while (nSpaces < (int)nMinBytesLen)
|
|
|
|
{
|
|
|
|
strcat( line_.sOpCodes, " " );
|
|
|
|
nSpaces++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return bDisasmFormatFlags;
|
|
|
|
}
|
|
|
|
|
2010-12-19 17:10:02 +00:00
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
const char* FormatAddress( WORD nAddress, int nBytes )
|
|
|
|
{
|
|
|
|
// There is no symbol for this nAddress
|
|
|
|
static TCHAR sSymbol[8] = TEXT("");
|
|
|
|
switch (nBytes)
|
|
|
|
{
|
|
|
|
case 2: wsprintf(sSymbol,TEXT("$%02X"),(unsigned)nAddress); break;
|
|
|
|
case 3: wsprintf(sSymbol,TEXT("$%04X"),(unsigned)nAddress); break;
|
|
|
|
// TODO: FIXME: Can we get called with nBytes == 16 ??
|
|
|
|
default: sSymbol[0] = 0; break; // clear since is static
|
|
|
|
}
|
|
|
|
return sSymbol;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
//===========================================================================
|
|
|
|
void FormatOpcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|
|
|
{
|
|
|
|
int nOpbyte = line_.nOpbyte;
|
|
|
|
|
|
|
|
char *pDst = line_.sOpCodes;
|
2014-08-28 23:52:41 +00:00
|
|
|
int nMaxOpBytes = nOpbyte;
|
|
|
|
if ( nMaxOpBytes > MAX_OPCODES) // 2.8.0.0 fix // TODO: FIX: show max 8 bytes for HEX
|
|
|
|
nMaxOpBytes = MAX_OPCODES;
|
|
|
|
|
|
|
|
for( int iByte = 0; iByte < nMaxOpBytes; iByte++ )
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
|
|
|
BYTE nMem = (unsigned)*(mem+nBaseAddress + iByte);
|
|
|
|
sprintf( pDst, "%02X", nMem ); // sBytes+strlen(sBytes)
|
|
|
|
pDst += 2;
|
|
|
|
|
2014-08-28 23:52:41 +00:00
|
|
|
// TODO: If Disassembly_IsDataAddress() don't show spaces...
|
2010-06-11 15:38:22 +00:00
|
|
|
if (g_bConfigDisasmOpcodeSpaces)
|
|
|
|
{
|
|
|
|
strcat( pDst, " " );
|
|
|
|
pDst++; // 2.5.3.3 fix
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Formats Target string with bytes,words, string, etc...
|
|
|
|
//===========================================================================
|
|
|
|
void FormatNopcodeBytes ( WORD nBaseAddress, DisasmLine_t & line_ )
|
|
|
|
{
|
2014-08-30 17:03:00 +00:00
|
|
|
char *pDst = line_.sTarget;
|
|
|
|
const char *pSrc = 0;
|
|
|
|
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;
|
2014-08-28 18:13:02 +00:00
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
for( int iByte = 0; iByte < line_.nOpbyte; )
|
|
|
|
{
|
|
|
|
BYTE nTarget8 = *(LPBYTE)(mem + nBaseAddress + iByte);
|
|
|
|
WORD nTarget16 = *(LPWORD)(mem + nBaseAddress + iByte);
|
|
|
|
|
|
|
|
switch( line_.iNoptype )
|
|
|
|
{
|
|
|
|
case NOP_BYTE_1:
|
2010-12-19 17:10:02 +00:00
|
|
|
case NOP_BYTE_2:
|
|
|
|
case NOP_BYTE_4:
|
2010-12-19 17:29:51 +00:00
|
|
|
case NOP_BYTE_8:
|
2010-12-19 17:10:02 +00:00
|
|
|
sprintf( pDst, "%02X", nTarget8 ); // sBytes+strlen(sBytes)
|
2010-12-19 17:29:51 +00:00
|
|
|
pDst += 2;
|
2010-06-11 15:38:22 +00:00
|
|
|
iByte++;
|
2010-12-19 17:29:51 +00:00
|
|
|
if( line_.iNoptype == NOP_BYTE_1)
|
|
|
|
if( iByte < line_.nOpbyte )
|
|
|
|
{
|
|
|
|
*pDst++ = ',';
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
break;
|
|
|
|
case NOP_WORD_1:
|
2010-12-19 17:10:02 +00:00
|
|
|
case NOP_WORD_2:
|
|
|
|
case NOP_WORD_4:
|
|
|
|
sprintf( pDst, "%04X", nTarget16 ); // sBytes+strlen(sBytes)
|
2010-12-19 17:29:51 +00:00
|
|
|
pDst += 4;
|
2010-06-11 15:38:22 +00:00
|
|
|
iByte+= 2;
|
|
|
|
if( iByte < line_.nOpbyte )
|
|
|
|
{
|
|
|
|
*pDst++ = ',';
|
|
|
|
}
|
|
|
|
break;
|
2010-12-19 17:29:51 +00:00
|
|
|
case NOP_ADDRESS:
|
2010-12-19 20:29:58 +00:00
|
|
|
// Nothing to do, already handled :-)
|
2010-12-19 17:29:51 +00:00
|
|
|
iByte += 2;
|
|
|
|
break;
|
2010-06-11 15:38:22 +00:00
|
|
|
case NOP_STRING_APPLESOFT:
|
|
|
|
iByte = line_.nOpbyte;
|
|
|
|
strncpy( pDst, (const char*)(mem + nBaseAddress), iByte );
|
|
|
|
pDst += iByte;
|
|
|
|
*pDst = 0;
|
2014-08-28 18:13:02 +00:00
|
|
|
case NOP_STRING_APPLE:
|
2014-08-30 17:03:00 +00:00
|
|
|
iByte = line_.nOpbyte; // handle all bytes of text
|
|
|
|
pSrc = (const char*)mem + nStartAddress;
|
|
|
|
|
|
|
|
if (len > (MAX_IMMEDIATE_LEN - 2)) // does "text" fit?
|
|
|
|
{
|
|
|
|
if (len > MAX_IMMEDIATE_LEN) // no; need extra characters for ellipsis?
|
|
|
|
len = (MAX_IMMEDIATE_LEN - 3); // ellipsis = true
|
2014-08-28 18:13:02 +00:00
|
|
|
|
2014-08-30 17:03:00 +00:00
|
|
|
// DISPLAY: text_longer_18...
|
2014-12-11 17:41:42 +00:00
|
|
|
FormatCharCopy( pDst, pSrc, len ); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
2014-08-28 18:13:02 +00:00
|
|
|
|
2014-08-30 17:03:00 +00:00
|
|
|
if( nDisplayLen > len ) // ellipsis
|
|
|
|
{
|
|
|
|
*pDst++ = '.';
|
|
|
|
*pDst++ = '.';
|
|
|
|
*pDst++ = '.';
|
|
|
|
}
|
|
|
|
} else { // DISPLAY: "max_18_char"
|
|
|
|
*pDst++ = '"';
|
2014-12-11 17:41:42 +00:00
|
|
|
pDst = FormatCharCopy( pDst, pSrc, len ); // BUG: #251 v2.8.0.7: ASC #:# with null byte doesn't mark up properly
|
2014-08-30 17:03:00 +00:00
|
|
|
*pDst++ = '"';
|
2014-08-28 18:13:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*pDst = 0;
|
|
|
|
break;
|
2010-06-11 15:38:22 +00:00
|
|
|
default:
|
2014-08-28 18:13:02 +00:00
|
|
|
#if _DEBUG // Unhandled data disassembly!
|
2010-12-19 17:10:02 +00:00
|
|
|
int *FATAL = 0;
|
|
|
|
*FATAL = 0xDEADC0DE;
|
|
|
|
#endif
|
|
|
|
iByte++;
|
2010-06-11 15:38:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-12-16 06:43:05 +00:00
|
|
|
//===========================================================================
|
2010-06-11 15:38:22 +00:00
|
|
|
void FormatDisassemblyLine( const DisasmLine_t & line, char * sDisassembly, const int nBufferSize )
|
|
|
|
{
|
|
|
|
//> Address Seperator Opcodes Label Mnemonic Target [Immediate] [Branch]
|
|
|
|
//
|
|
|
|
// Data Disassembler
|
|
|
|
// Label Directive [Immediate]
|
|
|
|
const char * pMnemonic = g_aOpcodes[ line.iOpcode ].sMnemonic;
|
|
|
|
|
|
|
|
sprintf( sDisassembly, "%s:%s %s "
|
|
|
|
, line.sAddress
|
|
|
|
, line.sOpCodes
|
|
|
|
, pMnemonic
|
|
|
|
);
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (line.bTargetIndexed || line.bTargetIndirect)
|
|
|
|
{
|
|
|
|
strcat( sDisassembly, "(" );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (line.bTargetImmediate)
|
|
|
|
strcat( sDisassembly, "#$" );
|
|
|
|
|
|
|
|
if (line.bTargetValue)
|
|
|
|
strcat( sDisassembly, line.sTarget );
|
|
|
|
|
|
|
|
if (line.bTargetIndirect)
|
|
|
|
{
|
|
|
|
if (line.bTargetX)
|
|
|
|
strcat( sDisassembly, ", X" );
|
|
|
|
if (line.bTargetY)
|
|
|
|
strcat( sDisassembly, ", Y" );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (line.bTargetIndexed || line.bTargetIndirect)
|
|
|
|
{
|
|
|
|
strcat( sDisassembly, ")" );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (line.bTargetIndirect)
|
|
|
|
{
|
|
|
|
if (line.bTargetY)
|
|
|
|
strcat( sDisassembly, ", Y" );
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
char sTarget[ 32 ];
|
|
|
|
|
|
|
|
if (line.bTargetValue || line.bTargetRelative || line.bTargetImmediate)
|
|
|
|
{
|
|
|
|
if (line.bTargetRelative)
|
|
|
|
strcpy( sTarget, line.sTargetValue );
|
|
|
|
else
|
|
|
|
if (line.bTargetImmediate)
|
|
|
|
{
|
|
|
|
strcat( sDisassembly, "#" );
|
|
|
|
strcpy( sTarget, line.sTarget ); // sTarget
|
|
|
|
}
|
|
|
|
else
|
|
|
|
sprintf( sTarget, g_aOpmodes[ line.iOpmode ].m_sFormat, line.nTarget );
|
|
|
|
|
|
|
|
strcat( sDisassembly, "$" );
|
|
|
|
strcat( sDisassembly, sTarget );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
WORD DrawDisassemblyLine ( int iLine, const WORD nBaseAddress )
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
int iOpcode;
|
|
|
|
int iOpmode;
|
|
|
|
int nOpbyte;
|
|
|
|
DisasmLine_t line;
|
2010-12-19 17:10:02 +00:00
|
|
|
const char* pSymbol = FindSymbolFromAddress( nBaseAddress );
|
|
|
|
const char* pMnemonic = NULL;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2010-12-19 17:10:02 +00:00
|
|
|
// Data Disassembler
|
2010-06-11 15:38:22 +00:00
|
|
|
int bDisasmFormatFlags = GetDisassemblyLine( nBaseAddress, line );
|
2010-12-19 17:10:02 +00:00
|
|
|
const DisasmData_t *pData = line.pDisasmData;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
iOpcode = line.iOpcode;
|
|
|
|
iOpmode = line.iOpmode;
|
|
|
|
nOpbyte = line.nOpbyte;
|
|
|
|
|
|
|
|
// sAddress, sOpcodes, sTarget, sTargetOffset, nTargetOffset, sTargetPointer, sTargetValue, 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
|
|
|
|
|
|
|
|
enum TabStop_e
|
|
|
|
{
|
|
|
|
TS_OPCODE
|
|
|
|
, TS_LABEL
|
|
|
|
, TS_INSTRUCTION
|
|
|
|
, TS_IMMEDIATE
|
|
|
|
, TS_BRANCH
|
|
|
|
, TS_CHAR
|
|
|
|
, _NUM_TAB_STOPS
|
|
|
|
};
|
|
|
|
|
|
|
|
// int X_OPCODE = 6 * nDefaultFontWidth;
|
|
|
|
// int X_LABEL = 17 * nDefaultFontWidth;
|
|
|
|
// int X_INSTRUCTION = 26 * nDefaultFontWidth; // 27
|
|
|
|
// int X_IMMEDIATE = 40 * nDefaultFontWidth; // 41
|
|
|
|
// int X_BRANCH = 46 * nDefaultFontWidth;
|
|
|
|
|
|
|
|
float aTabs[ _NUM_TAB_STOPS ] =
|
|
|
|
// { 6, 16, 26, 41, 46, 49 }; // 6, 17, 26, 40, 46
|
|
|
|
#if USE_APPLE_FONT
|
|
|
|
// { 5, 14, 20, 40, 46, 49 };
|
|
|
|
// xxxx:xx xx xx LABELxxxxxx MNEMONIC 'E' =
|
|
|
|
// 0 45 14 26
|
|
|
|
{ 5, 14, 26, 41, 48, 49 };
|
|
|
|
#else
|
|
|
|
{ 5.75, 15.5, 25, 40.5, 45.5, 48.5 };
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !USE_APPLE_FONT
|
|
|
|
if (! g_bConfigDisasmAddressColon)
|
|
|
|
{
|
|
|
|
aTabs[ TS_OPCODE ] -= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((g_bConfigDisasmOpcodesView) && (! g_bConfigDisasmOpcodeSpaces))
|
|
|
|
{
|
|
|
|
aTabs[ TS_LABEL ] -= 3;
|
|
|
|
aTabs[ TS_INSTRUCTION ] -= 2;
|
|
|
|
aTabs[ TS_IMMEDIATE ] -= 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
const int OPCODE_TO_LABEL_SPACE = static_cast<int>( aTabs[ TS_INSTRUCTION ] - aTabs[ TS_LABEL ] );
|
|
|
|
|
|
|
|
int iTab = 0;
|
|
|
|
int nSpacer = 11; // 9
|
|
|
|
for (iTab = 0; iTab < _NUM_TAB_STOPS; iTab++ )
|
|
|
|
{
|
|
|
|
if (! g_bConfigDisasmAddressView )
|
|
|
|
{
|
|
|
|
if (iTab < TS_IMMEDIATE) // TS_BRANCH)
|
|
|
|
{
|
|
|
|
aTabs[ iTab ] -= 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (! g_bConfigDisasmOpcodesView)
|
|
|
|
{
|
|
|
|
if (iTab < TS_IMMEDIATE) // TS_BRANCH)
|
|
|
|
{
|
|
|
|
aTabs[ iTab ] -= nSpacer;
|
|
|
|
if (nSpacer > 0)
|
|
|
|
nSpacer -= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aTabs[ iTab ] *= nDefaultFontWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if USE_APPLE_FONT
|
|
|
|
const int DISASM_SYMBOL_LEN = 12;
|
|
|
|
#else
|
|
|
|
const int DISASM_SYMBOL_LEN = 9;
|
|
|
|
#endif
|
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
int nFontHeight = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nLineHeight; // _nFontHeight; // g_nFontHeight
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
RECT linerect;
|
|
|
|
linerect.left = 0;
|
|
|
|
linerect.top = iLine * nFontHeight;
|
|
|
|
linerect.right = DISPLAY_DISASM_RIGHT;
|
|
|
|
linerect.bottom = linerect.top + nFontHeight;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
bool bBreakpointActive;
|
|
|
|
bool bBreakpointEnable;
|
|
|
|
GetBreakpointInfo( nBaseAddress, bBreakpointActive, bBreakpointEnable );
|
|
|
|
bool bAddressAtPC = (nBaseAddress == regs.pc);
|
|
|
|
bool bAddressIsBookmark = Bookmark_Find( nBaseAddress );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
DebugColors_e iBackground = BG_DISASM_1;
|
|
|
|
DebugColors_e iForeground = FG_DISASM_MNEMONIC; // FG_DISASM_TEXT;
|
|
|
|
bool bCursorLine = false;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (((! g_bDisasmCurBad) && (iLine == g_nDisasmCurLine))
|
|
|
|
|| (g_bDisasmCurBad && (iLine == 0)))
|
|
|
|
{
|
|
|
|
bCursorLine = true;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// Breakpoint
|
|
|
|
if (bBreakpointActive)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
if (bBreakpointEnable)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
iBackground = BG_DISASM_BP_S_C; iForeground = FG_DISASM_BP_S_C;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
iBackground = BG_DISASM_BP_0_C; iForeground = FG_DISASM_BP_0_C;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
2017-12-17 18:20:39 +00:00
|
|
|
if (bAddressAtPC)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
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;
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// This address has a breakpoint, but the cursor is not on it (atm)
|
|
|
|
if (bBreakpointActive)
|
|
|
|
{
|
|
|
|
if (bBreakpointEnable)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
iForeground = FG_DISASM_BP_S_X; // Red (old Yellow)
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
iForeground = FG_DISASM_BP_0_X; // Yellow
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
else
|
|
|
|
if (bAddressAtPC)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
iBackground = BG_DISASM_PC_X; iForeground = FG_DISASM_PC_X;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
iForeground = FG_DISASM_MNEMONIC;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (bAddressIsBookmark)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DISASM_BOOKMARK ) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_BOOKMARK ) );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
// Address
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ) );
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// DebuggerSetColorBG( GetDebuggerMemDC(), DebuggerGetColor( FG_DISASM_BOOKMARK ) ); // swapped
|
|
|
|
// DebuggerSetColorFG( GetDebuggerMemDC(), DebuggerGetColor( BG_DISASM_BOOKMARK ) ); // swapped
|
|
|
|
// }
|
|
|
|
|
|
|
|
if( g_bConfigDisasmAddressView )
|
|
|
|
{
|
|
|
|
PrintTextCursorX( (LPCTSTR) line.sAddress, linerect );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bAddressIsBookmark)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Address Seperator
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (g_bConfigDisasmAddressColon)
|
|
|
|
PrintTextCursorX( ":", linerect );
|
|
|
|
else
|
|
|
|
PrintTextCursorX( " ", linerect ); // bugfix, not showing "addr:" doesn't alternate color lines
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Opcodes
|
2017-12-17 18:20:39 +00:00
|
|
|
linerect.left = (int) aTabs[ TS_OPCODE ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPCODE ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (g_bConfigDisasmOpcodesView)
|
|
|
|
PrintTextCursorX( (LPCTSTR) line.sOpCodes, linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Label
|
2017-12-17 18:20:39 +00:00
|
|
|
linerect.left = (int) aTabs[ TS_LABEL ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (pSymbol)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_SYMBOL ) );
|
|
|
|
PrintTextCursorX( pSymbol, linerect );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Instruction / Mnemonic
|
2017-12-17 18:20:39 +00:00
|
|
|
linerect.left = (int) aTabs[ TS_INSTRUCTION ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
{
|
|
|
|
if( pData ) // Assembler Data Directive / Data Disassembler
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_DIRECTIVE ) ); // TODO: FIXME: HACK? Is the color fine?
|
|
|
|
else
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ) );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
pMnemonic = line.sMnemonic;
|
|
|
|
PrintTextCursorX( pMnemonic, linerect );
|
|
|
|
PrintTextCursorX( " ", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Target
|
2017-12-17 18:20:39 +00:00
|
|
|
if (line.bTargetImmediate)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
|
|
|
PrintTextCursorX( "#$", linerect );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (line.bTargetIndexed || line.bTargetIndirect)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
|
|
|
PrintTextCursorX( "(", linerect );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
char *pTarget = line.sTarget;
|
|
|
|
int nLen = strlen( pTarget );
|
2014-09-08 16:19:12 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (*pTarget == '$') // BUG? if ASC #:# starts with '$' ? // && (iOpcode != OPCODE_NOP)
|
|
|
|
{
|
|
|
|
pTarget++;
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
|
|
|
PrintTextCursorX( "$", linerect );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! bCursorLine)
|
|
|
|
{
|
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_SYMBOL ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
else
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
if (iOpmode == AM_M)
|
|
|
|
// if (bDisasmFormatFlags & DISASM_FORMAT_CHAR)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPCODE ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_TARGET ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
2014-09-08 16:19:12 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// https://github.com/AppleWin/AppleWin/issues/227
|
|
|
|
// (Debugger)[1.25] AppleSoft symbol: COPY.FAC.TO.ARG.ROUNDED overflows into registers
|
|
|
|
// Repro:
|
|
|
|
// UEA39
|
|
|
|
// 2.8.0.1 Clamp excessive symbol target to not overflow
|
|
|
|
// SYM COPY.FAC.TO.ARG.ROUNDED = EB63
|
|
|
|
// If opcodes aren't showing then length can be longer!
|
|
|
|
// FormatOpcodeBytes() uses 3 chars/MAX_OPCODES. i.e. "## "
|
|
|
|
int nMaxLen = MAX_TARGET_LEN;
|
2017-08-24 16:21:15 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// 2.8.0.8: Bug #227: AppleSoft symbol: COPY.FAC.TO.ARG.ROUNDED overflows into registers
|
|
|
|
if ( !g_bConfigDisasmAddressView )
|
|
|
|
nMaxLen += 4;
|
|
|
|
if ( !g_bConfigDisasmOpcodesView )
|
|
|
|
nMaxLen += (MAX_OPCODES*3);
|
2017-08-24 16:21:15 +00:00
|
|
|
|
2017-12-19 22:23:58 +00:00
|
|
|
// 2.9.0.9 Continuation of 2.8.0.8: Fix overflowing disassembly pane for long symbols
|
|
|
|
int nOverflow = 0;
|
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
|
|
|
|
{
|
|
|
|
if (line.nTargetOffset != 0)
|
2017-08-24 16:21:15 +00:00
|
|
|
nOverflow++;
|
|
|
|
|
2017-12-19 22:23:58 +00:00
|
|
|
nOverflow += strlen( line.sTargetOffset );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (line.bTargetIndirect || line.bTargetX || line.bTargetY)
|
|
|
|
{
|
|
|
|
if (line.bTargetX)
|
2017-08-24 16:21:15 +00:00
|
|
|
nOverflow += 2;
|
2017-12-19 22:23:58 +00:00
|
|
|
else
|
|
|
|
if ((line.bTargetY) && (! line.bTargetIndirect))
|
|
|
|
nOverflow += 2;
|
|
|
|
}
|
2017-08-24 16:21:15 +00:00
|
|
|
|
2017-12-19 22:23:58 +00:00
|
|
|
if (line.bTargetIndexed || line.bTargetIndirect)
|
|
|
|
nOverflow++;
|
2017-08-24 16:21:15 +00:00
|
|
|
|
2017-12-19 22:23:58 +00:00
|
|
|
if (line.bTargetIndexed)
|
|
|
|
{
|
|
|
|
if (line.bTargetY)
|
|
|
|
nOverflow += 2;
|
|
|
|
}
|
2017-08-24 16:21:15 +00:00
|
|
|
|
2017-12-19 22:23:58 +00:00
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_TARGET_POINTER)
|
|
|
|
{
|
|
|
|
nOverflow += strlen( line.sTargetPointer ); // '####'
|
|
|
|
nOverflow ++ ; // ':'
|
|
|
|
nOverflow += 2; // '##'
|
|
|
|
nOverflow ++ ; // ' '
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_CHAR)
|
|
|
|
{
|
|
|
|
nOverflow += strlen( line.sImmediate );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nLen >= (nMaxLen - nOverflow))
|
2017-12-17 18:20:39 +00:00
|
|
|
{
|
2014-09-08 16:19:12 +00:00
|
|
|
#if _DEBUG
|
2017-12-17 18:20:39 +00:00
|
|
|
// TODO: Warn on import about long symbol/target names
|
2014-09-08 16:19:12 +00:00
|
|
|
#endif
|
2017-12-19 22:23:58 +00:00
|
|
|
pTarget[ nMaxLen - nOverflow ] = 0;
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
2014-09-08 16:19:12 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// TODO: FIXME: 2.8.0.7: Allow ctrl characters to show as inverse; i.e. ASC 400:40F
|
|
|
|
PrintTextCursorX( pTarget, linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// Target Offset +/-
|
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (line.nTargetOffset > 0)
|
|
|
|
PrintTextCursorX( "+", linerect );
|
|
|
|
else
|
|
|
|
if (line.nTargetOffset < 0)
|
|
|
|
PrintTextCursorX( "-", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPCODE )); // Technically, not a hex number, but decimal
|
|
|
|
}
|
|
|
|
PrintTextCursorX( line.sTargetOffset, linerect );
|
|
|
|
}
|
|
|
|
// Inside parenthesis = Indirect Target Regs
|
|
|
|
if (line.bTargetIndirect || line.bTargetX || line.bTargetY)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (line.bTargetX)
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
PrintTextCursorX( ",", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
if (! bCursorLine)
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG ) );
|
|
|
|
PrintTextCursorX( "X", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
else
|
|
|
|
if ((line.bTargetY) && (! line.bTargetIndirect))
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
PrintTextCursorX( ",", linerect );
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG ) );
|
|
|
|
PrintTextCursorX( "Y", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (line.bTargetIndexed || line.bTargetIndirect)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
|
|
|
|
|
|
|
PrintTextCursorX( ")", linerect );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (line.bTargetIndexed)
|
|
|
|
{
|
|
|
|
if (line.bTargetY)
|
2010-12-19 20:29:58 +00:00
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
PrintTextCursorX( ",", linerect );
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG ) );
|
|
|
|
PrintTextCursorX( "Y", linerect );
|
2010-12-19 20:29:58 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
2010-12-19 20:29:58 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// BUGFIX: 2.6.2.30: DA $target --> show right paren
|
|
|
|
if( pData )
|
|
|
|
{
|
|
|
|
return nOpbyte;
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
// Memory Pointer and Value
|
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_TARGET_POINTER) // (bTargetValue)
|
|
|
|
{
|
|
|
|
linerect.left = (int) aTabs[ TS_IMMEDIATE ]; // TS_IMMEDIATE ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
PrintTextCursorX( line.sTargetPointer, linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_TARGET_VALUE)
|
|
|
|
{
|
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (g_iConfigDisasmTargets & DISASM_TARGET_BOTH)
|
|
|
|
PrintTextCursorX( ":", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPCODE ));
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
PrintTextCursorX( line.sTargetValue, linerect );
|
|
|
|
PrintTextCursorX( " ", linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Immediate Char
|
2017-12-17 18:20:39 +00:00
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_CHAR)
|
|
|
|
{
|
|
|
|
linerect.left = (int) aTabs[ TS_CHAR ]; // TS_IMMEDIATE ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
{
|
|
|
|
ColorizeSpecialChar( NULL, line.nImmediate, MEM_VIEW_ASCII, iBackground );
|
|
|
|
}
|
|
|
|
PrintTextCursorX( line.sImmediate, linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) ); // Hack: Colorize can "color bleed to EOL"
|
|
|
|
if (! bCursorLine)
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
// Branch Indicator
|
2017-12-17 18:20:39 +00:00
|
|
|
if (bDisasmFormatFlags & DISASM_FORMAT_BRANCH)
|
|
|
|
{
|
|
|
|
linerect.left = (int) aTabs[ TS_BRANCH ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (! bCursorLine)
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_BRANCH ) );
|
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
#if !USE_APPLE_FONT
|
2017-12-17 18:20:39 +00:00
|
|
|
if (g_iConfigDisasmBranchType == DISASM_BRANCH_FANCY)
|
|
|
|
SelectObject( GetDebuggerMemDC(), g_aFontConfig[ FONT_DISASM_BRANCH ]._hFont ); // g_hFontWebDings
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
PrintText( line.sBranch, linerect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
#if !USE_APPLE_FONT
|
2017-12-17 18:20:39 +00:00
|
|
|
if (g_iConfigDisasmBranchType)
|
|
|
|
SelectObject( GetDebuggerMemDC(), g_aFontConfig[ FONT_DISASM_DEFAULT ]._hFont ); // g_hFontDisasm
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return nOpbyte;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Optionally copy the flags to pText_
|
|
|
|
//===========================================================================
|
|
|
|
void DrawFlags ( int line, WORD nRegFlags, LPTSTR pFlagNames_)
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
char sFlagNames[ _6502_NUM_FLAGS+1 ] = ""; // = "NVRBDIZC"; // copy from g_aFlagNames
|
|
|
|
char sText[4] = "?";
|
2017-12-17 18:20:39 +00:00
|
|
|
RECT rect;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
// Regs are 10 chars across
|
|
|
|
// Flags are 8 chars across -- scale "up"
|
|
|
|
int nSpacerWidth = nFontWidth;
|
|
|
|
|
|
|
|
#if OLD_FLAGS_SPACING
|
|
|
|
const int nScaledWidth = 10;
|
|
|
|
if (nFontWidth)
|
|
|
|
nSpacerWidth = (nScaledWidth * nFontWidth) / 8;
|
|
|
|
nSpacerWidth++;
|
|
|
|
#endif
|
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
//
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
GetDebuggerMemDC();
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
rect.top = line * g_nFontHeight;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
|
|
|
rect.left = DISPLAY_FLAG_COLUMN;
|
|
|
|
rect.right = rect.left + (10 * nFontWidth);
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DATA_1 )); // BG_INFO
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG ));
|
|
|
|
PrintText( "P ", rect );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
sprintf( sText, "%02X", nRegFlags );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
|
|
|
PrintText( sText, rect );
|
|
|
|
|
|
|
|
rect.top -= g_nFontHeight;
|
|
|
|
rect.bottom -= g_nFontHeight;
|
|
|
|
sText[1] = 0;
|
|
|
|
|
|
|
|
rect.left += ((2 + _6502_NUM_FLAGS) * nSpacerWidth);
|
|
|
|
rect.right = rect.left + nFontWidth;
|
|
|
|
|
|
|
|
//
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int iFlag = 0;
|
|
|
|
int nFlag = _6502_NUM_FLAGS;
|
|
|
|
while (nFlag--)
|
|
|
|
{
|
|
|
|
iFlag = (_6502_NUM_FLAGS - nFlag - 1);
|
|
|
|
|
|
|
|
bool bSet = (nRegFlags & 1);
|
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
sText[0] = g_aBreakpointSource[ BP_SRC_FLAG_C + iFlag ][0];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
if (bSet)
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO_INVERSE ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_INVERSE ));
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
2017-12-17 18:20:39 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
2017-12-17 18:20:39 +00:00
|
|
|
rect.left -= nSpacerWidth;
|
|
|
|
rect.right -= nSpacerWidth;
|
|
|
|
PrintText( sText, rect );
|
|
|
|
|
|
|
|
// Print Binary value
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
|
|
|
|
sText[0] = '0' + static_cast<int>(bSet);
|
|
|
|
PrintText( sText, rect );
|
|
|
|
rect.top -= g_nFontHeight;
|
|
|
|
rect.bottom -= g_nFontHeight;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
if (pFlagNames_)
|
|
|
|
{
|
2017-12-17 18:20:39 +00:00
|
|
|
if (!bSet)
|
2010-06-11 15:38:22 +00:00
|
|
|
sFlagNames[nFlag] = '.';
|
|
|
|
else
|
|
|
|
sFlagNames[nFlag] = g_aBreakpointSource[ BP_SRC_FLAG_C + iFlag ][0];
|
|
|
|
}
|
|
|
|
|
|
|
|
nRegFlags >>= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pFlagNames_)
|
|
|
|
strcpy(pFlagNames_,sFlagNames);
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawMemory ( int line, int iMemDump )
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
MemoryDump_t* pMD = &g_aMemDump[ iMemDump ];
|
2011-02-20 23:29:00 +00:00
|
|
|
bool bActive = pMD->bActive;
|
|
|
|
#if DEBUG_FORCE_DISPLAY
|
|
|
|
bActive = true;
|
|
|
|
#endif
|
|
|
|
if( !bActive )
|
|
|
|
return;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
USHORT nAddr = pMD->nAddress;
|
|
|
|
DEVICE_e eDevice = pMD->eDevice;
|
|
|
|
MemoryView_e iView = pMD->eView;
|
|
|
|
|
2016-03-21 23:48:02 +00:00
|
|
|
SS_CARD_MOCKINGBOARD_v1 SS_MB;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
if ((eDevice == DEV_SY6522) || (eDevice == DEV_AY8910))
|
2016-03-21 23:48:02 +00:00
|
|
|
MB_GetSnapshot_v1(&SS_MB, 4+(nAddr>>1)); // Slot4 or Slot5
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
rect.left = DISPLAY_MINIMEM_COLUMN;
|
|
|
|
rect.top = (line * g_nFontHeight);
|
|
|
|
rect.right = DISPLAY_WIDTH;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
|
|
|
|
|
|
|
RECT rect2;
|
|
|
|
rect2 = rect;
|
|
|
|
|
|
|
|
const int MAX_MEM_VIEW_TXT = 16;
|
|
|
|
char sText[ MAX_MEM_VIEW_TXT * 2 ];
|
|
|
|
char sData[ MAX_MEM_VIEW_TXT * 2 ];
|
|
|
|
|
|
|
|
char sType [ 4 ] = "Mem";
|
|
|
|
char sAddress[ 8 ] = "";
|
|
|
|
|
|
|
|
int iForeground = FG_INFO_OPCODE;
|
|
|
|
int iBackground = BG_INFO;
|
|
|
|
|
|
|
|
#if DISPLAY_MEMORY_TITLE
|
|
|
|
if (eDevice == DEV_SY6522)
|
|
|
|
{
|
|
|
|
// sprintf(sData,"Mem at SY#%d", nAddr);
|
|
|
|
sprintf( sAddress,"SY#%d", nAddr );
|
|
|
|
}
|
|
|
|
else if(eDevice == DEV_AY8910)
|
|
|
|
{
|
|
|
|
// sprintf(sData,"Mem at AY#%d", nAddr);
|
|
|
|
sprintf( sAddress,"AY#%d", nAddr );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
sprintf( sAddress,"%04X",(unsigned)nAddr);
|
|
|
|
|
|
|
|
if (iView == MEM_VIEW_HEX)
|
|
|
|
sprintf( sType, "HEX" );
|
|
|
|
else
|
|
|
|
if (iView == MEM_VIEW_ASCII)
|
|
|
|
sprintf( sType, "ASCII" );
|
|
|
|
else
|
|
|
|
sprintf( sType, "TEXT" );
|
|
|
|
}
|
|
|
|
|
|
|
|
rect2 = rect;
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
PrintTextCursorX( sType, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( " at ", rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
PrintTextCursorY( sAddress, rect2 );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
rect.top = rect2.top;
|
|
|
|
rect.bottom = rect2.bottom;
|
|
|
|
|
|
|
|
sData[0] = 0;
|
|
|
|
|
|
|
|
WORD iAddress = nAddr;
|
|
|
|
|
|
|
|
int nLines = g_nDisplayMemoryLines;
|
|
|
|
int nCols = 4;
|
|
|
|
|
|
|
|
if (iView != MEM_VIEW_HEX)
|
|
|
|
{
|
|
|
|
nCols = MAX_MEM_VIEW_TXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( (eDevice == DEV_SY6522) || (eDevice == DEV_AY8910) )
|
|
|
|
{
|
|
|
|
iAddress = 0;
|
|
|
|
nCols = 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
rect.right = DISPLAY_WIDTH - 1;
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
|
|
|
|
|
|
|
for (int iLine = 0; iLine < nLines; iLine++ )
|
|
|
|
{
|
|
|
|
rect2 = rect;
|
|
|
|
|
|
|
|
if (iView == MEM_VIEW_HEX)
|
|
|
|
{
|
|
|
|
sprintf( sText, "%04X", iAddress );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( ":", rect2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int iCol = 0; iCol < nCols; iCol++)
|
|
|
|
{
|
|
|
|
bool bHiBit = false;
|
|
|
|
bool bLoBit = false;
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ));
|
|
|
|
|
|
|
|
// .12 Bugfix: DrawMemory() should draw memory byte for IO address: ML1 C000
|
|
|
|
// if ((iAddress >= _6502_IO_BEGIN) && (iAddress <= _6502_IO_END))
|
|
|
|
// {
|
|
|
|
// sprintf( sText, "IO " );
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
if (eDevice == DEV_SY6522)
|
|
|
|
{
|
|
|
|
sprintf( sText, "%02X", (unsigned) ((BYTE*)&SS_MB.Unit[nAddr & 1].RegsSY6522)[iAddress] );
|
|
|
|
if (iCol & 1)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ));
|
|
|
|
else
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (eDevice == DEV_AY8910)
|
|
|
|
{
|
|
|
|
sprintf( sText, "%02X", (unsigned)SS_MB.Unit[nAddr & 1].RegsAY8910[iAddress] );
|
|
|
|
if (iCol & 1)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( iForeground ));
|
|
|
|
else
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
}
|
|
|
|
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))
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_IO_BYTE ));
|
|
|
|
}
|
2011-02-20 23:29:00 +00:00
|
|
|
|
|
|
|
|
|
|
|
if (nCols == 6)
|
|
|
|
{
|
|
|
|
if ((iCol & 1) == 1)
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( WATCH_ZERO_BG )); // BG_DATA_2
|
|
|
|
else
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DATA_2 ));
|
|
|
|
sprintf(sText, "%02X", nData );
|
|
|
|
} else
|
|
|
|
sprintf(sText, "%02X ", nData );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
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( sText, nData, iView, iBackground );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
int nChars = PrintTextCursorX( sText, rect2 ); // PrintTextCursorX()
|
|
|
|
iAddress++;
|
|
|
|
}
|
|
|
|
// Windows HACK: Bugfix: Rest of line is still background color
|
|
|
|
// DebuggerSetColorBG( hDC, DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA
|
|
|
|
// DebuggerSetColorFG(hDC, DebuggerGetColor( FG_INFO_TITLE )); //COLOR_STATIC
|
|
|
|
// PrintTextCursorX( " ", rect2 );
|
|
|
|
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
sData[0] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawRegister ( int line, LPCTSTR name, const int nBytes, const WORD nValue, int iSource )
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
rect.top = line * g_nFontHeight;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
|
|
|
rect.left = DISPLAY_REGS_COLUMN;
|
|
|
|
rect.right = rect.left + (10 * nFontWidth); // + 1;
|
|
|
|
|
|
|
|
if ((PARAM_REG_A == iSource) ||
|
|
|
|
(PARAM_REG_X == iSource) ||
|
|
|
|
(PARAM_REG_Y == iSource) ||
|
|
|
|
(PARAM_REG_PC == iSource) ||
|
|
|
|
(PARAM_REG_SP == iSource))
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
rect.left += nFontWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2.6.0.0 Alpha - Regs not "boxed"
|
|
|
|
int iBackground = BG_DATA_1; // BG_INFO
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ));
|
|
|
|
PrintText( name, rect );
|
|
|
|
|
|
|
|
unsigned int nData = nValue;
|
|
|
|
int nOffset = 6;
|
|
|
|
|
|
|
|
char sValue[8];
|
|
|
|
|
|
|
|
if (PARAM_REG_SP == iSource)
|
|
|
|
{
|
|
|
|
WORD nStackDepth = _6502_STACK_END - nValue;
|
|
|
|
sprintf( 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)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR )); // FG_INFO_OPCODE, FG_INFO_TITLE
|
|
|
|
PrintText( sValue, rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nBytes == 2)
|
|
|
|
{
|
|
|
|
sprintf(sValue,"%04X", nData);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rect.left = DISPLAY_REGS_COLUMN + (3 * nFontWidth);
|
|
|
|
// rect.right = SCREENSPLIT2;
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( "'", rect ); // PrintTextCursorX
|
|
|
|
|
|
|
|
ColorizeSpecialChar( sValue, nData, MEM_VIEW_ASCII ); // MEM_VIEW_APPLE for inverse background little hard on the eyes
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ));
|
|
|
|
PrintTextCursorX( sValue, rect ); // PrintTextCursorX()
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( "'", rect ); // PrintTextCursorX()
|
|
|
|
|
|
|
|
sprintf(sValue," %02X", nData );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Needs to be far enough over, since 4 chars of ZeroPage symbol also calls us
|
|
|
|
rect.left = DISPLAY_REGS_COLUMN + (nOffset * nFontWidth);
|
|
|
|
|
|
|
|
if ((PARAM_REG_PC == iSource) || (PARAM_REG_SP == iSource)) // Stack Pointer is target address, but doesn't look as good.
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE )); // FG_DISASM_OPCODE
|
|
|
|
}
|
|
|
|
PrintText( sValue, rect );
|
|
|
|
}
|
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
//===========================================================================
|
|
|
|
void DrawRegisters ( int line )
|
|
|
|
{
|
|
|
|
const char **sReg = g_aBreakpointSource;
|
|
|
|
|
|
|
|
DrawRegister( line++, sReg[ BP_SRC_REG_A ] , 1, regs.a , PARAM_REG_A );
|
|
|
|
DrawRegister( line++, sReg[ BP_SRC_REG_X ] , 1, regs.x , PARAM_REG_X );
|
|
|
|
DrawRegister( line++, sReg[ BP_SRC_REG_Y ] , 1, regs.y , PARAM_REG_Y );
|
|
|
|
DrawRegister( line++, sReg[ BP_SRC_REG_PC] , 2, regs.pc, PARAM_REG_PC );
|
|
|
|
DrawFlags ( line , regs.ps, NULL);
|
|
|
|
line += 2;
|
|
|
|
DrawRegister( line++, sReg[ BP_SRC_REG_S ] , 2, regs.sp, PARAM_REG_SP );
|
|
|
|
}
|
|
|
|
|
2017-04-27 16:30:08 +00:00
|
|
|
|
|
|
|
// 2.9.0.3
|
|
|
|
//===========================================================================
|
|
|
|
void _DrawSoftSwitchHighlight( RECT & temp, bool bSet, const char *sOn, const char *sOff, int bg = BG_INFO )
|
|
|
|
{
|
|
|
|
// DebuggerSetColorBG( DebuggerGetColor( bg ) ); // BG_INFO
|
|
|
|
|
|
|
|
ColorizeFlags( bSet, bg );
|
|
|
|
PrintTextCursorX( sOn, temp );
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg ) ); // BG_INFO
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
|
|
|
PrintTextCursorX( "/", temp );
|
|
|
|
|
|
|
|
ColorizeFlags( !bSet, bg );
|
|
|
|
PrintTextCursorX( sOff, temp );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-10 16:51:45 +00:00
|
|
|
// 2.9.0.8
|
2011-01-30 21:41:03 +00:00
|
|
|
//===========================================================================
|
2017-05-10 16:51:45 +00:00
|
|
|
void _DrawSoftSwitchAddress( RECT & rect, int nAddress, int bg_default = BG_INFO )
|
2011-01-30 21:41:03 +00:00
|
|
|
{
|
|
|
|
char sText[ 4 ] = "";
|
|
|
|
|
2017-04-27 23:41:03 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg_default ));
|
2011-01-30 21:41:03 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_TARGET ));
|
|
|
|
sprintf( sText, "%02X", (nAddress & 0xFF) );
|
2017-05-10 16:51:45 +00:00
|
|
|
PrintTextCursorX( sText, rect );
|
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
2017-05-10 16:51:45 +00:00
|
|
|
PrintTextCursorX( ":", rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
// 2.7.0.7 Cleaned up display of soft-switches to show address.
|
|
|
|
//===========================================================================
|
|
|
|
void _DrawSoftSwitch( RECT & rect, int nAddress, bool bSet, char *sPrefix, char *sOn, char *sOff, const char *sSuffix = NULL, int bg_default = BG_INFO )
|
|
|
|
{
|
|
|
|
RECT temp = rect;
|
|
|
|
char sText[ 4 ] = "";
|
|
|
|
|
|
|
|
_DrawSoftSwitchAddress( temp, nAddress, bg_default );
|
2011-01-30 21:41:03 +00:00
|
|
|
|
|
|
|
if( sPrefix )
|
2017-04-27 23:37:13 +00:00
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG )); // light blue
|
2011-01-30 21:41:03 +00:00
|
|
|
PrintTextCursorX( sPrefix, temp );
|
2017-04-27 23:37:13 +00:00
|
|
|
}
|
2011-01-30 21:41:03 +00:00
|
|
|
|
2017-04-27 16:30:08 +00:00
|
|
|
// 2.9.0.3
|
|
|
|
_DrawSoftSwitchHighlight( temp, bSet, sOn, sOff, bg_default );
|
2011-01-30 21:41:03 +00:00
|
|
|
|
2017-04-27 16:30:08 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg_default ));
|
2011-01-30 21:41:03 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
if ( sSuffix )
|
|
|
|
PrintTextCursorX( sSuffix, temp );
|
|
|
|
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
}
|
|
|
|
|
2017-05-10 16:51:45 +00:00
|
|
|
// 2.9.0.8
|
|
|
|
//===========================================================================
|
|
|
|
void _DrawTriStateSoftSwitch( RECT & rect, int nAddress, int iDisplay, int iActive, char *sPrefix, char *sOn, char *sOff, const char *sSuffix = NULL, int bg_default = BG_INFO )
|
|
|
|
{
|
|
|
|
// if ((iActive == 0) || (iDisplay == iActive))
|
|
|
|
bool bSet = (iDisplay == iActive);
|
|
|
|
|
|
|
|
if ( bSet )
|
|
|
|
_DrawSoftSwitch( rect, nAddress, bSet, NULL, sOn, sOff, " ", bg_default );
|
|
|
|
else // Main Memory is active, or Bank # is not active
|
|
|
|
{
|
|
|
|
RECT temp = rect;
|
2018-03-20 01:49:08 +00:00
|
|
|
int iBank = (GetMemMode() & MF_BANK2)
|
2017-05-10 16:51:45 +00:00
|
|
|
? 2
|
|
|
|
: 1
|
|
|
|
;
|
|
|
|
bool bDisabled = ((iActive == 0) && (iBank == iDisplay));
|
|
|
|
|
|
|
|
|
|
|
|
_DrawSoftSwitchAddress( temp, nAddress, bg_default );
|
|
|
|
|
|
|
|
// TODO: Q. Show which bank we are writing to in red?
|
|
|
|
// A. No, since we highlight bank 2 or 1, along with R/W
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg_default ));
|
|
|
|
if( bDisabled )
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ) );
|
|
|
|
else
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
|
|
|
|
|
|
|
PrintTextCursorX( sOn , temp );
|
|
|
|
PrintTextCursorX( "/" , temp );
|
|
|
|
|
|
|
|
ColorizeFlags( bDisabled, bg_default, FG_DISASM_OPERATOR );
|
|
|
|
PrintTextCursorX( sOff, temp );
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg_default ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
PrintTextCursorX( " " , temp );
|
|
|
|
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-27 19:00:54 +00:00
|
|
|
/*
|
|
|
|
Debugger: Support LC status and memory
|
|
|
|
https://github.com/AppleWin/AppleWin/issues/406
|
|
|
|
|
|
|
|
Bank2 Bank1 First Access, Second Access
|
|
|
|
-----------------------------------------------
|
|
|
|
C080 C088 Read RAM, Write protect MF_HIGHRAM ~MF_WRITERAM
|
|
|
|
C081 C089 Read ROM, Write enable ~MF_HIGHRAM MF_WRITERAM
|
|
|
|
C082 C08A Read ROM, Write protect ~MF_HIGHRAM ~MF_WRITERAM
|
|
|
|
C083 C08B Read RAM, Write enable MF_HIGHRAM MF_WRITERAM
|
|
|
|
c084 C08C same as C080/C088
|
|
|
|
c085 C08D same as C081/C089
|
|
|
|
c086 C08E same as C082/C08A
|
|
|
|
c087 C08F same as C083/C08B
|
2017-05-10 16:49:48 +00:00
|
|
|
MF_BANK2 ~MF_BANK2
|
2017-04-27 19:00:54 +00:00
|
|
|
|
|
|
|
NOTE: Saturn 128K uses C084 .. C087 and C08C .. C08F to select Banks 0 .. 7 !
|
|
|
|
*/
|
|
|
|
// 2.9.0.4 Draw Language Card Bank Usage
|
2017-05-10 16:51:45 +00:00
|
|
|
// @param iBankDisplay Either 1 or 2
|
2017-04-27 19:00:54 +00:00
|
|
|
//===========================================================================
|
2017-05-10 16:51:45 +00:00
|
|
|
void _DrawSoftSwitchLanguageCardBank( RECT & rect, int iBankDisplay, int bg_default = BG_INFO )
|
2017-04-27 19:00:54 +00:00
|
|
|
{
|
|
|
|
int w = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nFontWidthAvg;
|
|
|
|
int dx = 8 * w; // "80:L#/M R/W"
|
|
|
|
// ^-------^
|
|
|
|
|
|
|
|
rect.right = rect.left + dx;
|
|
|
|
|
|
|
|
// 0 = RAM
|
|
|
|
// 1 = Bank 1
|
|
|
|
// 2 = Bank 2
|
2018-03-20 01:49:08 +00:00
|
|
|
bool bBankWritable = (GetMemMode() & MF_WRITERAM) ? 1 : 0;
|
|
|
|
int iBankActive = (GetMemMode() & MF_HIGHRAM)
|
|
|
|
? (GetMemMode() & MF_BANK2)
|
2017-04-27 19:00:54 +00:00
|
|
|
? 2
|
|
|
|
: 1
|
|
|
|
: 0
|
|
|
|
;
|
2017-05-10 16:51:45 +00:00
|
|
|
bool bBankOn = (iBankActive == iBankDisplay);
|
2017-04-27 19:00:54 +00:00
|
|
|
|
2017-05-10 16:51:45 +00:00
|
|
|
char sOff[ 4 ] = "M";
|
|
|
|
char sOn [ 4 ] = "B#"; // LC# but one char too wide :-/
|
2017-04-27 19:00:54 +00:00
|
|
|
// C080 LC2
|
|
|
|
// C088 LC1
|
2017-05-10 16:51:45 +00:00
|
|
|
int nAddress = 0xC080 + (8 * (2 - iBankDisplay));
|
|
|
|
sOn[1] = '0' + iBankDisplay;
|
2017-04-27 19:00:54 +00:00
|
|
|
|
2017-05-10 16:51:45 +00:00
|
|
|
// if off then ONLY highlight 'M' but only for the appropiate bank
|
|
|
|
// if on then do NOT highlight 'M'
|
|
|
|
// if on then also only highly the ACTIVE bank
|
|
|
|
_DrawTriStateSoftSwitch( rect, nAddress, iBankDisplay, iBankActive, NULL, sOn, sOff, " ", bg_default );
|
2017-04-27 19:00:54 +00:00
|
|
|
|
|
|
|
rect.top -= g_nFontHeight;
|
|
|
|
rect.bottom -= g_nFontHeight;
|
2017-04-27 20:37:56 +00:00
|
|
|
|
2017-04-27 19:00:54 +00:00
|
|
|
rect.left += dx;
|
2017-04-27 20:37:56 +00:00
|
|
|
rect.right += 3*w;
|
2017-04-27 19:00:54 +00:00
|
|
|
|
2017-04-27 21:04:53 +00:00
|
|
|
#if defined(RAMWORKS) || defined(SATURN)
|
2017-05-10 16:51:45 +00:00
|
|
|
if (iBankDisplay == 1)
|
2017-04-27 21:04:53 +00:00
|
|
|
{
|
2017-05-01 15:47:31 +00:00
|
|
|
int iActiveBank = -1;
|
2017-04-27 21:04:53 +00:00
|
|
|
char sText[ 4 ] = "?"; // Default to RAMWORKS
|
2017-05-01 15:47:31 +00:00
|
|
|
#ifdef RAMWORKS
|
|
|
|
if (g_eMemType == MEM_TYPE_RAMWORKS) { sText[0] = 'r'; iActiveBank = g_uActiveBank; } // RAMWORKS
|
|
|
|
#endif
|
|
|
|
#ifdef SATURN
|
|
|
|
if (g_eMemType == MEM_TYPE_SATURN ) { sText[0] = 's'; iActiveBank = g_uSaturnActiveBank; } // SATURN 64K 128K
|
|
|
|
#endif // SATURN
|
2017-04-27 21:04:53 +00:00
|
|
|
|
2017-05-01 15:47:31 +00:00
|
|
|
if (iActiveBank >= 0)
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_REG )); // light blue
|
|
|
|
PrintTextCursorX( sText, rect );
|
2017-04-27 21:04:53 +00:00
|
|
|
|
2017-05-01 15:47:31 +00:00
|
|
|
sprintf( sText, "%02X", (iActiveBank & 0x7F) );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
PrintTextCursorX( sText, rect );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
PrintTextCursorX( " ", rect );
|
2017-04-27 21:04:53 +00:00
|
|
|
}
|
|
|
|
#endif // SATURN
|
2017-05-01 15:47:31 +00:00
|
|
|
|
2017-05-10 16:51:45 +00:00
|
|
|
if (iBankDisplay == 2)
|
2017-04-27 20:39:59 +00:00
|
|
|
{
|
|
|
|
// [2]/M R/[W]
|
|
|
|
// [2]/M [R]/W
|
|
|
|
const char *pOn = "R";
|
|
|
|
const char *pOff = "W";
|
2017-04-27 19:00:54 +00:00
|
|
|
|
2017-04-28 00:13:34 +00:00
|
|
|
_DrawSoftSwitchHighlight( rect, !bBankWritable, pOn, pOff, bg_default );
|
2017-04-27 20:39:59 +00:00
|
|
|
}
|
2017-04-27 19:00:54 +00:00
|
|
|
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
}
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2017-04-27 23:58:43 +00:00
|
|
|
/*
|
|
|
|
$C002 W RAMRDOFF Read enable main memory from $0200-$BFFF
|
|
|
|
$C003 W RAMDRON Read enable aux memory from $0200-$BFFF
|
|
|
|
$C004 W RAMWRTOFF Write enable main memory from $0200-$BFFF
|
|
|
|
$C005 W RAMWRTON Write enable aux memory from $0200-$BFFF
|
|
|
|
*/
|
|
|
|
// 2.9.0.6
|
|
|
|
// GH#406 https://github.com/AppleWin/AppleWin/issues/406
|
|
|
|
//===========================================================================
|
2017-04-28 00:13:34 +00:00
|
|
|
void _DrawSoftSwitchMainAuxBanks( RECT & rect, int bg_default = BG_INFO )
|
2017-04-27 23:58:43 +00:00
|
|
|
{
|
|
|
|
RECT temp = rect;
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Ideally, we'd show Read/Write for Main/Aux
|
|
|
|
02:RM/X
|
|
|
|
04:WM/X
|
|
|
|
But we only have 1 line:
|
|
|
|
02:Rm/x Wm/x
|
|
|
|
00:ASC/MOUS
|
|
|
|
Which is one character too much.
|
|
|
|
02:Rm/x Wm/a
|
|
|
|
But we abbreaviate it without the space and color code the Read and Write:
|
|
|
|
02:Rm/xWm/x
|
|
|
|
*/
|
|
|
|
|
|
|
|
int w = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nFontWidthAvg;
|
|
|
|
int dx = 7 * w;
|
|
|
|
|
|
|
|
int nAddress = 0xC002;
|
2018-03-20 01:49:08 +00:00
|
|
|
bool bMainRead = (GetMemMode() & MF_AUXREAD) ? true : false;
|
|
|
|
bool bAuxWrite = (GetMemMode() & MF_AUXWRITE) ? true : false;
|
2017-04-27 23:58:43 +00:00
|
|
|
|
|
|
|
temp.right = rect.left + dx;
|
|
|
|
_DrawSoftSwitch( temp, nAddress, !bMainRead, "R", "m", "x", NULL, BG_DATA_2 );
|
|
|
|
|
|
|
|
temp.top -= g_nFontHeight;
|
|
|
|
temp.bottom -= g_nFontHeight;
|
|
|
|
temp.left += dx;
|
|
|
|
temp.right += 3*w;
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_BP_S_X )); // FG_INFO_OPCODE )); Yellow
|
2017-04-28 00:13:34 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bg_default ));
|
2017-04-27 23:58:43 +00:00
|
|
|
PrintTextCursorX( "W", temp );
|
|
|
|
_DrawSoftSwitchHighlight( temp, !bAuxWrite, "m", "x", BG_DATA_2 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-04 17:33:10 +00:00
|
|
|
// 2.7.0.1 Display state of soft switches
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSoftSwitches( int iSoftSwitch )
|
|
|
|
{
|
|
|
|
RECT rect;
|
2011-01-30 21:41:03 +00:00
|
|
|
RECT temp;
|
2011-01-04 17:33:10 +00:00
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
rect.left = DISPLAY_SOFTSWITCH_COLUMN;
|
2011-01-04 17:33:10 +00:00
|
|
|
rect.top = iSoftSwitch * g_nFontHeight;
|
|
|
|
rect.right = rect.left + (10 * nFontWidth) + 1;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
2011-01-30 21:41:03 +00:00
|
|
|
temp = rect;
|
2011-01-04 17:33:10 +00:00
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
char sText[16] = "";
|
2011-01-04 17:33:10 +00:00
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
#if SOFTSWITCH_OLD
|
2011-01-04 17:33:10 +00:00
|
|
|
// $C050 / $C051 = TEXTOFF/TEXTON = SW.TXTCLR/SW.TXTSET
|
|
|
|
// GR / TEXT
|
|
|
|
// GRAPH/TEXT
|
|
|
|
// TEXT ON/OFF
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf( sText, !VideoGetSWTEXT() ? "GR / ----" : "-- / TEXT" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
|
|
|
|
// $C052 / $C053 = MIXEDOFF/MIXEDON = SW.MIXCLR/SW.MIXSET
|
|
|
|
// FULL/MIXED
|
|
|
|
// MIX OFF/ON
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf( sText, !VideoGetSWMIXED() ? "FULL/-----" : "----/MIXED" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
|
|
|
|
// $C054 / $C055 = PAGE1/PAGE2 = PAGE2OFF/PAGE2ON = SW.LOWSCR/SW.HISCR
|
|
|
|
// PAGE 1 / 2
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf( sText, !VideoGetSWPAGE2() ? "PAGE 1 / -" : "PAGE - / 2" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
|
|
|
|
// $C056 / $C057 LORES/HIRES = HIRESOFF/HIRESON = SW.LORES/SW.HIRES
|
|
|
|
// LO / HIRES
|
|
|
|
// LO / -----
|
|
|
|
// -- / HIRES
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf( sText, !VideoGetSWHIRES() ? "LO /-- RES" : "---/HI RES" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
|
|
|
|
PrintTextCursorY( "", rect );
|
|
|
|
|
|
|
|
// Extended soft switches
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf( sText, !VideoGetSW80COL() ? "40 / -- COL" : "-- / 80 COL" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf(sText, VideoGetSWAltCharSet() ? "ASCII/-----" : "-----/MOUSE" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
|
|
|
|
// 280/560 HGR
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
sprintf(sText, !VideoGetSWDHIRES() ? "HGR / ----" : "--- / DHGR" );
|
2011-01-04 17:33:10 +00:00
|
|
|
PrintTextCursorY( sText, rect );
|
2011-01-30 21:41:03 +00:00
|
|
|
#else //SOFTSWITCH_OLD
|
|
|
|
// See: VideoSetMode()
|
|
|
|
|
|
|
|
// $C050 / $C051 = TEXTOFF/TEXTON = SW.TXTCLR/SW.TXTSET
|
|
|
|
// GR / TEXT
|
|
|
|
// GRAPH/TEXT
|
|
|
|
// TEXT ON/OFF
|
|
|
|
bool bSet;
|
|
|
|
|
|
|
|
// $C050 / $C051 = TEXTOFF/TEXTON = SW.TXTCLR/SW.TXTSET
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = !VideoGetSWTEXT();
|
2011-01-30 21:41:03 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC050, bSet, NULL, "GR.", "TEXT" );
|
|
|
|
|
|
|
|
// $C052 / $C053 = MIXEDOFF/MIXEDON = SW.MIXCLR/SW.MIXSET
|
|
|
|
// FULL/MIXED
|
|
|
|
// MIX OFF/ON
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = !VideoGetSWMIXED();
|
2011-01-30 21:41:03 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC052, bSet, NULL, "FULL", "MIX" );
|
|
|
|
|
|
|
|
// $C054 / $C055 = PAGE1/PAGE2 = PAGE2OFF/PAGE2ON = SW.LOWSCR/SW.HISCR
|
|
|
|
// PAGE 1 / 2
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = !VideoGetSWPAGE2();
|
2011-01-30 21:41:03 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC054, bSet, "PAGE ", "1", "2" );
|
|
|
|
|
|
|
|
// $C056 / $C057 LORES/HIRES = HIRESOFF/HIRESON = SW.LORES/SW.HIRES
|
|
|
|
// LO / HIRES
|
|
|
|
// LO / -----
|
|
|
|
// -- / HIRES
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = !VideoGetSWHIRES();
|
2011-01-30 21:41:03 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC056, bSet, NULL, "LO", "HI", "RES" );
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
|
|
|
|
// 280/560 HGR
|
|
|
|
// C05E = ON, C05F = OFF
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = VideoGetSWDHIRES();
|
2011-01-30 21:41:03 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC05E, bSet, NULL, "DHGR", "HGR" );
|
|
|
|
|
2017-04-27 23:58:43 +00:00
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
// Extended soft switches
|
2017-04-28 00:13:34 +00:00
|
|
|
int bgMemory = BG_DATA_2;
|
|
|
|
|
|
|
|
// C000 = 80STOREOFF, C001 = 80STOREON
|
|
|
|
bSet = !VideoGetSW80STORE();
|
|
|
|
_DrawSoftSwitch( rect, 0xC000, bSet, "80Sto", "0", "1", NULL, bgMemory );
|
|
|
|
|
|
|
|
// C002 .. C005
|
|
|
|
_DrawSoftSwitchMainAuxBanks( rect, bgMemory );
|
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
// C00C = off, C00D = on
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = !VideoGetSW80COL();
|
2017-04-28 00:13:34 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC00C, bSet, "Col", "40", "80", NULL, bgMemory );
|
2011-01-30 21:41:03 +00:00
|
|
|
|
|
|
|
// C00E = off, C00F = on
|
Simplified and moved main-loop video update logic into Video.cpp.
Removed complex case below for:
. VideoHasRefreshed(), 'anyupdates'
. VideoCheckPage()
Detailed notes below.
---
Video updates in ContinueExecution() loop:
'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles:
anyupdates |= VideoHasRefreshed();
ie. VideoRefreshScreen() was called outside of this loop.
If there's been a call to VideoRefreshScreen() outside of this loop,
and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE,
then don't call VideoRefreshScreen() from this loop for 3 frames.
(If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.)
So..
if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer).
if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur).
Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes,
and so if the emulator does the very occasional screen update in this main loop, it is of no consequence.
(I guess this extra logic was to throttle video updates on very old slow machines)
---
VideoCheckPage(BOOL bForce) was called twice in main-loop:
UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2
Once each time through the loop (ie. every 1ms), with bForce=0
if UnexpectedPage && >500ms since last flip then VideoRefreshScreen()
Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1
if UnexpectedPage then VideoRefreshScreen()
Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen().
2014-09-13 21:22:27 +00:00
|
|
|
bSet = VideoGetSWAltCharSet();
|
2017-04-28 00:13:34 +00:00
|
|
|
_DrawSoftSwitch( rect, 0xC00E, bSet, NULL, "ASC", "MOUS", NULL, bgMemory ); // ASCII/MouseText
|
2017-04-27 19:00:54 +00:00
|
|
|
|
|
|
|
#if SOFTSWITCH_LANGCARD
|
2017-04-27 23:58:43 +00:00
|
|
|
// GH#406 https://github.com/AppleWin/AppleWin/issues/406
|
2017-04-27 19:00:54 +00:00
|
|
|
// 2.9.0.4
|
|
|
|
// Language Card Bank 1/2
|
|
|
|
// See: MemSetPaging()
|
|
|
|
|
|
|
|
// LC2
|
2017-04-28 00:13:34 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( bgMemory )); // BG_INFO_2 -> BG_DATA_2
|
2017-05-01 15:47:31 +00:00
|
|
|
_DrawSoftSwitchLanguageCardBank( rect, 2, bgMemory );
|
2017-04-27 19:00:54 +00:00
|
|
|
|
|
|
|
// LC1
|
|
|
|
rect.left = DISPLAY_SOFTSWITCH_COLUMN; // INFO_COL_2;
|
2017-05-01 15:47:31 +00:00
|
|
|
_DrawSoftSwitchLanguageCardBank( rect, 1, bgMemory );
|
2017-04-27 19:00:54 +00:00
|
|
|
#endif
|
|
|
|
|
2011-01-30 21:41:03 +00:00
|
|
|
#endif // SOFTSWITCH_OLD
|
2011-01-04 17:33:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
//===========================================================================
|
|
|
|
void DrawSourceLine( int iSourceLine, RECT &rect )
|
|
|
|
{
|
|
|
|
char sLine[ CONSOLE_WIDTH ];
|
|
|
|
ZeroMemory( sLine, CONSOLE_WIDTH );
|
|
|
|
|
|
|
|
if ((iSourceLine >=0) && (iSourceLine < g_AssemblerSourceBuffer.GetNumLines() ))
|
|
|
|
{
|
|
|
|
char * pSource = g_AssemblerSourceBuffer.GetLine( iSourceLine );
|
|
|
|
|
|
|
|
// int nLenSrc = strlen( 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 = strlen( sLine );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
strcpy( sLine, " " );
|
|
|
|
}
|
|
|
|
|
|
|
|
PrintText( sLine, rect );
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawStack ( int line)
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
unsigned nAddress = regs.sp;
|
2011-02-20 23:29:00 +00:00
|
|
|
#if DEBUG_FORCE_DISPLAY // Stack
|
2010-06-11 15:38:22 +00:00
|
|
|
nAddress = 0x100;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
// 2.6.0.0 Alpha - Stack was dark cyan BG_DATA_1
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DATA_1 )); // BG_INFO // recessed 3d look
|
|
|
|
|
|
|
|
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 = rect.left + (10 * nFontWidth) + 1;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE )); // [COLOR_STATIC
|
|
|
|
|
|
|
|
char sText[8] = "";
|
|
|
|
if (nAddress <= _6502_STACK_END)
|
|
|
|
{
|
|
|
|
sprintf( sText,"%04X: ", nAddress );
|
|
|
|
PrintTextCursorX( sText, rect );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nAddress <= _6502_STACK_END)
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE )); // COLOR_FG_DATA_TEXT
|
|
|
|
sprintf(sText, " %02X",(unsigned)*(LPBYTE)(mem+nAddress));
|
|
|
|
PrintTextCursorX( sText, rect );
|
|
|
|
}
|
|
|
|
iStack++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawTargets ( int line)
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return;
|
|
|
|
|
2017-08-04 19:52:17 +00:00
|
|
|
int aTarget[3];
|
|
|
|
_6502_GetTargets( regs.pc, &aTarget[0],&aTarget[1],&aTarget[2], NULL );
|
|
|
|
|
|
|
|
aTarget[1] = aTarget[2]; // Move down as we only have 2 lines
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
2011-01-04 17:33:10 +00:00
|
|
|
int iAddress = MAX_DISPLAY_TARGET_PTR_LINES;
|
2010-06-11 15:38:22 +00:00
|
|
|
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;
|
|
|
|
|
|
|
|
char sAddress[8] = "-none-";
|
|
|
|
char sData[8] = "";
|
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
#if DEBUG_FORCE_DISPLAY // Targets
|
2010-06-11 15:38:22 +00:00
|
|
|
if (aTarget[iAddress] == NO_6502_TARGET)
|
|
|
|
aTarget[iAddress] = 0;
|
|
|
|
#endif
|
|
|
|
if (aTarget[iAddress] != NO_6502_TARGET)
|
|
|
|
{
|
|
|
|
sprintf(sAddress,"%04X",aTarget[iAddress]);
|
|
|
|
if (iAddress)
|
|
|
|
sprintf(sData,"%02X",*(LPBYTE)(mem+aTarget[iAddress]));
|
|
|
|
else
|
|
|
|
sprintf(sData,"%04X",*(LPWORD)(mem+aTarget[iAddress]));
|
|
|
|
}
|
|
|
|
|
|
|
|
rect.left = DISPLAY_TARGETS_COLUMN;
|
|
|
|
rect.top = (line+iAddress) * g_nFontHeight;
|
|
|
|
int nColumn = rect.left + (7 * nFontWidth);
|
|
|
|
rect.right = nColumn;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
|
|
|
|
|
|
|
if (iAddress == 0)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE )); // Temp Address
|
|
|
|
else
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS )); // Target Address
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO ));
|
|
|
|
PrintText( sAddress, rect );
|
|
|
|
|
|
|
|
rect.left = nColumn;
|
|
|
|
rect.right = rect.left + (10 * nFontWidth); // SCREENSPLIT2
|
|
|
|
|
|
|
|
if (iAddress == 0)
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS )); // Temp Target
|
|
|
|
else
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE )); // Target Bytes
|
|
|
|
|
|
|
|
PrintText( sData, rect );
|
2011-02-20 23:29:00 +00:00
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWatches (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;
|
|
|
|
|
|
|
|
char sText[16] = "Watches";
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( WATCH_ZERO_BG )); // BG_INFO
|
|
|
|
|
|
|
|
#if DISPLAY_WATCH_TITLE
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ));
|
|
|
|
PrintTextCursorY( sText, rect );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int iWatch;
|
|
|
|
for (iWatch = 0; iWatch < MAX_WATCHES; iWatch++ )
|
|
|
|
{
|
2011-02-20 23:29:00 +00:00
|
|
|
#if DEBUG_FORCE_DISPLAY // Watch
|
2010-06-11 15:38:22 +00:00
|
|
|
if (true)
|
|
|
|
#else
|
|
|
|
if (g_aWatches[iWatch].bEnabled)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
RECT rect2 = rect;
|
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( WATCH_ZERO_BG )); // BG_INFO
|
2010-06-11 15:38:22 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ) );
|
|
|
|
PrintTextCursorX( "W", rect2 );
|
|
|
|
|
|
|
|
sprintf( sText, "%X ",iWatch );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_BULLET ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
// PrintTextCursorX( ".", rect2 );
|
|
|
|
|
|
|
|
sprintf( sText,"%04X", g_aWatches[iWatch].nAddress );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( ":", rect2 );
|
|
|
|
|
2011-02-20 07:31:08 +00:00
|
|
|
BYTE nTarget8 = 0;
|
|
|
|
BYTE nValue8 = 0;
|
|
|
|
|
|
|
|
nTarget8 = (unsigned)*(LPBYTE)(mem+g_aWatches[iWatch].nAddress);
|
|
|
|
sprintf(sText,"%02X", nTarget8 );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
nTarget8 = (unsigned)*(LPBYTE)(mem+g_aWatches[iWatch].nAddress + 1);
|
2010-06-11 15:38:22 +00:00
|
|
|
sprintf(sText,"%02X", nTarget8 );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
2011-02-20 07:31:08 +00:00
|
|
|
sprintf( sText,"(" );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
WORD nTarget16 = (unsigned)*(LPWORD)(mem+g_aWatches[iWatch].nAddress);
|
2011-02-20 07:31:08 +00:00
|
|
|
sprintf( sText,"%04X", nTarget16 );
|
2010-06-11 15:38:22 +00:00
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
2011-02-20 07:31:08 +00:00
|
|
|
// PrintTextCursorX( ":", rect2 );
|
|
|
|
PrintTextCursorX( ")", rect2 );
|
|
|
|
|
|
|
|
// BYTE nValue8 = (unsigned)*(LPBYTE)(mem + nTarget16);
|
|
|
|
// sprintf(sText,"%02X", nValue8 );
|
|
|
|
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
|
|
|
// PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
|
|
|
|
// 1.19.4 Added: Watch show (dynamic) raw hex bytes
|
|
|
|
rect2 = rect;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
2011-02-20 07:31:08 +00:00
|
|
|
for( int iByte = 0; iByte < 8; iByte++ )
|
|
|
|
{
|
2011-02-20 23:29:00 +00:00
|
|
|
if ((iByte & 3) == 0) {
|
2011-02-20 07:31:08 +00:00
|
|
|
DebuggerSetColorBG( DebuggerGetColor( WATCH_ZERO_BG )); // BG_INFO
|
|
|
|
PrintTextCursorX( " ", rect2 );
|
|
|
|
}
|
2011-02-20 23:29:00 +00:00
|
|
|
|
|
|
|
if ((iByte & 1) == 1)
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( WATCH_ZERO_BG )); // BG_DATA_2
|
|
|
|
else
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DATA_2 ));
|
|
|
|
|
|
|
|
BYTE nValue8 = (unsigned)*(LPBYTE)(mem + nTarget16 + iByte );
|
|
|
|
sprintf(sText,"%02X", nValue8 );
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
2011-02-20 07:31:08 +00:00
|
|
|
}
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
rect.top += g_nFontHeight;
|
|
|
|
rect.bottom += g_nFontHeight;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawZeroPagePointers ( int line )
|
|
|
|
{
|
|
|
|
if (! ((g_iWindowThis == WINDOW_CODE) || ((g_iWindowThis == WINDOW_DATA))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
rect.top = line * g_nFontHeight;
|
|
|
|
rect.bottom = rect.top + g_nFontHeight;
|
|
|
|
rect.left = DISPLAY_ZEROPAGE_COLUMN;
|
|
|
|
rect.right = rect.left + (10 * nFontWidth);
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( WATCH_ZERO_BG )); // BG_INFO
|
|
|
|
|
|
|
|
const int nMaxSymbolLen = 7;
|
|
|
|
char sText[nMaxSymbolLen+1] = "";
|
|
|
|
|
|
|
|
for(int iZP = 0; iZP < MAX_ZEROPAGE_POINTERS; iZP++)
|
|
|
|
{
|
|
|
|
RECT rect2 = rect;
|
|
|
|
|
|
|
|
Breakpoint_t *pZP = &g_aZeroPagePointers[iZP];
|
|
|
|
bool bEnabled = pZP->bEnabled;
|
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
#if DEBUG_FORCE_DISPLAY // Zero-Page
|
2010-06-11 15:38:22 +00:00
|
|
|
bEnabled = true;
|
|
|
|
#endif
|
|
|
|
if (bEnabled)
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_TITLE ) );
|
|
|
|
PrintTextCursorX( "Z", rect2 );
|
|
|
|
|
|
|
|
sprintf( sText, "%X ", iZP );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_BULLET ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
// PrintTextCursorX( " ", rect2 );
|
|
|
|
|
|
|
|
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* pSymbol2 = GetSymbol(nZPAddr2, 2); // 2:8-bit value (if symbol not found)
|
|
|
|
const char* pSymbol1 = GetSymbol(nZPAddr1, 2); // 2:8-bit value (if symbol not found)
|
|
|
|
|
|
|
|
int nLen1 = strlen( pSymbol1 );
|
|
|
|
int nLen2 = strlen( pSymbol2 );
|
|
|
|
|
|
|
|
|
|
|
|
// if ((nLen1 == 1) && (nLen2 == 1))
|
|
|
|
// sprintf( sText, "%s%s", pszSymbol1, pszSymbol2);
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
|
|
|
|
|
|
|
|
int x;
|
|
|
|
for( x = 0; x < nMaxSymbolLen; x++ )
|
|
|
|
{
|
|
|
|
sText[ x ] = CHAR_SPACE;
|
|
|
|
}
|
|
|
|
sText[nMaxSymbolLen] = 0;
|
|
|
|
|
|
|
|
if ((nLen1) && (pSymbol1[0] == '$'))
|
|
|
|
{
|
|
|
|
// sprintf( sText, "%s%s", pSymbol1 );
|
|
|
|
// sprintf( sText, "%04X", nZPAddr1 );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if ((nLen2) && (pSymbol2[0] == '$'))
|
|
|
|
{
|
|
|
|
// sprintf( sText, "%s%s", pSymbol2 );
|
|
|
|
// sprintf( sText, "%04X", nZPAddr2 );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int nMin = min( nLen1, nMaxSymbolLen );
|
|
|
|
memcpy(sText, pSymbol1, nMin);
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_SYMBOL ) );
|
|
|
|
}
|
|
|
|
// DrawRegister( line+iZP, szZP, 2, nTarget16);
|
|
|
|
// PrintText( szZP, rect2 );
|
|
|
|
PrintText( sText, rect2);
|
|
|
|
|
|
|
|
rect2.left = rect.left;
|
|
|
|
rect2.top += g_nFontHeight;
|
|
|
|
rect2.bottom += g_nFontHeight;
|
|
|
|
|
|
|
|
sprintf( sText, "%02X", nZPAddr1 );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( ":", rect2 );
|
|
|
|
|
|
|
|
WORD nTarget16 = (WORD)mem[ nZPAddr1 ] | ((WORD)mem[ nZPAddr2 ]<< 8);
|
|
|
|
sprintf( sText, "%04X", nTarget16 );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
|
|
|
|
PrintTextCursorX( ":", rect2 );
|
|
|
|
|
|
|
|
BYTE nValue8 = (unsigned)*(LPBYTE)(mem + nTarget16);
|
|
|
|
sprintf(sText, "%02X", nValue8 );
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
|
|
|
|
PrintTextCursorX( sText, rect2 );
|
|
|
|
}
|
|
|
|
rect.top += (g_nFontHeight * 2);
|
|
|
|
rect.bottom += (g_nFontHeight * 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Sub Windows ____________________________________________________________________________________
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSubWindow_Console (Update_t bUpdate)
|
|
|
|
{
|
|
|
|
if (! CanDrawDebugger())
|
|
|
|
return;
|
|
|
|
|
|
|
|
#if !USE_APPLE_FONT
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( GetDebuggerMemDC(), g_aFontConfig[ FONT_CONSOLE ]._hFont );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if ((bUpdate & UPDATE_CONSOLE_DISPLAY)
|
|
|
|
|| (bUpdate & UPDATE_CONSOLE_INPUT))
|
|
|
|
{
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_CONSOLE_OUTPUT ));
|
|
|
|
|
|
|
|
// int nLines = MIN(g_nConsoleDisplayTotal - g_iConsoleDisplayStart, g_nConsoleDisplayHeight);
|
|
|
|
int iLine = g_iConsoleDisplayStart + CONSOLE_FIRST_LINE;
|
|
|
|
for (int y = 1; y < g_nConsoleDisplayLines ; y++ )
|
|
|
|
{
|
|
|
|
if (iLine <= (g_nConsoleDisplayTotal + CONSOLE_FIRST_LINE))
|
|
|
|
{
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_CONSOLE_OUTPUT ));
|
|
|
|
DrawConsoleLine( g_aConsoleDisplay[ iLine ], y );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// bugfix: 2.6.1.34
|
|
|
|
// scrolled past top of console... Draw blank line
|
|
|
|
DrawConsoleLine( NULL, y );
|
|
|
|
}
|
|
|
|
iLine++;
|
|
|
|
}
|
|
|
|
|
|
|
|
DrawConsoleInput();
|
|
|
|
}
|
|
|
|
|
|
|
|
// if (bUpdate & UPDATE_CONSOLE_INPUT)
|
|
|
|
{
|
2012-12-29 14:53:52 +00:00
|
|
|
// DrawConsoleInput();
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSubWindow_Data (Update_t bUpdate)
|
|
|
|
{
|
|
|
|
// HDC hDC = g_hDC;
|
2014-08-28 23:52:41 +00:00
|
|
|
int iBackground;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
const int nMaxOpcodes = WINDOW_DATA_BYTES_PER_LINE;
|
2014-08-28 23:52:41 +00:00
|
|
|
char sAddress[ 5 ];
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
assert( CONSOLE_WIDTH > WINDOW_DATA_BYTES_PER_LINE );
|
|
|
|
|
|
|
|
char sOpcodes [ CONSOLE_WIDTH ] = "";
|
|
|
|
char 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;
|
|
|
|
|
2010-12-18 15:29:26 +00:00
|
|
|
// if (!pMD->bActive)
|
|
|
|
// return;
|
|
|
|
|
|
|
|
// int iWindows = g_iThisWindow;
|
|
|
|
// WindowSplit_t * pWindow = &g_aWindowConfig[ iWindow ];
|
|
|
|
|
|
|
|
RECT rect;
|
|
|
|
rect.top = 0 + 0;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
int iByte;
|
|
|
|
WORD iAddress = nAddress;
|
|
|
|
|
|
|
|
int iLine;
|
|
|
|
int nLines = g_nDisasmWinHeight;
|
|
|
|
|
|
|
|
for (iLine = 0; iLine < nLines; iLine++ )
|
|
|
|
{
|
|
|
|
iAddress = nAddress;
|
|
|
|
|
|
|
|
// Format
|
|
|
|
sprintf( sAddress, "%04X", iAddress );
|
|
|
|
|
|
|
|
sOpcodes[0] = 0;
|
|
|
|
for ( iByte = 0; iByte < nMaxOpcodes; iByte++ )
|
|
|
|
{
|
|
|
|
BYTE nData = (unsigned)*(LPBYTE)(mem + iAddress + iByte);
|
|
|
|
sprintf( &sOpcodes[ iByte * 3 ], "%02X ", nData );
|
|
|
|
}
|
|
|
|
sOpcodes[ nMaxOpcodes * 3 ] = 0;
|
|
|
|
|
|
|
|
int nFontHeight = g_aFontConfig[ FONT_DISASM_DEFAULT ]._nLineHeight;
|
|
|
|
|
|
|
|
// Draw
|
|
|
|
rect.left = 0;
|
|
|
|
rect.right = DISPLAY_DISASM_RIGHT;
|
|
|
|
rect.bottom = rect.top + nFontHeight;
|
|
|
|
|
|
|
|
if (iLine & 1)
|
|
|
|
{
|
|
|
|
iBackground = BG_DATA_1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
iBackground = BG_DATA_2;
|
|
|
|
}
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ) );
|
|
|
|
PrintTextCursorX( (LPCTSTR) sAddress, rect );
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ) );
|
|
|
|
if (g_bConfigDisasmAddressColon)
|
|
|
|
PrintTextCursorX( ":", rect );
|
|
|
|
|
|
|
|
rect.left = X_OPCODE;
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DATA_BYTE ) );
|
|
|
|
PrintTextCursorX( (LPCTSTR) sOpcodes, rect );
|
|
|
|
|
|
|
|
rect.left = X_CHAR;
|
|
|
|
|
|
|
|
// Seperator
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
|
|
|
PrintTextCursorX( " | ", rect );
|
|
|
|
|
|
|
|
|
|
|
|
// Plain Text
|
|
|
|
DebuggerSetColorFG( 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( sImmediate, (BYTE) nImmediate, eView, iBackground );
|
|
|
|
PrintTextCursorX( (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 );
|
|
|
|
PrintTextCursorX( (LPCSTR) sImmediate, rect );
|
|
|
|
|
|
|
|
iAddress++;
|
|
|
|
}
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) ); // Hack, colorize Char background "spills over to EOL"
|
|
|
|
PrintTextCursorX( " ", rect );
|
|
|
|
*/
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ) ); // HACK: Colorize() can "spill over" to EOL
|
|
|
|
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_OPERATOR ));
|
|
|
|
PrintTextCursorX( " | ", rect );
|
|
|
|
|
|
|
|
nAddress += nMaxOpcodes;
|
2010-12-18 15:29:26 +00:00
|
|
|
|
|
|
|
rect.top += nFontHeight;
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
2011-02-20 23:29:00 +00:00
|
|
|
void DrawSubWindow_Info ( Update_t bUpdate, int iWindow )
|
2010-06-11 15:38:22 +00:00
|
|
|
{
|
|
|
|
if (g_iWindowThis == WINDOW_CONSOLE)
|
|
|
|
return;
|
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
// Left Side
|
|
|
|
int yRegs = 0; // 12
|
|
|
|
int yStack = yRegs + MAX_DISPLAY_REGS_LINES + 0; // 0
|
|
|
|
int yTarget = yStack + MAX_DISPLAY_STACK_LINES - 1; // 9
|
|
|
|
int yZeroPage = 16; // yTarget
|
2017-04-27 19:00:54 +00:00
|
|
|
int ySoft = yZeroPage + (2 * MAX_DISPLAY_ZEROPAGE_LINES) + !SOFTSWITCH_LANGCARD;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
if ((bUpdate & UPDATE_REGS) || (bUpdate & UPDATE_FLAGS))
|
|
|
|
DrawRegisters( yRegs );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
if (bUpdate & UPDATE_STACK)
|
|
|
|
DrawStack( yStack );
|
2011-01-04 17:33:10 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
// 2.7.0.2 Fixed: Debug build of debugger force display all CPU info window wasn't calling DrawTargets()
|
|
|
|
bool bForceDisplayTargetPtr = DEBUG_FORCE_DISPLAY || (g_bConfigInfoTargetPointer);
|
|
|
|
if (bForceDisplayTargetPtr || (bUpdate & UPDATE_TARGETS))
|
|
|
|
DrawTargets( yTarget );
|
|
|
|
|
|
|
|
if (bUpdate & UPDATE_ZERO_PAGE)
|
|
|
|
DrawZeroPagePointers( yZeroPage );
|
|
|
|
|
|
|
|
bool bForceDisplaySoftSwitches = DEBUG_FORCE_DISPLAY || (bUpdate & UPDATE_SOFTSWITCHES);
|
|
|
|
DrawSoftSwitches( ySoft );
|
|
|
|
|
|
|
|
#if defined(SUPPORT_Z80_EMU) && defined(OUTPUT_Z80_REGS)
|
|
|
|
DrawRegister( 19,"AF",2,*(WORD*)(membank+REG_AF));
|
|
|
|
DrawRegister( 20,"BC",2,*(WORD*)(membank+REG_BC));
|
|
|
|
DrawRegister( 21,"DE",2,*(WORD*)(membank+REG_DE));
|
|
|
|
DrawRegister( 22,"HL",2,*(WORD*)(membank+REG_HL));
|
|
|
|
DrawRegister( 23,"IX",2,*(WORD*)(membank+REG_IX));
|
|
|
|
#endif
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// Right Side
|
2011-02-20 23:29:00 +00:00
|
|
|
int yBreakpoints = 0;
|
|
|
|
int yWatches = yBreakpoints + MAX_BREAKPOINTS; // MAX_DISPLAY_BREAKPOINTS_LINES; // 7
|
|
|
|
int yMemory = yWatches + (MAX_WATCHES*2); // MAX_DISPLAY_WATCHES_LINES ; // 14 // 2.7.0.15 Fixed: Memory Dump was over-writing watches
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
// if ((MAX_DISPLAY_BREAKPOINTS_LINES + MAX_DISPLAY_WATCHES_LINES) < 12)
|
|
|
|
// yWatches++;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
bool bForceDisplayBreakpoints = DEBUG_FORCE_DISPLAY || (g_nBreakpoints > 0); // 2.7.0.11 Fixed: Breakpoints and Watches no longer disappear.
|
|
|
|
if ( bForceDisplayBreakpoints || (bUpdate & UPDATE_BREAKPOINTS))
|
|
|
|
DrawBreakpoints( yBreakpoints );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
bool bForceDisplayWatches = DEBUG_FORCE_DISPLAY || (g_nWatches > 0); // 2.7.0.11 Fixed: Breakpoints and Watches no longer disappear.
|
|
|
|
if ( bForceDisplayWatches || (bUpdate & UPDATE_WATCH))
|
|
|
|
DrawWatches( yWatches );
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
g_nDisplayMemoryLines = MAX_DISPLAY_MEMORY_LINES_1;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
bool bForceDisplayMemory1 = DEBUG_FORCE_DISPLAY || (g_aMemDump[0].bActive);
|
|
|
|
if (bForceDisplayMemory1 || (bUpdate & UPDATE_MEM_DUMP))
|
|
|
|
DrawMemory( yMemory, 0 ); // g_aMemDump[0].nAddress, g_aMemDump[0].eDevice);
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
yMemory += (g_nDisplayMemoryLines + 1);
|
|
|
|
g_nDisplayMemoryLines = MAX_DISPLAY_MEMORY_LINES_2;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
bool bForceDisplayMemory2 = DEBUG_FORCE_DISPLAY || (g_aMemDump[1].bActive);
|
|
|
|
if (bForceDisplayMemory2 || (bUpdate & UPDATE_MEM_DUMP))
|
|
|
|
DrawMemory( yMemory, 1 ); // g_aMemDump[1].nAddress, g_aMemDump[1].eDevice);
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSubWindow_IO (Update_t bUpdate)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSubWindow_Source (Update_t bUpdate)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSubWindow_Source2 (Update_t bUpdate)
|
|
|
|
{
|
|
|
|
// if (! g_bSourceLevelDebugging)
|
|
|
|
// return;
|
|
|
|
|
|
|
|
DebuggerSetColorFG( 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
|
|
|
|
char sTitle[ CONSOLE_WIDTH ];
|
|
|
|
char sText [ CONSOLE_WIDTH ];
|
|
|
|
strcpy ( sTitle, " Source: " );
|
2018-02-24 15:24:37 +00:00
|
|
|
int maxSizeToCopy = g_nConsoleDisplayWidth - strlen(sTitle) - 1;
|
|
|
|
strncpy( sText , g_aSourceFileName, maxSizeToCopy );
|
|
|
|
sText[ maxSizeToCopy - 1 ] = 0;
|
2010-06-11 15:38:22 +00:00
|
|
|
strcat ( sTitle, sText );
|
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_SOURCE_TITLE ));
|
|
|
|
DebuggerSetColorFG( DebuggerGetColor( FG_SOURCE_TITLE ));
|
|
|
|
PrintText( 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
|
|
|
|
}
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( iBackground ));
|
|
|
|
DebuggerSetColorFG( 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 );
|
|
|
|
|
2011-02-20 23:29:00 +00:00
|
|
|
DrawSubWindow_Info( bUpdate, g_iWindowThis );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Full Screen console
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindow_Console( Update_t bUpdate )
|
|
|
|
{
|
|
|
|
// Nothing to do, since text and draw background handled by DrawSubWindow_Console()
|
|
|
|
// If the full screen console is only showing partial lines
|
|
|
|
// don't erase the background
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
// FillRect( GetDebuggerMemDC(), &rect, g_hConsoleBrushBG );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindow_Data( Update_t bUpdate )
|
|
|
|
{
|
|
|
|
DrawSubWindow_Data( g_iWindowThis );
|
2011-02-20 23:29:00 +00:00
|
|
|
DrawSubWindow_Info( bUpdate, g_iWindowThis );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindow_IO( Update_t bUpdate )
|
|
|
|
{
|
|
|
|
DrawSubWindow_IO( g_iWindowThis );
|
2011-02-20 23:29:00 +00:00
|
|
|
DrawSubWindow_Info( bUpdate, g_iWindowThis );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindow_Source( Update_t bUpdate )
|
|
|
|
{
|
|
|
|
DrawSubWindow_Source( g_iWindowThis );
|
2011-02-20 23:29:00 +00:00
|
|
|
DrawSubWindow_Info( bUpdate, g_iWindowThis );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindow_Symbols( Update_t bUpdate )
|
|
|
|
{
|
|
|
|
DrawSubWindow_Symbols( g_iWindowThis );
|
2011-02-20 23:29:00 +00:00
|
|
|
DrawSubWindow_Info( bUpdate, g_iWindowThis );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DrawWindow_ZeroPage( Update_t bUpdate )
|
|
|
|
{
|
|
|
|
DrawSubWindow_ZeroPage( g_iWindowThis );
|
2011-02-20 23:29:00 +00:00
|
|
|
DrawSubWindow_Info( bUpdate, g_iWindowThis );
|
2010-06-11 15:38:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindowBackground_Main( int g_iWindowThis )
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
rect.left = 0;
|
|
|
|
rect.top = 0;
|
|
|
|
rect.right = DISPLAY_DISASM_RIGHT;
|
|
|
|
int nTop = GetConsoleTopPixels( g_nConsoleDisplayLines - 1 );
|
2012-12-29 14:53:52 +00:00
|
|
|
rect.bottom = nTop;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
// TODO/FIXME: COLOR_BG_CODE -> g_iWindowThis, once all tab backgrounds are listed first in g_aColors !
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_DISASM_1 )); // COLOR_BG_CODE
|
|
|
|
|
|
|
|
#if !DEBUG_FONT_NO_BACKGROUND_FILL_MAIN
|
2012-12-29 14:53:52 +00:00
|
|
|
FillRect( GetDebuggerMemDC(), &rect, g_hConsoleBrushBG );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindowBackground_Info( int g_iWindowThis )
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
rect.top = 0;
|
|
|
|
rect.left = DISPLAY_DISASM_RIGHT;
|
|
|
|
rect.right = DISPLAY_WIDTH;
|
|
|
|
int nTop = GetConsoleTopPixels( g_nConsoleDisplayLines - 1 );
|
2012-12-29 14:53:52 +00:00
|
|
|
rect.bottom = nTop;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
DebuggerSetColorBG( DebuggerGetColor( BG_INFO )); // COLOR_BG_DATA
|
|
|
|
|
|
|
|
#if !DEBUG_FONT_NO_BACKGROUND_FILL_INFO
|
2012-12-29 14:53:52 +00:00
|
|
|
FillRect( GetDebuggerMemDC(), &rect, g_hConsoleBrushBG );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void UpdateDisplay (Update_t bUpdate)
|
|
|
|
{
|
|
|
|
static int spDrawMutex = false;
|
|
|
|
|
|
|
|
if (spDrawMutex)
|
|
|
|
{
|
|
|
|
#if DEBUG
|
|
|
|
MessageBox( g_hFrameWindow, "Already drawing!", "!", MB_OK );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
spDrawMutex = true;
|
|
|
|
|
|
|
|
// Hack: Full screen console scrolled, "erase" left over console lines
|
|
|
|
if (g_iWindowThis == WINDOW_CONSOLE)
|
|
|
|
bUpdate |= UPDATE_BACKGROUND;
|
|
|
|
|
|
|
|
if (bUpdate & UPDATE_BACKGROUND)
|
|
|
|
{
|
|
|
|
#if USE_APPLE_FONT
|
2012-12-29 14:53:52 +00:00
|
|
|
SetBkMode( GetDebuggerMemDC(), OPAQUE);
|
|
|
|
SetBkColor(GetDebuggerMemDC(), RGB(0,0,0));
|
2010-06-11 15:38:22 +00:00
|
|
|
#else
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( GetDebuggerMemDC(), g_aFontConfig[ FONT_INFO ]._hFont ); // g_hFontDebugger
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
SetTextAlign( GetDebuggerMemDC(), TA_TOP | TA_LEFT);
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
if ((bUpdate & UPDATE_BREAKPOINTS)
|
2011-02-20 23:29:00 +00:00
|
|
|
// || (bUpdate & UPDATE_DISASM)
|
2010-06-11 15:38:22 +00:00
|
|
|
|| (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 );
|
2017-12-17 18:20:39 +00:00
|
|
|
break;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
case WINDOW_SOURCE:
|
|
|
|
DrawWindow_Source( bUpdate );
|
2017-12-17 18:20:39 +00:00
|
|
|
break;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
case WINDOW_SYMBOLS:
|
|
|
|
DrawWindow_Symbols( bUpdate );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WINDOW_ZEROPAGE:
|
|
|
|
DrawWindow_ZeroPage( bUpdate );
|
2017-12-17 18:20:39 +00:00
|
|
|
break;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((bUpdate & UPDATE_CONSOLE_DISPLAY) || (bUpdate & UPDATE_CONSOLE_INPUT))
|
|
|
|
DrawSubWindow_Console( bUpdate );
|
|
|
|
|
2012-12-29 14:53:52 +00:00
|
|
|
StretchBltMemToFrameDC();
|
2010-06-11 15:38:22 +00:00
|
|
|
|
|
|
|
spDrawMutex = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawWindowBottom ( Update_t bUpdate, int iWindow )
|
|
|
|
{
|
|
|
|
if (! g_aWindowConfig[ iWindow ].bSplit)
|
|
|
|
return;
|
|
|
|
|
|
|
|
WindowSplit_t * pWindow = &g_aWindowConfig[ iWindow ];
|
2010-12-18 15:29:26 +00:00
|
|
|
g_pDisplayWindow = pWindow;
|
2010-06-11 15:38:22 +00:00
|
|
|
|
2010-12-18 15:29:26 +00:00
|
|
|
if (pWindow->eBot == WINDOW_DATA)
|
|
|
|
DrawWindow_Data( bUpdate ); // false
|
|
|
|
else
|
2010-06-11 15:38:22 +00:00
|
|
|
if (pWindow->eBot == WINDOW_SOURCE)
|
|
|
|
DrawSubWindow_Source2( bUpdate );
|
|
|
|
}
|
|
|
|
|
|
|
|
//===========================================================================
|
|
|
|
void DrawSubWindow_Code ( int iWindow )
|
|
|
|
{
|
|
|
|
int nLines = g_nDisasmWinHeight;
|
|
|
|
|
2010-12-18 15:29:26 +00:00
|
|
|
// WindowSplit_t * pWindow = &g_aWindowConfig[ iWindow ];
|
|
|
|
|
2010-06-11 15:38:22 +00:00
|
|
|
// 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();
|
|
|
|
#if !USE_APPLE_FONT
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( GetDebuggerMemDC(), g_aFontConfig[ FONT_DISASM_DEFAULT ]._hFont );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
WORD nAddress = g_nDisasmTopAddress; // g_nDisasmCurAddress;
|
|
|
|
for (int iLine = 0; iLine < nLines; iLine++ )
|
|
|
|
{
|
|
|
|
nAddress += DrawDisassemblyLine( iLine, nAddress );
|
|
|
|
}
|
|
|
|
|
|
|
|
#if !USE_APPLE_FONT
|
2012-12-29 14:53:52 +00:00
|
|
|
SelectObject( GetDebuggerMemDC(), g_aFontConfig[ FONT_INFO ]._hFont );
|
2010-06-11 15:38:22 +00:00
|
|
|
#endif
|
|
|
|
}
|