project64/Source/Project64/UserInterface/Debugger/Debugger-DMALogView.cpp

420 lines
10 KiB
C++
Raw Normal View History

2017-08-18 05:08:22 +00:00
#include "stdafx.h"
#include "DebuggerUI.h"
#include "DMALog.h"
#include <fstream>
2017-08-18 05:08:22 +00:00
CDebugDMALogView::CDebugDMALogView(CDebuggerUI* debugger) :
CDebugDialog<CDebugDMALogView>(debugger)
{
2019-12-25 00:41:20 +00:00
m_DMALog = debugger->DMALog();
m_bFilterChanged = false;
m_bUniqueRomAddresses = true;
m_bCustomDrawClrNext = false;
2017-08-18 05:08:22 +00:00
}
CDebugDMALogView::~CDebugDMALogView()
{
}
/*
bool CDebugDMALogView::FilterEntry(int dmaLogIndex)
{
2019-12-25 00:41:20 +00:00
DMALogEntry entry = m_Debugger->DMALog()->at(dmaLogIndex);
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
for (int i = 0; i < dmaLogIndex; i++)
{
DMALogEntry testEntry = m_Debugger->DMALog()->at(i);
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
// Don't show if another entry has the same ROM address
if (entry.romAddr == testEntry.romAddr)
{
return false;
}
}
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
return true;
2017-08-18 05:08:22 +00:00
}
*/
2017-08-18 05:08:22 +00:00
void CDebugDMALogView::RefreshList()
{
2021-04-12 11:35:39 +00:00
if (g_Rom == nullptr)
2019-12-25 00:41:20 +00:00
{
return;
}
uint8_t* rom = g_Rom->GetRomAddress();
// Get scrollbar state
SCROLLINFO scroll;
scroll.cbSize = sizeof(SCROLLINFO);
scroll.fMask = SIF_ALL;
m_DMAList.GetScrollInfo(SB_VERT, &scroll);
bool bScrolledDown = false;
if ((scroll.nPage + scroll.nPos) - 1 == (uint32_t)scroll.nMax)
{
bScrolledDown = true;
}
int startIndex;
int dmaLogSize = m_Debugger->DMALog()->GetNumEntries();
HWND hWndExportBtn = GetDlgItem(IDC_EXPORT_BTN);
2019-12-25 00:41:20 +00:00
if (dmaLogSize == 0)
{
// Reset
m_DMAList.DeleteAllItems();
startIndex = 0;
m_bFilterChanged = false;
::EnableWindow(hWndExportBtn, FALSE);
2019-12-25 00:41:20 +00:00
}
else
{
// Continue from last index
startIndex = m_nLastStartIndex;
::EnableWindow(hWndExportBtn, TRUE);
2019-12-25 00:41:20 +00:00
}
m_DMAList.SetRedraw(FALSE);
int itemIndex = m_DMAList.GetItemCount();
for (int i = startIndex; i < dmaLogSize; i++)
{
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByIndex(i);
//if (!FilterEntry(i))
//{
// continue;
//}
2020-05-12 12:19:05 +00:00
m_DMAList.AddItem(itemIndex, 0, stdstr_f("%08X", lpEntry->romAddr).ToUTF16().c_str());
m_DMAList.AddItem(itemIndex, 1, stdstr_f("%08X", lpEntry->ramAddr).ToUTF16().c_str());
m_DMAList.AddItem(itemIndex, 2, stdstr_f("%08X (%d)", lpEntry->length, lpEntry->length).ToUTF16().c_str());
2019-12-25 00:41:20 +00:00
union
{
uint32_t u32;
uint8_t sz[5];
} sig = { 0 };
2017-08-18 05:08:22 +00:00
2019-04-02 19:16:39 +00:00
if (lpEntry->romAddr < g_Rom->GetRomSize())
{
sig.u32 = _byteswap_ulong(*(uint32_t*)&rom[lpEntry->romAddr]);
2019-04-02 19:16:39 +00:00
}
2017-08-18 05:08:22 +00:00
// TODO: checkbox to display all in hex
2019-12-25 00:41:20 +00:00
if (isalnum(sig.sz[0]) && isalnum(sig.sz[1]) && isalnum(sig.sz[2]) && isalnum(sig.sz[3]))
{
2020-05-12 12:19:05 +00:00
m_DMAList.AddItem(itemIndex, 4, stdstr((char*)sig.sz).ToUTF16().c_str());
2019-12-25 00:41:20 +00:00
}
itemIndex++;
}
if (bScrolledDown)
{
m_DMAList.EnsureVisible(m_DMAList.GetItemCount() - 1, FALSE);
}
m_DMAList.SetRedraw(TRUE);
m_nLastStartIndex = dmaLogSize;
2017-08-18 05:08:22 +00:00
}
void CDebugDMALogView::Export(void)
{
OPENFILENAME openfilename;
TCHAR filePath[_MAX_PATH];
memset(&filePath, 0, sizeof(filePath));
memset(&openfilename, 0, sizeof(openfilename));
wsprintf(filePath, L"*.csv");
const TCHAR* filters = (
/*1*/ L"Comma separated values (*.csv)\0*.csv;\0"
/*2*/ L"Plain text (*.txt)\0*.txt;\0"
);
const char *extensions[] = { "", ".csv", ".txt" };
openfilename.lStructSize = sizeof(openfilename);
openfilename.hwndOwner = (HWND)m_hWnd;
openfilename.lpstrFilter = filters;
openfilename.lpstrFile = filePath;
openfilename.lpstrInitialDir = L".";
openfilename.nMaxFile = MAX_PATH;
openfilename.Flags = OFN_HIDEREADONLY;
if (GetSaveFileName(&openfilename))
{
stdstr path;
path.FromUTF16(filePath);
if (openfilename.nFileExtension == 0)
{
path += extensions[openfilename.nFilterIndex];
}
std::ofstream file;
file.open(path, std::ios::out | std::ios::binary);
if (!file.is_open())
{
return;
}
file << "ROM Address,RAM Address,Length\r\n";
size_t numEntries = m_DMALog->GetNumEntries();
for (size_t nEntry = 0; nEntry < numEntries; nEntry++)
{
DMALOGENTRY* entry = m_DMALog->GetEntryByIndex(nEntry);
file << stdstr_f("0x%08X,0x%08X,0x%08X\r\n",
entry->romAddr, entry->ramAddr, entry->length);
}
file.close();
}
}
2018-01-18 06:53:07 +00:00
LRESULT CDebugDMALogView::OnActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2017-08-18 05:08:22 +00:00
{
2019-12-25 00:41:20 +00:00
//RefreshList();
return FALSE;
2017-08-18 05:08:22 +00:00
}
2018-01-18 06:53:07 +00:00
LRESULT CDebugDMALogView::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2017-08-18 05:08:22 +00:00
{
2019-12-25 00:41:20 +00:00
DlgResize_Init(false, true);
DlgSavePos_Init(DebuggerUI_DMALogPos);
2019-12-25 00:41:20 +00:00
m_bConvertingAddress = false;
m_nLastStartIndex = 0;
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
m_DMAList.Attach(GetDlgItem(IDC_DMA_LIST));
2019-04-02 19:16:39 +00:00
m_DMARamEdit.Attach(GetDlgItem(IDC_DMA_RAM_EDIT));
m_DMARomEdit.Attach(GetDlgItem(IDC_DMA_ROM_EDIT));
m_BlockInfo.Attach(GetDlgItem(IDC_BLOCK_INFO));
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
m_DMAList.ModifyStyle(LVS_OWNERDRAWFIXED, 0, 0);
2017-08-18 05:08:22 +00:00
2020-05-12 12:19:05 +00:00
m_DMAList.AddColumn(L"ROM", 0);
m_DMAList.AddColumn(L"RAM", 1);
m_DMAList.AddColumn(L"Length", 2);
m_DMAList.AddColumn(L"Symbol (RAM)", 3);
m_DMAList.AddColumn(L"Signature", 4);
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
m_DMAList.SetExtendedListViewStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER);
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
m_DMAList.SetColumnWidth(0, 65);
m_DMAList.SetColumnWidth(1, 65);
m_DMAList.SetColumnWidth(2, 120);
//m_DMAList.SetColumnWidth(3, 50);
//m_DMAList.SetColumnWidth(4, 50);
//m_DMAList.SetColumnWidth(5, 50);
m_DMARamEdit.SetLimitText(8);
m_DMARomEdit.SetLimitText(8);
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
RefreshList();
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
LoadWindowPos();
WindowCreated();
2017-08-18 05:08:22 +00:00
2019-12-25 00:41:20 +00:00
return TRUE;
2017-08-18 05:08:22 +00:00
}
2019-04-02 19:16:39 +00:00
void CDebugDMALogView::RefreshDMALogWindow(bool bReset)
2019-04-02 18:28:46 +00:00
{
2021-04-12 11:35:39 +00:00
if (m_hWnd == nullptr || m_DMAList.m_hWnd == nullptr)
2019-04-02 18:28:46 +00:00
{
2019-04-02 19:16:39 +00:00
if (bReset)
{
m_DMALog->ClearEntries();
}
2019-04-02 18:28:46 +00:00
return;
}
2019-04-02 19:16:39 +00:00
PostMessage(WM_REFRESH, bReset);
2019-04-02 18:28:46 +00:00
}
2019-04-02 19:16:39 +00:00
LRESULT CDebugDMALogView::OnRefresh(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
2019-04-02 18:28:46 +00:00
{
2020-01-22 06:34:27 +00:00
bool bReset = (wParam != 0);
2019-04-02 19:16:39 +00:00
if (bReset)
{
m_DMALog->ClearEntries();
}
2019-04-02 18:28:46 +00:00
RefreshList();
return TRUE;
}
void CDebugDMALogView::OnExitSizeMove(void)
{
SaveWindowPos(true);
}
2017-08-18 05:08:22 +00:00
LRESULT CDebugDMALogView::OnDestroy(void)
{
2019-04-02 19:16:39 +00:00
m_DMAList.Detach();
m_DMARamEdit.Detach();
m_DMARomEdit.Detach();
m_BlockInfo.Detach();
2019-12-25 00:41:20 +00:00
return 0;
2017-08-18 05:08:22 +00:00
}
LRESULT CDebugDMALogView::OnClicked(WORD /*wNotifyCode*/, WORD wID, HWND, BOOL& /*bHandled*/)
{
2019-12-25 00:41:20 +00:00
switch (wID)
{
case IDOK:
EndDialog(0);
break;
case IDCANCEL:
EndDialog(0);
break;
case IDC_CLEAR_BTN:
m_DMALog->ClearEntries();
RefreshList();
break;
case IDC_EXPORT_BTN:
Export();
break;
2019-12-25 00:41:20 +00:00
}
return FALSE;
2017-08-18 05:08:22 +00:00
}
2018-01-18 06:53:07 +00:00
LRESULT CDebugDMALogView::OnRamAddrChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
2017-08-18 05:08:22 +00:00
{
2019-12-25 00:41:20 +00:00
if (m_bConvertingAddress)
{
return FALSE;
}
2020-05-12 12:19:05 +00:00
wchar_t szRamAddr[9];
2019-12-25 00:41:20 +00:00
char szRomAddr[9];
2020-05-12 12:19:05 +00:00
m_DMARamEdit.GetWindowText(szRamAddr, 9);
2021-04-12 11:35:39 +00:00
uint32_t ramAddr = wcstoul(szRamAddr, nullptr, 16);
2019-12-25 00:41:20 +00:00
uint32_t romAddr, offset;
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByRamAddress(ramAddr, &romAddr, &offset);
2021-04-12 11:35:39 +00:00
if (lpEntry != nullptr)
2019-12-25 00:41:20 +00:00
{
sprintf(szRomAddr, "%08X", romAddr);
2020-05-12 12:19:05 +00:00
stdstr_f blockInfo("Block: %08X -> %08X [%X] +%X", romAddr, ramAddr, lpEntry->length, offset);
m_BlockInfo.SetWindowText(blockInfo.ToUTF16().c_str());
2019-12-25 00:41:20 +00:00
}
else
{
sprintf(szRomAddr, "????????");
2020-05-12 12:19:05 +00:00
m_BlockInfo.SetWindowText(L"Block: ?");
2019-12-25 00:41:20 +00:00
}
m_bConvertingAddress = true;
2020-05-12 12:19:05 +00:00
m_DMARomEdit.SetWindowText(stdstr(szRomAddr).ToUTF16().c_str());
2019-12-25 00:41:20 +00:00
m_bConvertingAddress = false;
return FALSE;
2017-08-18 05:08:22 +00:00
}
2018-01-18 06:53:07 +00:00
LRESULT CDebugDMALogView::OnRomAddrChanged(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
2017-08-18 05:08:22 +00:00
{
2019-12-25 00:41:20 +00:00
if (m_bConvertingAddress)
{
return FALSE;
}
2020-05-12 12:19:05 +00:00
wchar_t szRamAddr[9];
wchar_t szRomAddr[9];
2019-12-25 00:41:20 +00:00
2020-05-12 12:19:05 +00:00
m_DMARomEdit.GetWindowText(szRomAddr, 9);
2021-04-12 11:35:39 +00:00
uint32_t romAddr = wcstoul(szRomAddr, nullptr, 16);
2019-12-25 00:41:20 +00:00
uint32_t ramAddr, offset;
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByRomAddress(romAddr, &ramAddr, &offset);
2021-04-12 11:35:39 +00:00
if (lpEntry != nullptr)
2019-12-25 00:41:20 +00:00
{
2020-05-12 12:19:05 +00:00
wsprintf(szRamAddr, L"%08X", ramAddr);
2019-12-25 00:41:20 +00:00
stdstr blockInfo = stdstr_f("Block: %08X -> %08X [%X] +%X", romAddr, ramAddr, lpEntry->length, offset);
2020-05-12 12:19:05 +00:00
m_BlockInfo.SetWindowText(blockInfo.ToUTF16().c_str());
2019-12-25 00:41:20 +00:00
}
else
{
2020-05-12 12:19:05 +00:00
wsprintf(szRamAddr, L"????????");
m_BlockInfo.SetWindowText(L"Block: ?");
2019-12-25 00:41:20 +00:00
}
m_bConvertingAddress = true;
2020-05-12 12:19:05 +00:00
m_DMARamEdit.SetWindowText(szRamAddr);
2019-12-25 00:41:20 +00:00
m_bConvertingAddress = false;
return FALSE;
2017-08-18 05:08:22 +00:00
}
LRESULT CDebugDMALogView::OnCustomDrawList(NMHDR* pNMHDR)
{
2019-12-25 00:41:20 +00:00
NMLVCUSTOMDRAW* pLVCD = reinterpret_cast<NMLVCUSTOMDRAW*>(pNMHDR);
DWORD drawStage = pLVCD->nmcd.dwDrawStage;
switch (drawStage)
{
case CDDS_PREPAINT: return CDRF_NOTIFYITEMDRAW;
case CDDS_ITEMPREPAINT: return CDRF_NOTIFYSUBITEMDRAW;
case (CDDS_ITEMPREPAINT | CDDS_SUBITEM): break;
default: return CDRF_DODEFAULT;
}
DWORD nItem = pLVCD->nmcd.dwItemSpec;
DWORD nSubItem = pLVCD->iSubItem;
if (nSubItem != 0)
{
return CDRF_DODEFAULT;
}
size_t nEntries = m_DMALog->GetNumEntries();
if (nEntries == 0)
{
return CDRF_DODEFAULT;
}
DMALOGENTRY* lpEntry = m_DMALog->GetEntryByIndex(nItem);
if (nItem >= 1) // Continuation
2019-12-25 00:41:20 +00:00
{
DMALOGENTRY* lpPrevEntry = m_DMALog->GetEntryByIndex(nItem - 1);
if (lpEntry->romAddr == lpPrevEntry->romAddr + lpPrevEntry->length)
{
pLVCD->clrTextBk = RGB(0xFF, 0xFF, 0xCC);
return CDRF_DODEFAULT;
}
}
if (nEntries >= 2 && nItem <= nEntries - 2) // Head
2019-12-25 00:41:20 +00:00
{
DMALOGENTRY* lpNextEntry = m_DMALog->GetEntryByIndex(nItem + 1);
if (lpNextEntry->romAddr == lpEntry->romAddr + lpEntry->length)
{
pLVCD->clrTextBk = RGB(0xFF, 0xFF, 0x88);
return CDRF_DODEFAULT;
}
}
return CDRF_DODEFAULT;
}