rlm@1: // MemoryViewerDlg.cpp : implementation file rlm@1: // rlm@1: rlm@1: #include "stdafx.h" rlm@1: #include "resource.h" rlm@1: #include "MemoryViewerDlg.h" rlm@1: #include "FileDlg.h" rlm@1: #include "MemoryViewerAddressSize.h" rlm@1: #include "Reg.h" rlm@1: #include "WinResUtil.h" rlm@1: #include "VBA.h" rlm@1: rlm@1: #include "../gba/GBAGlobals.h" rlm@1: rlm@1: #define CPUReadByteQuick(addr) \ rlm@1: ::map[(addr)>>24].address[(addr) & ::map[(addr)>>24].mask] rlm@1: #define CPUWriteByteQuick(addr, b) \ rlm@1: ::map[(addr)>>24].address[(addr) & ::map[(addr)>>24].mask] = (b) rlm@1: #define CPUReadHalfWordQuick(addr) \ rlm@1: *((u16 *)&::map[(addr)>>24].address[(addr) & ::map[(addr)>>24].mask]) rlm@1: #define CPUWriteHalfWordQuick(addr, b) \ rlm@1: *((u16 *)&::map[(addr)>>24].address[(addr) & ::map[(addr)>>24].mask]) = (b) rlm@1: #define CPUReadMemoryQuick(addr) \ rlm@1: *((u32 *)&::map[(addr)>>24].address[(addr) & ::map[(addr)>>24].mask]) rlm@1: #define CPUWriteMemoryQuick(addr, b) \ rlm@1: *((u32 *)&::map[(addr)>>24].address[(addr) & ::map[(addr)>>24].mask]) = (b) rlm@1: rlm@1: ///////////////////////////////////////////////////////////////////////////// rlm@1: // GBAMemoryViewer control rlm@1: rlm@1: GBAMemoryViewer::GBAMemoryViewer() rlm@1: : MemoryViewer() rlm@1: { rlm@1: setAddressSize(0); rlm@1: } rlm@1: rlm@1: void GBAMemoryViewer::readData(u32 address, int len, u8 *data) rlm@1: { rlm@1: if (emulating && rom != NULL) rlm@1: { rlm@1: for (int i = 0; i < len; i++) rlm@1: { rlm@1: *data++ = CPUReadByteQuick(address); rlm@1: address++; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: for (int i = 0; i < len; i++) rlm@1: { rlm@1: *data++ = 0; rlm@1: address++; rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void GBAMemoryViewer::editData(u32 address, int size, int mask, u32 value) rlm@1: { rlm@1: u32 oldValue; rlm@1: rlm@1: switch (size) rlm@1: { rlm@1: case 8: rlm@1: oldValue = (CPUReadByteQuick(address) & mask) | value; rlm@1: CPUWriteByteQuick(address, oldValue); rlm@1: break; rlm@1: case 16: rlm@1: oldValue = (CPUReadHalfWordQuick(address) & mask) | value; rlm@1: CPUWriteHalfWordQuick(address, oldValue); rlm@1: break; rlm@1: case 32: rlm@1: oldValue = (CPUReadMemoryQuick(address) & mask) | value; rlm@1: CPUWriteMemoryQuick(address, oldValue); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: ///////////////////////////////////////////////////////////////////////////// rlm@1: // MemoryViewerDlg dialog rlm@1: rlm@1: MemoryViewerDlg::MemoryViewerDlg(CWnd*pParent /*=NULL*/) rlm@1: : ResizeDlg(MemoryViewerDlg::IDD, pParent) rlm@1: { rlm@1: //{{AFX_DATA_INIT(MemoryViewerDlg) rlm@1: m_size = -1; rlm@1: //}}AFX_DATA_INIT rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::DoDataExchange(CDataExchange*pDX) rlm@1: { rlm@1: CDialog::DoDataExchange(pDX); rlm@1: //{{AFX_DATA_MAP(MemoryViewerDlg) rlm@1: DDX_Control(pDX, IDC_CURRENT_ADDRESS, m_current); rlm@1: DDX_Control(pDX, IDC_ADDRESS, m_address); rlm@1: DDX_Control(pDX, IDC_ADDRESSES, m_addresses); rlm@1: DDX_Check(pDX, IDC_AUTO_UPDATE, autoUpdate); rlm@1: DDX_Check(pDX, IDC_DECIMAL_DISPLAY, decimalDisplay); rlm@1: DDX_Check(pDX, IDC_ALIGN, align); rlm@1: DDX_Radio(pDX, IDC_8_BIT, m_size); rlm@1: //}}AFX_DATA_MAP rlm@1: DDX_Control(pDX, IDC_VIEWER, m_viewer); rlm@1: } rlm@1: rlm@1: BEGIN_MESSAGE_MAP(MemoryViewerDlg, CDialog) rlm@1: //{{AFX_MSG_MAP(MemoryViewerDlg) rlm@1: ON_BN_CLICKED(IDC_CLOSE, OnClose) rlm@1: ON_BN_CLICKED(IDC_REFRESH, OnRefresh) rlm@1: ON_BN_CLICKED(IDC_8_BIT, On8Bit) rlm@1: ON_BN_CLICKED(IDC_16_BIT, On16Bit) rlm@1: ON_BN_CLICKED(IDC_32_BIT, On32Bit) rlm@1: ON_BN_CLICKED(IDC_AUTO_UPDATE, OnAutoUpdate) rlm@1: ON_BN_CLICKED(IDC_DECIMAL_DISPLAY, OnDecimalDisplay) rlm@1: ON_BN_CLICKED(IDC_ALIGN, OnAlign) rlm@1: ON_BN_CLICKED(IDC_GO, OnGo) rlm@1: ON_CBN_SELCHANGE(IDC_ADDRESSES, OnSelchangeAddresses) rlm@1: ON_BN_CLICKED(IDC_SAVE, OnSave) rlm@1: ON_BN_CLICKED(IDC_LOAD, OnLoad) rlm@1: //}}AFX_MSG_MAP rlm@1: END_MESSAGE_MAP() rlm@1: rlm@1: ///////////////////////////////////////////////////////////////////////////// rlm@1: // MemoryViewerDlg message handlers rlm@1: rlm@1: BOOL MemoryViewerDlg::OnInitDialog() rlm@1: { rlm@1: CDialog::OnInitDialog(); rlm@1: rlm@1: DIALOG_SIZER_START(sz) rlm@1: DIALOG_SIZER_ENTRY(IDC_VIEWER, DS_SizeX | DS_SizeY) rlm@1: DIALOG_SIZER_ENTRY(IDC_REFRESH, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_CLOSE, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_LOAD, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_SAVE, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_AUTO_UPDATE, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_DECIMAL_DISPLAY, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_ALIGN, DS_MoveY) rlm@1: DIALOG_SIZER_ENTRY(IDC_CURRENT_ADDRESS_LABEL, DS_MoveY | DS_MoveX) rlm@1: DIALOG_SIZER_ENTRY(IDC_CURRENT_ADDRESS, DS_MoveY | DS_MoveX) rlm@1: DIALOG_SIZER_END() rlm@1: SetData(sz, rlm@1: TRUE, rlm@1: HKEY_CURRENT_USER, rlm@1: "Software\\Emulators\\VisualBoyAdvance\\Viewer\\GBDisassembleView", rlm@1: NULL); rlm@1: rlm@1: autoUpdate = regQueryDwordValue("memViewerAutoUpdate", 1); rlm@1: if (autoUpdate) rlm@1: { rlm@1: theApp.winAddUpdateListener(this); rlm@1: } rlm@1: else rlm@1: { rlm@1: theApp.winRemoveUpdateListener(this); rlm@1: } rlm@1: rlm@1: decimalDisplay = regQueryDwordValue("memViewerDecimalDisplay", 0); rlm@1: m_viewer.setDecimal(decimalDisplay ? true : false); rlm@1: align = regQueryDwordValue("memViewerAlign", 0); rlm@1: rlm@1: m_viewer.setDialog(this); rlm@1: m_viewer.ShowScrollBar(SB_VERT, TRUE); rlm@1: m_viewer.EnableScrollBar(SB_VERT, ESB_ENABLE_BOTH); rlm@1: rlm@1: LPCTSTR s[] = { rlm@1: "0x00000000 - BIOS", rlm@1: "0x02000000 - WRAM", rlm@1: "0x03000000 - IRAM", rlm@1: "0x04000000 - I/O", rlm@1: "0x05000000 - PALETTE", rlm@1: "0x06000000 - VRAM", rlm@1: "0x07000000 - OAM", rlm@1: "0x08000000 - ROM" rlm@1: }; rlm@1: rlm@1: for (int i = 0; i < 8; i++) rlm@1: m_addresses.AddString(s[i]); rlm@1: rlm@1: m_addresses.SetCurSel(0); rlm@1: rlm@1: RECT cbSize; rlm@1: int Height; rlm@1: rlm@1: m_addresses.GetClientRect(&cbSize); rlm@1: Height = m_addresses.GetItemHeight(-1); rlm@1: Height += m_addresses.GetItemHeight(0) * (9); rlm@1: rlm@1: // Note: The use of SM_CYEDGE assumes that we're using Windows '95 rlm@1: // Now add on the height of the border of the edit box rlm@1: Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges rlm@1: rlm@1: // The height of the border of the drop-down box rlm@1: Height += GetSystemMetrics(SM_CYEDGE) * 2; // top & bottom edges rlm@1: rlm@1: // now set the size of the window rlm@1: m_addresses.SetWindowPos(NULL, rlm@1: 0, 0, rlm@1: cbSize.right, Height, rlm@1: SWP_NOMOVE | SWP_NOZORDER); rlm@1: rlm@1: m_address.LimitText(8); rlm@1: rlm@1: m_size = regQueryDwordValue("memViewerDataSize", 1); rlm@1: if (m_size < 0 || m_size > 2) rlm@1: m_size = 0; rlm@1: m_viewer.setSize(m_size); rlm@1: UpdateData(FALSE); rlm@1: rlm@1: m_current.SetFont(CFont::FromHandle((HFONT)GetStockObject(SYSTEM_FIXED_FONT))); rlm@1: rlm@1: return TRUE; // return TRUE unless you set the focus to a control rlm@1: // EXCEPTION: OCX Property Pages should return FALSE rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnClose() rlm@1: { rlm@1: theApp.winRemoveUpdateListener(this); rlm@1: rlm@1: DestroyWindow(); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnRefresh() rlm@1: { rlm@1: m_viewer.Invalidate(); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::update() rlm@1: { rlm@1: OnRefresh(); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::On8Bit() rlm@1: { rlm@1: m_viewer.setSize(0); rlm@1: regSetDwordValue("memViewerDataSize", 0); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::On16Bit() rlm@1: { rlm@1: m_viewer.setSize(1); rlm@1: regSetDwordValue("memViewerDataSize", 1); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::On32Bit() rlm@1: { rlm@1: m_viewer.setSize(2); rlm@1: regSetDwordValue("memViewerDataSize", 2); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnAutoUpdate() rlm@1: { rlm@1: autoUpdate = !autoUpdate; rlm@1: if (autoUpdate) rlm@1: { rlm@1: theApp.winAddUpdateListener(this); rlm@1: } rlm@1: else rlm@1: { rlm@1: theApp.winRemoveUpdateListener(this); rlm@1: } rlm@1: regSetDwordValue("memViewerAutoUpdate", autoUpdate); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnDecimalDisplay() rlm@1: { rlm@1: decimalDisplay = !decimalDisplay; rlm@1: m_viewer.setDecimal(decimalDisplay ? true : false); rlm@1: regSetDwordValue("memViewerDecimalDisplay", decimalDisplay); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnAlign() rlm@1: { rlm@1: align = !align; rlm@1: regSetDwordValue("memViewerAlign", align); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnGo() rlm@1: { rlm@1: CString buffer; rlm@1: rlm@1: m_address.GetWindowText(buffer); rlm@1: rlm@1: u32 address; rlm@1: sscanf(buffer, "%x", &address); rlm@1: if (align) rlm@1: address &= ~0xF; rlm@1: else rlm@1: { rlm@1: if (m_viewer.getSize() == 1) rlm@1: address &= ~1; rlm@1: else if (m_viewer.getSize() == 2) rlm@1: address &= ~3; rlm@1: } rlm@1: m_viewer.setAddress(address); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnSelchangeAddresses() rlm@1: { rlm@1: int cur = m_addresses.GetCurSel(); rlm@1: rlm@1: switch (cur) rlm@1: { rlm@1: case 0: rlm@1: m_viewer.setAddress(0); rlm@1: break; rlm@1: case 1: rlm@1: m_viewer.setAddress(0x2000000); rlm@1: break; rlm@1: case 2: rlm@1: m_viewer.setAddress(0x3000000); rlm@1: break; rlm@1: case 3: rlm@1: m_viewer.setAddress(0x4000000); rlm@1: break; rlm@1: case 4: rlm@1: m_viewer.setAddress(0x5000000); rlm@1: break; rlm@1: case 5: rlm@1: m_viewer.setAddress(0x6000000); rlm@1: break; rlm@1: case 6: rlm@1: m_viewer.setAddress(0x7000000); rlm@1: break; rlm@1: case 7: rlm@1: m_viewer.setAddress(0x8000000); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::setCurrentAddress(u32 address) rlm@1: { rlm@1: CString buffer; rlm@1: rlm@1: buffer.Format("0x%08X", address); rlm@1: m_current.SetWindowText(buffer); rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnSave() rlm@1: { rlm@1: MemoryViewerAddressSize dlg; rlm@1: CString buffer; rlm@1: rlm@1: dlg.setAddress(m_viewer.getCurrentAddress()); rlm@1: rlm@1: LPCTSTR exts[] = { ".dmp", NULL }; rlm@1: rlm@1: if (dlg.DoModal() == IDOK) rlm@1: { rlm@1: CString filter = winResLoadFilter(IDS_FILTER_DUMP); rlm@1: CString title = winResLoadString(IDS_SELECT_DUMP_FILE); rlm@1: rlm@1: FileDlg file(this, rlm@1: buffer, rlm@1: filter, rlm@1: 0, rlm@1: "DMP", rlm@1: exts, rlm@1: "", rlm@1: title, rlm@1: true); rlm@1: if (file.DoModal() == IDOK) rlm@1: { rlm@1: buffer = file.GetPathName(); rlm@1: rlm@1: FILE *f = fopen(buffer, "wb"); rlm@1: rlm@1: if (f == NULL) rlm@1: { rlm@1: systemMessage(IDS_ERROR_CREATING_FILE, buffer); rlm@1: return; rlm@1: } rlm@1: rlm@1: int size = dlg.getSize(); rlm@1: u32 addr = dlg.getAddress(); rlm@1: rlm@1: for (int i = 0; i < size; i++) rlm@1: { rlm@1: fputc(CPUReadByteQuick(addr), f); rlm@1: addr++; rlm@1: } rlm@1: rlm@1: fclose(f); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::OnLoad() rlm@1: { rlm@1: CString buffer; rlm@1: LPCTSTR exts[] = { ".dmp", NULL }; rlm@1: rlm@1: CString filter = winResLoadFilter(IDS_FILTER_DUMP); rlm@1: CString title = winResLoadString(IDS_SELECT_DUMP_FILE); rlm@1: rlm@1: FileDlg file(this, rlm@1: buffer, rlm@1: filter, rlm@1: 0, rlm@1: "DMP", rlm@1: exts, rlm@1: "", rlm@1: title, rlm@1: false); rlm@1: rlm@1: if (file.DoModal() == IDOK) rlm@1: { rlm@1: buffer = file.GetPathName(); rlm@1: FILE *f = fopen(buffer, "rb"); rlm@1: if (f == NULL) rlm@1: { rlm@1: systemMessage(IDS_CANNOT_OPEN_FILE, rlm@1: "Cannot open file %s", rlm@1: buffer); rlm@1: return; rlm@1: } rlm@1: rlm@1: MemoryViewerAddressSize dlg; rlm@1: rlm@1: fseek(f, 0, SEEK_END); rlm@1: int size = ftell(f); rlm@1: rlm@1: fseek(f, 0, SEEK_SET); rlm@1: rlm@1: dlg.setAddress(m_viewer.getCurrentAddress()); rlm@1: dlg.setSize(size); rlm@1: rlm@1: if (dlg.DoModal() == IDOK) rlm@1: { rlm@1: int size = dlg.getSize(); rlm@1: u32 addr = dlg.getAddress(); rlm@1: rlm@1: for (int i = 0; i < size; i++) rlm@1: { rlm@1: int c = fgetc(f); rlm@1: if (c == -1) rlm@1: break; rlm@1: CPUWriteByteQuick(addr, c); rlm@1: addr++; rlm@1: } rlm@1: OnRefresh(); rlm@1: } rlm@1: fclose(f); rlm@1: } rlm@1: } rlm@1: rlm@1: void MemoryViewerDlg::PostNcDestroy() rlm@1: { rlm@1: delete this; rlm@1: } rlm@1: