From 1de6adabc2259bcf6dd6b697dccde6aa558b26ca Mon Sep 17 00:00:00 2001 From: nzeemin Date: Thu, 4 Mar 2021 15:33:42 +0300 Subject: [PATCH] MemoryView: split base address / current address; context menu. --- emulator/DisasmView.cpp | 8 +- emulator/Main.h | 2 + emulator/MainWindow.cpp | 4 +- emulator/MemoryView.cpp | 625 ++++++++++++++++++++++++---------------- emulator/Settings.cpp | 1 + emulator/res/Resource.h | 5 +- 6 files changed, 394 insertions(+), 251 deletions(-) diff --git a/emulator/DisasmView.cpp b/emulator/DisasmView.cpp index ae165f9..936492a 100644 --- a/emulator/DisasmView.cpp +++ b/emulator/DisasmView.cpp @@ -228,7 +228,7 @@ LRESULT CALLBACK DisasmViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, ::InvalidateRect(hWnd, NULL, TRUE); break; case WM_COMMAND: - if (wParam == ID_DISASM_COPY_ADDRESS || wParam == ID_DISASM_COPY_VALUE) + if (wParam == ID_DEBUG_COPY_ADDRESS || wParam == ID_DEBUG_COPY_VALUE) DisasmView_CopyToClipboard(wParam); else return DefWindowProc(hWnd, message, wParam, lParam); @@ -297,8 +297,8 @@ void DisasmView_OnRButtonDown(WPARAM /*wParam*/, int mousex, int mousey) ::SetFocus(m_hwndDisasmViewer); HMENU hMenu = ::CreatePopupMenu(); - ::AppendMenu(hMenu, 0, ID_DISASM_COPY_ADDRESS, _T("Copy Address")); - ::AppendMenu(hMenu, 0, ID_DISASM_COPY_VALUE, _T("Copy Value")); + ::AppendMenu(hMenu, 0, ID_DEBUG_COPY_ADDRESS, _T("Copy Address")); + ::AppendMenu(hMenu, 0, ID_DEBUG_COPY_VALUE, _T("Copy Value")); POINT pt = { mousex, mousey }; ::ClientToScreen(m_hwndDisasmViewer, &pt); @@ -317,7 +317,7 @@ void DisasmView_CopyToClipboard(WPARAM command) return; WORD value; - if (command == ID_DISASM_COPY_ADDRESS) + if (command == ID_DEBUG_COPY_ADDRESS) value = pLineItem->address; else value = pLineItem->value; diff --git a/emulator/Main.h b/emulator/Main.h index 7538939..115f562 100644 --- a/emulator/Main.h +++ b/emulator/Main.h @@ -202,6 +202,8 @@ void Settings_SetDebugMemoryMode(WORD mode); WORD Settings_GetDebugMemoryMode(); void Settings_SetDebugMemoryAddress(WORD address); WORD Settings_GetDebugMemoryAddress(); +void Settings_SetDebugMemoryBase(WORD address); +WORD Settings_GetDebugMemoryBase(); BOOL Settings_GetDebugMemoryByte(); void Settings_SetDebugMemoryByte(BOOL flag); void Settings_SetAutostart(BOOL flag); diff --git a/emulator/MainWindow.cpp b/emulator/MainWindow.cpp index 50eef6e..b636f95 100644 --- a/emulator/MainWindow.cpp +++ b/emulator/MainWindow.cpp @@ -1394,7 +1394,7 @@ void MainWindow_DoFileScreenshotToClipboard() HGLOBAL hDIB = ScreenView_GetScreenshotAsDIB(screenshotMode); if (hDIB != NULL) { - ::OpenClipboard(0); + ::OpenClipboard(g_hwnd); ::EmptyClipboard(); ::SetClipboardData(CF_DIB, hDIB); ::CloseClipboard(); @@ -1438,7 +1438,7 @@ void MainWindow_DoFileScreenToClipboard() GlobalUnlock(hMem); // Put text to Clipboard - OpenClipboard(0); + OpenClipboard(g_hwnd); EmptyClipboard(); SetClipboardData(CF_UNICODETEXT, hMem); CloseClipboard(); diff --git a/emulator/MemoryView.cpp b/emulator/MemoryView.cpp index e934043..eed7f81 100644 --- a/emulator/MemoryView.cpp +++ b/emulator/MemoryView.cpp @@ -12,6 +12,7 @@ UKNCBTL. If not, see . */ #include "stdafx.h" #include +#include #include "Main.h" #include "Views.h" #include "ToolWindow.h" @@ -25,27 +26,34 @@ UKNCBTL. If not, see . */ HWND g_hwndMemory = (HWND) INVALID_HANDLE_VALUE; // Memory view window handler WNDPROC m_wndprocMemoryToolWindow = NULL; // Old window proc address of the ToolWindow -int m_cyLineMemory = 0; // Line height in pixels -int m_nPageSize = 0; // Page size in lines - HWND m_hwndMemoryViewer = (HWND) INVALID_HANDLE_VALUE; HWND m_hwndMemoryToolbar = (HWND) INVALID_HANDLE_VALUE; -void MemoryView_OnDraw(HDC hdc); +int m_cxChar = 0; +int m_cyLineMemory = 0; // Line height in pixels +int m_nPageSize = 100; // Page size in lines + +int m_Mode = MEMMODE_ROM; // See MemoryViewMode enum +WORD m_wBaseAddress = 0xFFFF; +WORD m_wCurrentAddress = 0xFFFF; +BOOL m_okMemoryByteMode = FALSE; + +void MemoryView_AdjustWindowLayout(); BOOL MemoryView_OnKeyDown(WPARAM vkey, LPARAM lParam); +void MemoryView_OnLButtonDown(int mousex, int mousey); +void MemoryView_OnRButtonDown(int mousex, int mousey); BOOL MemoryView_OnMouseWheel(WPARAM wParam, LPARAM lParam); -BOOL MemoryView_OnVScroll(WPARAM wParam, LPARAM lParam); -void MemoryView_ScrollTo(WORD wAddress); -void MemoryView_Scroll(int nDeltaLines); -void MemoryView_UpdateScrollPos(); +BOOL MemoryView_OnVScroll(WORD scrollcmd, WORD scrollpos); +void MemoryView_CopyValueToClipboard(WPARAM command); +void MemoryView_GotoAddress(WORD wAddress); +void MemoryView_ScrollTo(WORD wBaseAddress); void MemoryView_UpdateWindowText(); -void MemoryView_UpdateToolbar(); LPCTSTR MemoryView_GetMemoryModeName(); -void MemoryView_AdjustWindowLayout(); - -int m_Mode = MEMMODE_ROM; // See MemoryViewMode enum -WORD m_wBaseAddress = 0; -BOOL m_okMemoryByteMode = FALSE; +void MemoryView_UpdateScrollPos(); +void MemoryView_UpdateToolbar(); +void MemoryView_GetCurrentValueRect(LPRECT pRect, int cxChar, int cyLine); +WORD MemoryView_GetWordFromMemory(WORD address, BOOL& okValid, int& addrtype, WORD& wChanged); +void MemoryView_OnDraw(HDC hdc); ////////////////////////////////////////////////////////////////////// @@ -138,7 +146,9 @@ void MemoryView_Create(HWND hwndParent, int x, int y, int width, int height) SendMessage(m_hwndMemoryToolbar, TB_ADDBUTTONS, (WPARAM) sizeof(buttons) / sizeof(TBBUTTON), (LPARAM) &buttons); - MemoryView_ScrollTo(Settings_GetDebugMemoryAddress()); + MemoryView_ScrollTo(Settings_GetDebugMemoryBase()); + MemoryView_GotoAddress(Settings_GetDebugMemoryAddress()); + MemoryView_UpdateToolbar(); } @@ -176,7 +186,12 @@ LRESULT CALLBACK MemoryViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, switch (message) { case WM_COMMAND: - ::PostMessage(g_hwnd, WM_COMMAND, wParam, lParam); + if (wParam == ID_DEBUG_COPY_VALUE || wParam == ID_DEBUG_COPY_ADDRESS) // Copy command from context menu + MemoryView_CopyValueToClipboard(wParam); + else if (wParam == ID_DEBUG_GOTO_ADDRESS) // "Go to Address" from context menu + MemoryView_SelectAddress(); + else + ::PostMessage(g_hwnd, WM_COMMAND, wParam, lParam); break; case WM_PAINT: { @@ -189,15 +204,17 @@ LRESULT CALLBACK MemoryViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, } break; case WM_LBUTTONDOWN: + MemoryView_OnLButtonDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + break; case WM_RBUTTONDOWN: - ::SetFocus(hWnd); + MemoryView_OnRButtonDown(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); break; case WM_KEYDOWN: return (LRESULT) MemoryView_OnKeyDown(wParam, lParam); case WM_MOUSEWHEEL: return (LRESULT) MemoryView_OnMouseWheel(wParam, lParam); case WM_VSCROLL: - return (LRESULT) MemoryView_OnVScroll(wParam, lParam); + return (LRESULT) MemoryView_OnVScroll(LOWORD(wParam), HIWORD(wParam)); case WM_SETFOCUS: case WM_KILLFOCUS: ::InvalidateRect(hWnd, NULL, TRUE); @@ -208,147 +225,138 @@ LRESULT CALLBACK MemoryViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, return (LRESULT)FALSE; } -void MemoryView_OnDraw(HDC hdc) +// Returns even address 0-65534, or -1 if out of area +int MemoryView_GetAddressByPoint(int mousex, int mousey) { - ASSERT(g_pBoard != NULL); + int line = mousey / m_cyLineMemory - 1; + if (line < 0) return -1; + else if (line >= m_nPageSize) return -1; + int pos = (mousex - 12 * m_cxChar - m_cxChar / 2) / (m_cxChar * 7); + if (pos < 0) return -1; + else if (pos > 7) return -1; + + return (WORD)(m_wBaseAddress + line * 16 + pos * 2); +} - HFONT hFont = CreateMonospacedFont(); - HGDIOBJ hOldFont = SelectObject(hdc, hFont); - int cxChar, cyLine; GetFontWidthAndHeight(hdc, &cxChar, &cyLine); - COLORREF colorText = Settings_GetColor(ColorDebugText); - COLORREF colorChanged = Settings_GetColor(ColorDebugValueChanged); - COLORREF colorMemoryRom = Settings_GetColor(ColorDebugMemoryRom); - COLORREF colorMemoryIO = Settings_GetColor(ColorDebugMemoryIO); - COLORREF colorMemoryNA = Settings_GetColor(ColorDebugMemoryNA); - COLORREF colorOld = SetTextColor(hdc, colorText); - COLORREF colorBkOld = SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); +BOOL MemoryView_OnKeyDown(WPARAM vkey, LPARAM /*lParam*/) +{ + switch (vkey) + { + case VK_ESCAPE: + ConsoleView_Activate(); + break; + case VK_HOME: + MemoryView_GotoAddress(0); + break; + case VK_LEFT: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress - 2)); + break; + case VK_RIGHT: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress + 2)); + break; + case VK_UP: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress - 16)); + break; + case VK_DOWN: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress + 16)); + break; + case VK_SPACE: + MemoryView_SetViewMode((MemoryViewMode)((m_Mode == MEMMODE_LAST) ? 0 : m_Mode + 1)); + break; + case VK_PRIOR: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress - m_nPageSize * 16)); + break; + case VK_NEXT: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress + m_nPageSize * 16)); + break; + case 0x47: // G - Go To Address + MemoryView_SelectAddress(); + break; + case 0x42: // B - change byte/word mode + case 0x57: // W + MemoryView_SwitchWordByte(); + break; + default: + return TRUE; + } + return FALSE; +} - m_cyLineMemory = cyLine; +void MemoryView_OnLButtonDown(int mousex, int mousey) +{ + ::SetFocus(m_hwndMemoryViewer); - TCHAR buffer[7]; - const TCHAR* ADDRESS_LINE = _T(" addr 0 2 4 6 10 12 14 16"); - TextOut(hdc, cxChar * 5, 0, ADDRESS_LINE, (int) _tcslen(ADDRESS_LINE)); + int addr = MemoryView_GetAddressByPoint(mousex, mousey); + if (addr >= 0) + MemoryView_GotoAddress((WORD)addr); +} - RECT rcClip; - GetClipBox(hdc, &rcClip); - RECT rcClient; - GetClientRect(m_hwndMemoryViewer, &rcClient); - m_nPageSize = rcClient.bottom / cyLine - 1; +void MemoryView_OnRButtonDown(int mousex, int mousey) +{ + ::SetFocus(m_hwndMemoryViewer); - WORD address = m_wBaseAddress; - int y = 1 * cyLine; - for (;;) // Draw lines - { - DrawOctalValue(hdc, 5 * cxChar, y, address); + int addr = MemoryView_GetAddressByPoint(mousex, mousey); + if (addr >= 0) + MemoryView_GotoAddress((WORD)addr); - int x = 13 * cxChar; - TCHAR wchars[16]; - for (int j = 0; j < 8; j++) // Draw words as octal value - { - // Get word from memory - WORD word = 0; - int addrtype = ADDRTYPE_NONE; - BOOL okValid = TRUE; - BOOL okHalt = FALSE; - WORD wChanged = 0; - switch (m_Mode) - { - case MEMMODE_RAM0: - case MEMMODE_RAM1: - case MEMMODE_RAM2: - word = g_pBoard->GetRAMWord(m_Mode, address); - wChanged = Emulator_GetChangeRamStatus(m_Mode, address); - break; - case MEMMODE_ROM: // ROM - only 32 Kbytes - if (address < 0100000) - okValid = FALSE; - else - { - addrtype = ADDRTYPE_ROM; - word = g_pBoard->GetROMWord(address - 0100000); - } - break; - case MEMMODE_CPU: - okHalt = g_pBoard->GetCPU()->IsHaltMode(); - word = g_pBoard->GetCPUMemoryController()->GetWordView(address, okHalt, FALSE, &addrtype); - okValid = (addrtype != ADDRTYPE_IO) && (addrtype != ADDRTYPE_DENY); - wChanged = Emulator_GetChangeRamStatus(ADDRTYPE_RAM12, address); - break; - case MEMMODE_PPU: - okHalt = g_pBoard->GetPPU()->IsHaltMode(); - word = g_pBoard->GetPPUMemoryController()->GetWordView(address, okHalt, FALSE, &addrtype); - okValid = (addrtype != ADDRTYPE_IO) && (addrtype != ADDRTYPE_DENY); - if (address < 0100000) - wChanged = Emulator_GetChangeRamStatus(ADDRTYPE_RAM0, address); - break; - } + RECT rcValue; + MemoryView_GetCurrentValueRect(&rcValue, m_cxChar, m_cyLineMemory); - if (okValid) - { - if (addrtype == ADDRTYPE_ROM) - ::SetTextColor(hdc, colorMemoryRom); - else - ::SetTextColor(hdc, (wChanged != 0) ? colorChanged : colorText); - if (m_okMemoryByteMode) - { - PrintOctalValue(buffer, (word & 0xff)); - TextOut(hdc, x, y, buffer + 3, 3); - PrintOctalValue(buffer, (word >> 8)); - TextOut(hdc, x + 3 * cxChar + 3, y, buffer + 3, 3); - } - else - DrawOctalValue(hdc, x, y, word); - } - else // !okValid - { - if (addrtype == ADDRTYPE_IO) - { - ::SetTextColor(hdc, colorMemoryIO); - TextOut(hdc, x, y, _T(" IO"), 4); - } - else - { - ::SetTextColor(hdc, colorMemoryNA); - TextOut(hdc, x, y, _T(" NA"), 4); - } - } + HMENU hMenu = ::CreatePopupMenu(); + ::AppendMenu(hMenu, 0, ID_DEBUG_COPY_VALUE, _T("Copy Value")); + ::AppendMenu(hMenu, 0, ID_DEBUG_COPY_ADDRESS, _T("Copy Address")); + ::AppendMenu(hMenu, MF_SEPARATOR, 0, NULL); + ::AppendMenu(hMenu, 0, ID_DEBUG_GOTO_ADDRESS, _T("Go to Address...")); - // Prepare characters to draw at right - BYTE ch1 = LOBYTE(word); - TCHAR wch1 = Translate_KOI8R(ch1); - if (ch1 < 32) wch1 = _T('·'); - wchars[j * 2] = wch1; - BYTE ch2 = HIBYTE(word); - TCHAR wch2 = Translate_KOI8R(ch2); - if (ch2 < 32) wch2 = _T('·'); - wchars[j * 2 + 1] = wch2; + POINT pt = { rcValue.left, rcValue.bottom }; + ::ClientToScreen(m_hwndMemoryViewer, &pt); + ::TrackPopupMenu(hMenu, 0, pt.x, pt.y, 0, m_hwndMemoryViewer, NULL); - address += 2; - x += 7 * cxChar; - } - ::SetTextColor(hdc, colorText); + VERIFY(::DestroyMenu(hMenu)); +} - // Draw characters at right - int xch = x + cxChar; - TextOut(hdc, xch, y, wchars, 16); +BOOL MemoryView_OnMouseWheel(WPARAM wParam, LPARAM /*lParam*/) +{ + short zDelta = GET_WHEEL_DELTA_WPARAM(wParam); - y += cyLine; - if (y > rcClip.bottom) break; - } + int nDelta = zDelta / 120; + if (nDelta > 5) nDelta = 5; + if (nDelta < -5) nDelta = -5; - SetTextColor(hdc, colorOld); - SetBkColor(hdc, colorBkOld); - SelectObject(hdc, hOldFont); - VERIFY(DeleteObject(hFont)); + MemoryView_GotoAddress((WORD)(m_wCurrentAddress - nDelta * 2 * 16)); - if (::GetFocus() == m_hwndMemoryViewer) + return FALSE; +} + +BOOL MemoryView_OnVScroll(WORD scrollcmd, WORD scrollpos) +{ + switch (scrollcmd) { - RECT rcFocus = rcClient; - rcFocus.left += cxChar * 5 - 1; - rcFocus.top += cyLine - 1; - rcFocus.right = cxChar * (66 + 22); - DrawFocusRect(hdc, &rcFocus); + case SB_LINEDOWN: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress + 16)); + break; + case SB_LINEUP: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress - 16)); + break; + case SB_PAGEDOWN: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress + m_nPageSize * 16)); + break; + case SB_PAGEUP: + MemoryView_GotoAddress((WORD)(m_wCurrentAddress - m_nPageSize * 16)); + break; + case SB_THUMBPOSITION: + MemoryView_GotoAddress((WORD)(scrollpos * 16)); + break; } + + return FALSE; +} + +void MemoryView_UpdateWindowText() +{ + TCHAR buffer[64]; + _stprintf_s(buffer, 64, _T("Memory - %s - %06o"), MemoryView_GetMemoryModeName(), m_wCurrentAddress); + ::SetWindowText(g_hwndMemory, buffer); } void MemoryView_UpdateToolbar() @@ -404,6 +412,81 @@ LPCTSTR MemoryView_GetMemoryModeName() } } +void MemoryView_GotoAddress(WORD wAddress) +{ + m_wCurrentAddress = wAddress & ((WORD)~1); // Address should be even + Settings_SetDebugMemoryAddress(m_wCurrentAddress); + + int addroffset = wAddress - m_wBaseAddress; + if (addroffset < 0) + { + WORD baseaddr = (m_wCurrentAddress & 0xFFF0); // Base address should be 16-byte aligned + MemoryView_ScrollTo(baseaddr); + } + else if (addroffset >= m_nPageSize * 16) + { + WORD baseaddr = (WORD)((m_wCurrentAddress & 0xFFF0) - (m_nPageSize - 1) * 16); + MemoryView_ScrollTo(baseaddr); + } + + MemoryView_UpdateWindowText(); +} + +// Scroll window to given base address +void MemoryView_ScrollTo(WORD wBaseAddress) +{ + if (wBaseAddress == m_wBaseAddress) + return; + + m_wBaseAddress = wBaseAddress; + Settings_SetDebugMemoryBase(wBaseAddress); + + InvalidateRect(m_hwndMemoryViewer, NULL, TRUE); + + MemoryView_UpdateScrollPos(); +} + +void MemoryView_CopyValueToClipboard(WPARAM command) +{ + WORD address = m_wCurrentAddress; + WORD value; + + if (command == ID_DEBUG_COPY_ADDRESS) + { + value = address; + } + else + { + //TODO: Get word from memory + // Get word from memory + int addrtype; + BOOL okValid; + WORD wChanged; + value = MemoryView_GetWordFromMemory(address, okValid, addrtype, wChanged); + + if (!okValid) + { + AlertWarning(_T("Failed to get value: invalid memory type.")); + return; + } + } + + TCHAR buffer[7]; + PrintOctalValue(buffer, value); + + // Prepare global memory object for the text + HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, sizeof(buffer)); + LPTSTR lptstrCopy = (LPTSTR) ::GlobalLock(hglbCopy); + memcpy(lptstrCopy, buffer, sizeof(buffer)); + ::GlobalUnlock(hglbCopy); + + // Send the text to the Clipboard + ::OpenClipboard(g_hwnd); + ::EmptyClipboard(); + ::SetClipboardData(CF_UNICODETEXT, hglbCopy); + ::CloseClipboard(); +} + void MemoryView_SwitchWordByte() { m_okMemoryByteMode = !m_okMemoryByteMode; @@ -414,134 +497,190 @@ void MemoryView_SwitchWordByte() void MemoryView_SelectAddress() { - WORD value = m_wBaseAddress; + WORD value = m_wCurrentAddress; if (InputBoxOctal(m_hwndMemoryViewer, _T("Go To Address"), &value)) - MemoryView_ScrollTo(value); + MemoryView_GotoAddress(value); + ::SetFocus(m_hwndMemoryViewer); } -void MemoryView_UpdateWindowText() +void MemoryView_UpdateScrollPos() { - TCHAR buffer[64]; - _stprintf_s(buffer, 64, _T("Memory - %s"), MemoryView_GetMemoryModeName()); - ::SetWindowText(g_hwndMemory, buffer); + SCROLLINFO si; + ZeroMemory(&si, sizeof(si)); + si.cbSize = sizeof(si); + si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; + si.nPage = m_nPageSize; + si.nPos = m_wBaseAddress / 16; + si.nMin = 0; + si.nMax = 0x10000 / 16 - 1; + SetScrollInfo(m_hwndMemoryViewer, SB_VERT, &si, TRUE); } -BOOL MemoryView_OnKeyDown(WPARAM vkey, LPARAM /*lParam*/) +void MemoryView_GetCurrentValueRect(LPRECT pRect, int cxChar, int cyLine) { - switch (vkey) + ASSERT(pRect != NULL); + + int addroffset = m_wCurrentAddress - m_wBaseAddress; + int line = addroffset / 16; + int pos = addroffset & 15; + + pRect->left = cxChar * (13 + 7 * (pos / 2)) - cxChar / 2; + pRect->right = pRect->left + cxChar * 7; + pRect->top = (line + 1) * cyLine - 1; + pRect->bottom = pRect->top + cyLine + 1; +} + +WORD MemoryView_GetWordFromMemory(WORD address, BOOL& okValid, int& addrtype, WORD& wChanged) +{ + WORD word = 0; + okValid = TRUE; + addrtype = ADDRTYPE_NONE; + wChanged = 0; + BOOL okHalt = FALSE; + + switch (m_Mode) { - case VK_ESCAPE: - ConsoleView_Activate(); - break; - case VK_HOME: - MemoryView_ScrollTo(0); - break; - case VK_LEFT: - MemoryView_Scroll(-2); - break; - case VK_RIGHT: - MemoryView_Scroll(2); - break; - case VK_UP: - MemoryView_Scroll(-16); - break; - case VK_DOWN: - MemoryView_Scroll(16); - break; - case VK_SPACE: - MemoryView_SetViewMode((MemoryViewMode)((m_Mode == MEMMODE_LAST) ? 0 : m_Mode + 1)); + case MEMMODE_RAM0: + case MEMMODE_RAM1: + case MEMMODE_RAM2: + word = g_pBoard->GetRAMWord(m_Mode, address); + wChanged = Emulator_GetChangeRamStatus(m_Mode, address); break; - case VK_PRIOR: - MemoryView_Scroll(-m_nPageSize * 16); + case MEMMODE_ROM: // ROM - only 32 Kbytes + if (address < 0100000) + okValid = FALSE; + else + { + addrtype = ADDRTYPE_ROM; + word = g_pBoard->GetROMWord(address - 0100000); + } break; - case VK_NEXT: - MemoryView_Scroll(m_nPageSize * 16); + case MEMMODE_CPU: + okHalt = g_pBoard->GetCPU()->IsHaltMode(); + word = g_pBoard->GetCPUMemoryController()->GetWordView(address, okHalt, FALSE, &addrtype); + okValid = (addrtype != ADDRTYPE_IO) && (addrtype != ADDRTYPE_DENY); + wChanged = Emulator_GetChangeRamStatus(ADDRTYPE_RAM12, address); break; - case 0x47: // G - Go To Address - MemoryView_SelectAddress(); + case MEMMODE_PPU: + okHalt = g_pBoard->GetPPU()->IsHaltMode(); + word = g_pBoard->GetPPUMemoryController()->GetWordView(address, okHalt, FALSE, &addrtype); + okValid = (addrtype != ADDRTYPE_IO) && (addrtype != ADDRTYPE_DENY); + if (address < 0100000) + wChanged = Emulator_GetChangeRamStatus(ADDRTYPE_RAM0, address); break; - case 0x42: // B - change byte/word mode - case 0x57: // W - MemoryView_SwitchWordByte(); - break; - default: - return TRUE; } - return FALSE; + + return word; } -BOOL MemoryView_OnMouseWheel(WPARAM wParam, LPARAM /*lParam*/) +void MemoryView_OnDraw(HDC hdc) { - short zDelta = GET_WHEEL_DELTA_WPARAM(wParam); + ASSERT(g_pBoard != NULL); - int nDelta = zDelta / 120; - if (nDelta > 5) nDelta = 5; - if (nDelta < -5) nDelta = -5; + HFONT hFont = CreateMonospacedFont(); + HGDIOBJ hOldFont = SelectObject(hdc, hFont); + int cxChar, cyLine; GetFontWidthAndHeight(hdc, &cxChar, &cyLine); + COLORREF colorText = Settings_GetColor(ColorDebugText); + COLORREF colorChanged = Settings_GetColor(ColorDebugValueChanged); + COLORREF colorMemoryRom = Settings_GetColor(ColorDebugMemoryRom); + COLORREF colorMemoryIO = Settings_GetColor(ColorDebugMemoryIO); + COLORREF colorMemoryNA = Settings_GetColor(ColorDebugMemoryNA); + COLORREF colorOld = SetTextColor(hdc, colorText); + COLORREF colorBkOld = SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); + + m_cxChar = cxChar; + m_cyLineMemory = cyLine; - MemoryView_Scroll(-nDelta * 2 * 16); + TCHAR buffer[7]; + const TCHAR* ADDRESS_LINE = _T(" addr 0 2 4 6 10 12 14 16"); + TextOut(hdc, cxChar * 5, 0, ADDRESS_LINE, (int)_tcslen(ADDRESS_LINE)); - return FALSE; -} + RECT rcClip; + GetClipBox(hdc, &rcClip); + RECT rcClient; + GetClientRect(m_hwndMemoryViewer, &rcClient); + m_nPageSize = rcClient.bottom / cyLine - 1; -BOOL MemoryView_OnVScroll(WPARAM wParam, LPARAM /*lParam*/) -{ - WORD scrollpos = HIWORD(wParam); - WORD scrollcmd = LOWORD(wParam); - switch (scrollcmd) + WORD address = m_wBaseAddress; + int y = 1 * cyLine; + for (;;) // Draw lines { - case SB_LINEDOWN: - MemoryView_Scroll(16); - break; - case SB_LINEUP: - MemoryView_Scroll(-16); - break; - case SB_PAGEDOWN: - MemoryView_Scroll(m_nPageSize * 16); - break; - case SB_PAGEUP: - MemoryView_Scroll(-m_nPageSize * 16); - break; - case SB_THUMBPOSITION: - MemoryView_ScrollTo(scrollpos * 16); - break; - } + DrawOctalValue(hdc, 5 * cxChar, y, address); - return FALSE; -} + int x = 13 * cxChar; + TCHAR wchars[16]; + for (int j = 0; j < 8; j++) // Draw words as octal value + { + // Get word from memory + int addrtype; + BOOL okValid; + WORD wChanged; + WORD word = MemoryView_GetWordFromMemory(address, okValid, addrtype, wChanged); -// Scroll window to given base address -void MemoryView_ScrollTo(WORD wAddress) -{ - m_wBaseAddress = wAddress & ((WORD)~1); - Settings_SetDebugMemoryAddress(m_wBaseAddress); + if (okValid) + { + if (addrtype == ADDRTYPE_ROM) + ::SetTextColor(hdc, colorMemoryRom); + else + ::SetTextColor(hdc, (wChanged != 0) ? colorChanged : colorText); + if (m_okMemoryByteMode) + { + PrintOctalValue(buffer, (word & 0xff)); + TextOut(hdc, x, y, buffer + 3, 3); + PrintOctalValue(buffer, (word >> 8)); + TextOut(hdc, x + 3 * cxChar + 3, y, buffer + 3, 3); + } + else + DrawOctalValue(hdc, x, y, word); + } + else // !okValid + { + if (addrtype == ADDRTYPE_IO) + { + ::SetTextColor(hdc, colorMemoryIO); + TextOut(hdc, x, y, _T(" IO"), 4); + } + else + { + ::SetTextColor(hdc, colorMemoryNA); + TextOut(hdc, x, y, _T(" NA"), 4); + } + } - InvalidateRect(m_hwndMemoryViewer, NULL, TRUE); + // Prepare characters to draw at right + BYTE ch1 = LOBYTE(word); + TCHAR wch1 = Translate_KOI8R(ch1); + if (ch1 < 32) wch1 = _T('·'); + wchars[j * 2] = wch1; + BYTE ch2 = HIBYTE(word); + TCHAR wch2 = Translate_KOI8R(ch2); + if (ch2 < 32) wch2 = _T('·'); + wchars[j * 2 + 1] = wch2; - MemoryView_UpdateScrollPos(); -} -// Scroll window on given lines forward or backward -void MemoryView_Scroll(int nDelta) -{ - if (nDelta == 0) return; + address += 2; + x += 7 * cxChar; + } + ::SetTextColor(hdc, colorText); - m_wBaseAddress = (WORD)(m_wBaseAddress + nDelta) & ((WORD)~1); - Settings_SetDebugMemoryAddress(m_wBaseAddress); + // Draw characters at right + int xch = x + cxChar; + TextOut(hdc, xch, y, wchars, 16); - InvalidateRect(m_hwndMemoryViewer, NULL, TRUE); + y += cyLine; + if (y > rcClip.bottom) break; + } - MemoryView_UpdateScrollPos(); -} -void MemoryView_UpdateScrollPos() -{ - SCROLLINFO si; - ZeroMemory(&si, sizeof(si)); - si.cbSize = sizeof(si); - si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE; - si.nPage = m_nPageSize; - si.nPos = m_wBaseAddress / 16; - si.nMin = 0; - si.nMax = 0x10000 / 16 - 1; - SetScrollInfo(m_hwndMemoryViewer, SB_VERT, &si, TRUE); + SetTextColor(hdc, colorOld); + SetBkColor(hdc, colorBkOld); + SelectObject(hdc, hOldFont); + VERIFY(::DeleteObject(hFont)); + + if (::GetFocus() == m_hwndMemoryViewer) + { + RECT rcFocus; + MemoryView_GetCurrentValueRect(&rcFocus, cxChar, cyLine); + DrawFocusRect(hdc, &rcFocus); + } } diff --git a/emulator/Settings.cpp b/emulator/Settings.cpp index 9bd17ef..139bdd7 100644 --- a/emulator/Settings.cpp +++ b/emulator/Settings.cpp @@ -350,6 +350,7 @@ SETTINGS_GETSET_DWORD(DebugCpuPpu, _T("DebugCpuPpu"), BOOL, FALSE); SETTINGS_GETSET_DWORD(DebugMemoryMode, _T("DebugMemoryMode"), WORD, 3); SETTINGS_GETSET_DWORD(DebugMemoryAddress, _T("DebugMemoryAddress"), WORD, 0); +SETTINGS_GETSET_DWORD(DebugMemoryBase, _T("DebugMemoryBase"), WORD, 0); SETTINGS_GETSET_DWORD(DebugMemoryByte, _T("DebugMemoryByte"), BOOL, FALSE); SETTINGS_GETSET_DWORD(Autostart, _T("Autostart"), BOOL, FALSE); diff --git a/emulator/res/Resource.h b/emulator/res/Resource.h index 646fa77..63a94f3 100644 --- a/emulator/res/Resource.h +++ b/emulator/res/Resource.h @@ -132,8 +132,9 @@ #define ID_DEBUG_CLEARCONSOLE 32896 #define ID_DEBUG_DELETEALLBREAKPTS 32897 #define ID_DEBUG_SUBTITLES 32898 -#define ID_DISASM_COPY_ADDRESS 32899 -#define ID_DISASM_COPY_VALUE 32900 +#define ID_DEBUG_COPY_ADDRESS 32899 +#define ID_DEBUG_COPY_VALUE 32900 +#define ID_DEBUG_GOTO_ADDRESS 32901 #define IDC_STATIC -1 // Next default values for new objects