/* This file is part of BKBTL.
BKBTL is free software: you can redistribute it and/or modify it under the terms
of the GNU Lesser General Public License as published by the Free Software Foundation,
either version 3 of the License, or (at your option) any later version.
BKBTL 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
BKBTL. If not, see . */
// MemoryMapView.cpp
#include "stdafx.h"
#include
#include "Main.h"
#include "Views.h"
#include "ToolWindow.h"
#include "Emulator.h"
//////////////////////////////////////////////////////////////////////
HWND g_hwndMemoryMap = (HWND)INVALID_HANDLE_VALUE; // MemoryMap view window handler
WNDPROC m_wndprocMemoryMapToolWindow = NULL; // Old window proc address of the ToolWindow
HWND m_hwndMemoryMapViewer = (HWND)INVALID_HANDLE_VALUE;
HDRAWDIB m_hMemoryMapDrawDib = NULL;
BITMAPINFO m_bmpinfoMemoryMap;
HBITMAP m_hMemoryMapBitmap = NULL;
DWORD * m_pMemoryMap_bits = NULL;
const int m_nMemoryMap_ViewCX = 256;
const int m_nMemoryMap_ViewCY = 256;
int m_nMemoryMap_xpos = 0;
int m_nMemoryMap_ypos = 0;
int m_nMemoryMap_scale = 1;
void MemoryMapView_OnDraw(HDC hdc);
BOOL MemoryMapView_OnKeyDown(WPARAM vkey, LPARAM lParam);
BOOL MemoryMapView_OnVScroll(WPARAM wParam, LPARAM lParam);
BOOL MemoryMapView_OnHScroll(WPARAM wParam, LPARAM lParam);
BOOL MemoryMapView_OnMouseWheel(WPARAM wParam, LPARAM lParam);
void MemoryMapView_InitBitmap();
void MemoryMapView_DoneBitmap();
void MemoryMapView_PrepareBitmap();
void MemoryMapView_Zoom(BOOL inout);
void MemoryMapView_Scroll(int dx, int dy);
void MemoryMapView_UpdateScrollPos();
//////////////////////////////////////////////////////////////////////
void MemoryMapView_RegisterClass()
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = MemoryMapViewViewerWndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = g_hInst;
wcex.hIcon = NULL;
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = CLASSNAME_MEMORYMAPVIEW;
wcex.hIconSm = NULL;
RegisterClassEx(&wcex);
}
void MemoryMapView_Create(HWND hwndParent, int x, int y)
{
int cxScroll = ::GetSystemMetrics(SM_CXVSCROLL);
int cyScroll = ::GetSystemMetrics(SM_CYHSCROLL);
int cyCaption = TOOLWINDOW_CAPTION_HEIGHT;
int width = m_nMemoryMap_ViewCX + cxScroll;
int height = m_nMemoryMap_ViewCY + cyScroll + cyCaption;
g_hwndMemoryMap = CreateWindow(
CLASSNAME_TOOLWINDOW, _T("Memory Map"),
WS_CHILD | WS_VISIBLE,
x, y, width, height,
hwndParent, NULL, g_hInst, NULL);
// ToolWindow subclassing
m_wndprocMemoryMapToolWindow = (WNDPROC)LongToPtr( SetWindowLongPtr(
g_hwndMemoryMap, GWLP_WNDPROC, PtrToLong(MemoryMapViewWndProc)) );
RECT rcClient; GetClientRect(g_hwndMemoryMap, &rcClient);
m_hwndMemoryMapViewer = CreateWindow(
CLASSNAME_MEMORYMAPVIEW, NULL,
WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_TABSTOP,
0, 0, rcClient.right, rcClient.bottom,
g_hwndMemoryMap, NULL, g_hInst, NULL);
MemoryMapView_InitBitmap();
MemoryMapView_UpdateScrollPos();
}
void MemoryMapView_InitBitmap()
{
m_hMemoryMapDrawDib = DrawDibOpen();
HDC hdc = ::GetDC(g_hwnd);
m_bmpinfoMemoryMap.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
m_bmpinfoMemoryMap.bmiHeader.biWidth = 256;
m_bmpinfoMemoryMap.bmiHeader.biHeight = 256;
m_bmpinfoMemoryMap.bmiHeader.biPlanes = 1;
m_bmpinfoMemoryMap.bmiHeader.biBitCount = 32;
m_bmpinfoMemoryMap.bmiHeader.biCompression = BI_RGB;
m_bmpinfoMemoryMap.bmiHeader.biSizeImage = 0;
m_bmpinfoMemoryMap.bmiHeader.biXPelsPerMeter = 0;
m_bmpinfoMemoryMap.bmiHeader.biYPelsPerMeter = 0;
m_bmpinfoMemoryMap.bmiHeader.biClrUsed = 0;
m_bmpinfoMemoryMap.bmiHeader.biClrImportant = 0;
m_hMemoryMapBitmap = CreateDIBSection( hdc, &m_bmpinfoMemoryMap, DIB_RGB_COLORS, (void **)&m_pMemoryMap_bits, NULL, 0 );
VERIFY(::ReleaseDC(g_hwnd, hdc));
}
void MemoryMapView_DoneBitmap()
{
if (m_hMemoryMapBitmap != NULL)
{
VERIFY(::DeleteObject(m_hMemoryMapBitmap)); m_hMemoryMapBitmap = NULL;
}
DrawDibClose( m_hMemoryMapDrawDib );
}
LRESULT CALLBACK MemoryMapViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_SETFOCUS:
::SetFocus(m_hwndMemoryMapViewer);
break;
case WM_DESTROY:
g_hwndMemoryMap = (HWND) INVALID_HANDLE_VALUE; // We are closed! Bye-bye!..
return CallWindowProc(m_wndprocMemoryMapToolWindow, hWnd, message, wParam, lParam);
default:
return CallWindowProc(m_wndprocMemoryMapToolWindow, hWnd, message, wParam, lParam);
}
return (LRESULT)FALSE;
}
LRESULT CALLBACK MemoryMapViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
MemoryMapView_OnDraw(hdc); // Draw memory dump
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
// Free resources
MemoryMapView_DoneBitmap();
return DefWindowProc(hWnd, message, wParam, lParam);
case WM_LBUTTONDOWN:
SetFocus(hWnd);
break;
case WM_KEYDOWN:
return (LRESULT) MemoryMapView_OnKeyDown(wParam, lParam);
case WM_HSCROLL:
return (LRESULT) MemoryMapView_OnHScroll(wParam, lParam);
case WM_VSCROLL:
return (LRESULT) MemoryMapView_OnVScroll(wParam, lParam);
case WM_MOUSEWHEEL:
return (LRESULT) MemoryMapView_OnMouseWheel(wParam, lParam);
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return (LRESULT)FALSE;
}
void MemoryMapView_Zoom(BOOL inout)
{
if (inout)
{
if (m_nMemoryMap_scale >= 40)
return;
m_nMemoryMap_scale += 1;
}
else
{
if (m_nMemoryMap_scale <= 2)
return;
m_nMemoryMap_scale -= 1;
}
InvalidateRect(m_hwndMemoryMapViewer, NULL, FALSE);
MemoryMapView_UpdateScrollPos();
}
void MemoryMapView_ScrollTo(int newxpos, int newypos)
{
int maxxpos = 256 - m_nMemoryMap_ViewCX / m_nMemoryMap_scale;
int maxypos = 256 - m_nMemoryMap_ViewCY / m_nMemoryMap_scale;
if (newxpos < 0) newxpos = 0;
if (newxpos > maxxpos) newxpos = maxxpos;
if (newypos < 0) newypos = 0;
if (newypos > maxypos) newypos = maxypos;
m_nMemoryMap_xpos = newxpos;
m_nMemoryMap_ypos = newypos;
InvalidateRect(m_hwndMemoryMapViewer, NULL, TRUE);
MemoryMapView_UpdateScrollPos();
}
void MemoryMapView_Scroll(int dx, int dy)
{
int newxpos = m_nMemoryMap_xpos + dx;
int newypos = m_nMemoryMap_ypos + dy;
MemoryMapView_ScrollTo(newxpos, newypos);
}
BOOL MemoryMapView_OnMouseWheel(WPARAM wParam, LPARAM /*lParam*/)
{
short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
MemoryMapView_Scroll(0, (zDelta > 0) ? -24 : 24);
return FALSE;
}
BOOL MemoryMapView_OnKeyDown(WPARAM vkey, LPARAM /*lParam*/)
{
switch (vkey)
{
case VK_OEM_MINUS:
MemoryMapView_Zoom(FALSE);
break;
case VK_OEM_PLUS:
MemoryMapView_Zoom(TRUE);
break;
case VK_LEFT:
MemoryMapView_Scroll(-2, 0);
break;
case VK_RIGHT:
MemoryMapView_Scroll(2, 0);
break;
case VK_UP:
MemoryMapView_Scroll(0, -2);
break;
case VK_DOWN:
MemoryMapView_Scroll(0, 2);
break;
default:
return TRUE;
}
return FALSE;
}
BOOL MemoryMapView_OnHScroll(WPARAM wParam, LPARAM /*lParam*/)
{
WORD scrollpos = HIWORD(wParam);
WORD scrollcmd = LOWORD(wParam);
switch (scrollcmd)
{
case SB_LINEDOWN:
MemoryMapView_Scroll(8, 0);
break;
case SB_LINEUP:
MemoryMapView_Scroll(-8, 0);
break;
case SB_PAGEDOWN:
MemoryMapView_Scroll(m_nMemoryMap_ViewCX / m_nMemoryMap_scale, 0);
break;
case SB_PAGEUP:
MemoryMapView_Scroll(-m_nMemoryMap_ViewCX / m_nMemoryMap_scale, 0);
break;
case SB_THUMBPOSITION:
MemoryMapView_ScrollTo(scrollpos, m_nMemoryMap_ypos);
break;
}
return FALSE;
}
BOOL MemoryMapView_OnVScroll(WPARAM wParam, LPARAM /*lParam*/)
{
WORD scrollpos = HIWORD(wParam);
WORD scrollcmd = LOWORD(wParam);
switch (scrollcmd)
{
case SB_LINEDOWN:
MemoryMapView_Scroll(0, 8);
break;
case SB_LINEUP:
MemoryMapView_Scroll(0, -8);
break;
case SB_PAGEDOWN:
MemoryMapView_Scroll(0, m_nMemoryMap_ViewCY / m_nMemoryMap_scale);
break;
case SB_PAGEUP:
MemoryMapView_Scroll(0, -m_nMemoryMap_ViewCY / m_nMemoryMap_scale);
break;
case SB_THUMBPOSITION:
MemoryMapView_ScrollTo(m_nMemoryMap_xpos, scrollpos);
break;
}
return FALSE;
}
void MemoryMapView_OnDraw(HDC hdc)
{
ASSERT(g_pBoard != NULL);
MemoryMapView_PrepareBitmap();
DrawDibDraw(m_hMemoryMapDrawDib, hdc,
-m_nMemoryMap_xpos * m_nMemoryMap_scale, -m_nMemoryMap_ypos * m_nMemoryMap_scale,
256 * m_nMemoryMap_scale, 256 * m_nMemoryMap_scale,
&m_bmpinfoMemoryMap.bmiHeader, m_pMemoryMap_bits, 0, 0,
256, 256,
0);
}
void MemoryMapView_RedrawMap()
{
if (g_hwndMemoryMap == (HWND)INVALID_HANDLE_VALUE) return;
MemoryMapView_PrepareBitmap();
HDC hdc = GetDC(g_hwndMemoryMap);
MemoryMapView_OnDraw(hdc);
VERIFY(::ReleaseDC(g_hwndMemoryMap, hdc));
}
void MemoryMapView_UpdateScrollPos()
{
SCROLLINFO siH;
ZeroMemory(&siH, sizeof(siH));
siH.cbSize = sizeof(siH);
siH.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
siH.nPage = m_nMemoryMap_ViewCX / m_nMemoryMap_scale;
siH.nPos = m_nMemoryMap_xpos;
siH.nMin = 0;
siH.nMax = 256 - 1;
SetScrollInfo(m_hwndMemoryMapViewer, SB_HORZ, &siH, TRUE);
SCROLLINFO siV;
ZeroMemory(&siV, sizeof(siV));
siV.cbSize = sizeof(siV);
siV.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
siV.nPage = m_nMemoryMap_ViewCY / m_nMemoryMap_scale;
siV.nPos = m_nMemoryMap_ypos;
siV.nMin = 0;
siV.nMax = 256 - 1;
SetScrollInfo(m_hwndMemoryMapViewer, SB_VERT, &siV, TRUE);
}
void MemoryMapView_PrepareBitmap()
{
for (int y = 0; y < 256; y += 1)
{
DWORD* pBits = m_pMemoryMap_bits + (256 - 1 - y) * 256;
for (int x = 0; x < 256; x += 2)
{
WORD address = (WORD)(x + y * 256);
int addrtype;
WORD value = g_pBoard->GetWordView(address, FALSE, FALSE, &addrtype);
COLORREF color1, color2;
BYTE val;
switch (addrtype & ADDRTYPE_MASK)
{
case ADDRTYPE_IO:
color1 = color2 = RGB(128, 0, 128);
break;
case ADDRTYPE_DENY:
color1 = color2 = RGB(0, 0, 128);
break;
case ADDRTYPE_ROM:
val = (value & 0xff00) >> 8;
color1 = RGB(192, val, val);
val = value & 0x00ff;
color2 = RGB(192, val, val);
break;
case ADDRTYPE_RAM:
val = (value & 0xff00) >> 8;
color1 = RGB(val, val, val);
val = value & 0x00ff;
color2 = RGB(val, val, val);
break;
default:
color1 = color2 = RGB(0, 0, 0);
break;
}
*pBits = color1;
pBits++;
*pBits = color2;
pBits++;
}
}
}
//////////////////////////////////////////////////////////////////////