Debugger: Extend watches: 'WA <n> v' to show video scanner address & video data (aux and/or main or shr 4-byte)

This commit is contained in:
tomcw 2022-10-02 16:28:03 +01:00
parent 4fc07b4a7a
commit dfaaa2823e
6 changed files with 180 additions and 24 deletions

View File

@ -114,6 +114,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"M", // Mem RW
"M", // Mem READ_ONLY
"M", // Mem WRITE_ONLY
// Watches
"M", // Memory
"V", // Video Scanner
// TODO: M0 ram bank 0, M1 aux ram ?
};
@ -6655,7 +6658,7 @@ Update_t CmdWatch (int nArgs)
//===========================================================================
Update_t CmdWatchAdd (int nArgs)
{
// WA [adddress]
// WA [address]
// WA # address
if (! nArgs)
{
@ -6673,6 +6676,18 @@ Update_t CmdWatchAdd (int nArgs)
bool bAdded = false;
for (; iArg <= nArgs; iArg++ )
{
if (g_aArgs[iArg].eToken == TOKEN_ALPHANUMERIC && g_aArgs[iArg].sArg[0] == 'v') // 'video' ?
{
g_aWatches[iWatch].bSet = true;
g_aWatches[iWatch].bEnabled = true;
g_aWatches[iWatch].eSource = BP_SRC_VIDEO_SCANNER;
g_aWatches[iWatch].nAddress = 0xDEAD;
bAdded = true;
g_nWatches++;
iWatch++;
continue;
}
WORD nAddress = g_aArgs[iArg].nValue;
// Make sure address isn't an IO address
@ -6698,6 +6713,7 @@ Update_t CmdWatchAdd (int nArgs)
{
g_aWatches[iWatch].bSet = true;
g_aWatches[iWatch].bEnabled = true;
g_aWatches[iWatch].eSource = BP_SRC_MEMORY;
g_aWatches[iWatch].nAddress = (WORD) nAddress;
bAdded = true;
g_nWatches++;

View File

@ -2767,7 +2767,7 @@ void DrawWatches (int line)
#if DEBUG_FORCE_DISPLAY // Watch
if (true)
#else
if (g_aWatches[iWatch].bEnabled)
if (g_aWatches[iWatch].bEnabled && g_aWatches[iWatch].eSource == BP_SRC_MEMORY)
#endif
{
RECT rect2 = rect;
@ -2779,40 +2779,32 @@ void DrawWatches (int line)
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_BULLET ));
PrintTextCursorX( StrFormat( "%X ", iWatch ).c_str(), rect2 );
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
// PrintTextCursorX( ".", rect2 );
DebuggerSetColorFG( DebuggerGetColor( FG_DISASM_ADDRESS ));
PrintTextCursorX( WordToHexStr( g_aWatches[iWatch].nAddress ).c_str(), rect2 );
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
PrintTextCursorX( ":", rect2 );
BYTE nTarget8 = 0;
//
nTarget8 = (unsigned)*(LPBYTE)(mem+g_aWatches[iWatch].nAddress);
BYTE nTargetL = *(LPBYTE)(mem + g_aWatches[iWatch].nAddress);
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
PrintTextCursorX( ByteToHexStr( nTarget8 ).c_str(), rect2 );
PrintTextCursorX( ByteToHexStr( nTargetL ).c_str(), rect2 );
nTarget8 = (unsigned)*(LPBYTE)(mem+g_aWatches[iWatch].nAddress + 1);
BYTE nTargetH = *(LPBYTE)(mem + ((g_aWatches[iWatch].nAddress + 1) & 0xffff));
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
PrintTextCursorX( ByteToHexStr( nTarget8 ).c_str(), rect2 );
PrintTextCursorX( ByteToHexStr( nTargetH ).c_str(), rect2 );
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
PrintTextCursorX( "(", rect2 );
WORD nTarget16 = (unsigned)*(LPWORD)(mem+g_aWatches[iWatch].nAddress);
WORD nTarget16 = (((WORD)nTargetH) << 8) | ((WORD)nTargetL);
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_ADDRESS ));
PrintTextCursorX( WordToHexStr( nTarget16 ).c_str(), rect2 );
DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPERATOR ));
// PrintTextCursorX( ":", rect2 );
PrintTextCursorX( ")", rect2 );
// BYTE nValue8 = *(LPBYTE)(mem + nTarget16);
// DebuggerSetColorFG( DebuggerGetColor( FG_INFO_OPCODE ));
// PrintTextCursorX( ByteToHexStr( nValue8 ).c_str(), rect2 );
rect.top += g_nFontHeight;
rect.bottom += g_nFontHeight;
@ -2836,6 +2828,54 @@ void DrawWatches (int line)
PrintTextCursorX( ByteToHexStr( nValue8 ).c_str(), rect2 );
}
}
else if (g_aWatches[iWatch].bEnabled && g_aWatches[iWatch].eSource == BP_SRC_VIDEO_SCANNER)
{
uint32_t data;
int dataSize;
g_aWatches[iWatch].nAddress = NTSC_GetScannerAddressAndData(data, dataSize);
RECT rect2 = rect;
DebuggerSetColorBG(DebuggerGetColor(BG_INFO_WATCH));
DebuggerSetColorFG(DebuggerGetColor(FG_INFO_TITLE));
PrintTextCursorX("W", rect2);
DebuggerSetColorFG(DebuggerGetColor(FG_INFO_BULLET));
PrintTextCursorX(StrFormat("%X ", iWatch).c_str(), rect2);
DebuggerSetColorFG(DebuggerGetColor(FG_DISASM_ADDRESS));
PrintTextCursorX(WordToHexStr(g_aWatches[iWatch].nAddress).c_str(), rect2);
DebuggerSetColorFG(DebuggerGetColor(FG_INFO_OPERATOR));
PrintTextCursorX(":", rect2);
DebuggerSetColorFG(DebuggerGetColor(FG_INFO_OPCODE));
if (dataSize == 1)
{
PrintTextCursorX(ByteToHexStr(data).c_str(), rect2);
}
else if (dataSize == 2)
{
PrintTextCursorX("a:", rect2);
PrintTextCursorX(ByteToHexStr(data>>8).c_str(), rect2);
PrintTextCursorX(" m:", rect2);
PrintTextCursorX(ByteToHexStr(data).c_str(), rect2);
}
else
{
_ASSERT(dataSize == 4);
PrintTextCursorX(DWordToHexStr(data).c_str(), rect2);
}
rect.top += g_nFontHeight;
rect.bottom += g_nFontHeight;
}
else
{
rect.top += g_nFontHeight;
rect.bottom += g_nFontHeight;
}
rect.top += g_nFontHeight;
rect.bottom += g_nFontHeight;
}

View File

@ -184,6 +184,9 @@
BP_SRC_MEM_READ_ONLY,
BP_SRC_MEM_WRITE_ONLY,
BP_SRC_MEMORY, // For watches
BP_SRC_VIDEO_SCANNER, // For watches
NUM_BREAKPOINT_SOURCES
};
@ -516,7 +519,7 @@
, CMD_VIEW_DHGR2
, CMD_VIEW_SHR
// Watch
, CMD_WATCH // TODO: Deprecated ?
, CMD_WATCH
, CMD_WATCH_ADD
, CMD_WATCH_CLEAR
, CMD_WATCH_DISABLE

View File

@ -869,6 +869,16 @@ INLINE uint16_t getVideoScannerAddressHGR()
return nAddress;
}
//===========================================================================
INLINE uint16_t getVideoScannerAddressSHR()
{
// 2 pixels per byte in 320-pixel mode = 160 bytes/scanline
// 4 pixels per byte in 640-pixel mode = 160 bytes/scanline
const UINT kBytesPerScanline = 160;
const UINT kBytesPerCycle = 4;
return 0x2000 + kBytesPerScanline * g_nVideoClockVert + kBytesPerCycle * (g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START);
}
// Non-Inline _________________________________________________________
// Build the 4 phase chroma lookup table
@ -1822,14 +1832,10 @@ void updateScreenSHR(long cycles6502)
{
for (; cycles6502 > 0; --cycles6502)
{
// 2 pixels per byte in 320-pixel mode = 160 bytes/scanline
// 4 pixels per byte in 640-pixel mode = 160 bytes/scanline
const UINT kBytesPerScanline = 160;
const UINT kBytesPerCycle = 4;
uint16_t addr = 0x2000 + kBytesPerScanline * g_nVideoClockVert + kBytesPerCycle * (g_nVideoClockHorz - VIDEO_SCANNER_HORZ_START);
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY_IIGS)
{
uint16_t addr = getVideoScannerAddressSHR();
if (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START)
{
uint32_t* pAux = (uint32_t*) MemGetAuxPtr(addr); // 8 pixels (320 mode) / 16 pixels (640 mode)
@ -1947,6 +1953,8 @@ void NTSC_SetVideoTextMode( int cols )
//===========================================================================
void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
{
g_uNewVideoModeFlags = uVideoModeFlags;
if (uVideoModeFlags & VF_SHR)
{
g_pFuncUpdateGraphicsScreen = updateScreenSHR;
@ -1965,7 +1973,6 @@ void NTSC_SetVideoMode( uint32_t uVideoModeFlags, bool bDelay/*=false*/ )
// (GH#670) NB. if g_bFullSpeed then NTSC_VideoUpdateCycles() won't be called on the next 6502 opcode.
// - Instead it's called when !g_bFullSpeed (eg. drive motor off), then the stale g_uNewVideoModeFlags will get used for NTSC_SetVideoMode()!
g_bDelayVideoMode = true;
g_uNewVideoModeFlags = uVideoModeFlags;
return;
}
@ -2711,3 +2718,84 @@ bool NTSC_IsVisible(void)
{
return (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_START);
}
// For debugger
uint16_t NTSC_GetScannerAddressAndData(uint32_t& data, int& dataSize)
{
uint16_t addr = 0;
if (g_uNewVideoModeFlags & VF_SHR)
{
addr = getVideoScannerAddressSHR();
uint32_t* pAux = (uint32_t*)MemGetAuxPtr(addr); // 8 pixels (320 mode) / 16 pixels (640 mode)
data = pAux[0];
dataSize = 4;
return addr;
}
//
if ( (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED) ||
(g_uNewVideoModeFlags & VF_TEXT) ||
!(g_uNewVideoModeFlags & VF_HIRES) )
{
addr = getVideoScannerAddressTXT();
}
else
{
addr = getVideoScannerAddressHGR();
}
// Copy logic from NTSC_SetVideoMode()
if (g_uNewVideoModeFlags & VF_TEXT)
{
if (g_uNewVideoModeFlags & VF_80COL)
dataSize = 2;
else
dataSize = 1;
}
else if (g_uNewVideoModeFlags & VF_HIRES)
{
if (g_uNewVideoModeFlags & VF_DHIRES)
{
if (g_uNewVideoModeFlags & VF_80COL)
dataSize = 2;
else
dataSize = 1;
}
else
{
dataSize = 1;
}
}
else
{
if (g_uNewVideoModeFlags & VF_DHIRES)
{
if (g_uNewVideoModeFlags & VF_80COL)
dataSize = 2;
else
dataSize = 1;
}
else
{
dataSize = 1;
}
}
// Extra logic for MIXED mode
if (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && (g_uNewVideoModeFlags & VF_80COL))
dataSize = 2;
data = 0;
if (dataSize == 2)
{
uint8_t* pAux = MemGetAuxPtr(addr);
data = pAux[0] << 8;
}
uint8_t* pMain = MemGetMainPtr(addr);
data |= pMain[0];
return addr;
}

View File

@ -29,3 +29,4 @@ UINT NTSC_GetCyclesPerLine(void);
UINT NTSC_GetVideoLines(void);
UINT NTSC_GetCyclesUntilVBlank(int cycles);
bool NTSC_IsVisible(void);
uint16_t NTSC_GetScannerAddressAndData(uint32_t& data, int& dataSize);

View File

@ -75,4 +75,12 @@ inline std::string WordToHexStr(uint16_t n)
return s;
}
inline std::string DWordToHexStr(uint32_t n)
{
std::string s;
StrAppendWordAsHex(s, n >> 16);
StrAppendWordAsHex(s, n);
return s;
}
} // namespace