📄 nestreme.cpp
字号:
//------------------------------------------------------------------------------
// Name: Nestreme.cpp
// Desc:
//
// Things still left to add in the debugger.
// =========================================
// 1. Viewing all the memory, main, stack, prg-rom, chr-rom
// 2. Adding the memory registers to the register list view.
// 3. Better breakpoints, adding in dialog box, setting when dissassembling.
// 4. Step over.
// 5. View screen shot.
// 6. Editing memory.
// 7.
//
// Things to add to the CPU.
// =========================
// 1. More acurate cpu cycle emulation.
// 2. Test all the instructions.
// 3. Update cpu bytes and cycles array.
//
// Things to add to the PPU.
// =========================
// 1. Accurate emulation of registers 2005/2006.
//------------------------------------------------------------------------------
// Includes
#include <windows.h>
#include <commctrl.h>
#include <afxres.h>
#include <stdio.h>
#include "resource.h"
#include "Nestreme.h"
#include "Cpu.h"
#include "Io.h"
#include "PrintInstrToString.h"
#include "Gfx.h"
#include "Sound.h"
#include "NESData.h"
//------------------------------------------------------------------------------
// Name: WinMain()
// Desc: Main entry point for a windows application.
//------------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInst,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccel;
// Save the global variables
g_hInstance = hInstance;
// Initialize our classes.
if (InitializeApp() != S_OK)
return TRUE;
// Create our main window
hwndMain = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW,
strClassName,
strAppName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);
// Make sure we could create our window.
if (hwndMain == NULL)
return TRUE;
// Load the keyboard accelerators.
hAccel = LoadAccelerators(g_hInstance, MAKEINTRESOURCE(IDR_MAINACCEL));
// Show and update our window.
ShowWindow(hwndMain, SW_SHOWMAXIMIZED);
UpdateWindow(hwndMain);
// Now enter our main windows messaging loop.
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(hwndMain, hAccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
} // end windows messaging loop.
// Make sure to delete everything we allocate.
CleanUp();
return msg.wParam;
} // end WinMain()
//------------------------------------------------------------------------------
// Name: WndProcMain()
// Desc: Our message handling procedure for windows messages.
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProcMain(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
HANDLE hThreadGo; // Handle to the thread created when go is selected.
DWORD dwThreadIDGo; // Thread ID of the thread created when go is selected.
switch (uMsg)
{
case WM_QUIT:
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE:
CreateMDIClientWindow(hwnd);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_DEBUG_BREAK:
bBreak = TRUE;
break;
case ID_DEBUG_GO:
hThreadGo = CreateThread(NULL, 0, CPU_RunUntilBreak,
NULL, NULL, &dwThreadIDGo);
if (hThreadGo == NULL)
FATAL(hwnd, "Couldn't create thread for execution.");
break;
case ID_DEBUG_RESTART:
ResetNES();
break;
case ID_DEBUG_STEPINTO:
CPU_Step();
break;
case ID_FILE_FREE:
FreeNESFile();
break;
case ID_FILE_OPEN:
LoadNESFile(hwnd);
break;
case ID_FILE_RUN:
bRunning = TRUE;
hThreadRun = CreateThread(NULL, 0, CPU_Run,
NULL, NULL, &dwThreadIDRun);
if (hThreadRun == NULL)
FATAL(hwnd, "Couldn't create thread for execution.");
break;
case ID_FILE_EXIT:
PostQuitMessage(0);
break;
case ID_VIEW_MEMORY:
CreateMemoryWindow(hwnd);
break;
case ID_VIEW_DISASSEMBLY:
CreateDebugWindow(hwnd);
DissassembleROM();
UpdateDebugInfo();
break;
case ID_WINDOW_TILEHORIZONTALLY:
SendMessage(hwndMDIClient, WM_MDITILE, MDITILE_HORIZONTAL, 0);
break;
case ID_WINDOW_TILEVERTICALLY:
SendMessage(hwndMDIClient, WM_MDITILE, MDITILE_VERTICAL, 0);
break;
}
default:
return DefFrameProc(hwnd, hwndMDIClient, uMsg, wParam, lParam);
}
return 0;
} // end WndProcMain()
//------------------------------------------------------------------------------
// Name: WndProcDebug()
// Desc: Our message handling procedure for windows messages.
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProcDebug(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_NOTIFY:
// Process notification messages.
switch (((LPNMHDR)lParam)->code)
{
case NM_DBLCLK:
ToggleBreakpoint(((LPNMITEMACTIVATE)lParam)->iItem);
break;
}
break;
case WM_SIZE:
ResizeDebugControls(hwndDebugWnd, hwndCodeLV, hwndRegsLV);
default:
return DefMDIChildProc(hwnd, uMsg, wParam, lParam);
}
return 0;
} // end WndProcDebug()
//------------------------------------------------------------------------------
// Name: WndProcMemory()
// Desc: Our message handling procedure for windows messages.
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProcMemory(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
static HWND hwndEdit = NULL; // Handle to the edit control to hold the memory contents.
static HWND hwndButton = NULL; // Handle to the refresh button.
static HWND hwndMemoryTab = NULL; // Handle to the memory tab control.
switch (uMsg)
{
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
// Display the memory that corresponds, on what tab is selected.
switch (TabCtrl_GetCurSel(hwndMemoryTab))
{
case 0:
// Dump the main memory to the control.
DisplayMainMemDump(hwndEdit);
break;
case 1:
// Dump the stack memory to the control.
DisplayStackMemDump(hwndEdit);
break;
case 2:
// Dump the PRG-ROM memory to the control.
DisplayPRGROMMemDump(hwndEdit);
break;
case 3:
// Dump the PPU memory to the control.
DisplayPPUMemDump(hwndEdit);
break;
case 4:
// Dump the Sprite memory to the control.
DisplaySpriteMemDump(hwndEdit);
break;
default:
break;
}
}
break;
case WM_CREATE:
// Create the tab control to hold all the different types of memory.
if ((hwndMemoryTab = CreateTabControl(hwnd, IDS_MEMORY_MAIN, 5)) == NULL)
FATAL(hwnd, "Couldn't create tab control.");
// Create the edit control and initialize it.
if (CreateMemoryDump(hwnd, &hwndEdit, &hwndButton) != S_OK)
FATAL(hwnd, "Couldn't create the edit window.")
// Dump the memory to the control.
DisplayMainMemDump(hwndEdit);
break;
case WM_NOTIFY:
switch (((LPNMHDR) lParam)->code)
{
case TCN_SELCHANGE:
{
RECT rc;
// Create the edit control and initialize it.
if (CreateMemoryDump(hwnd, &hwndEdit, &hwndButton) != S_OK)
FATAL(hwnd, "Couldn't create the edit window.")
// Display the memory that corresponds, on what tab is selected.
switch (TabCtrl_GetCurSel(hwndMemoryTab))
{
case 0:
// Dump the main memory to the control.
DisplayMainMemDump(hwndEdit);
break;
case 1:
// Dump the stack memory to the control.
DisplayStackMemDump(hwndEdit);
break;
case 2:
// Dump the PRG-ROM memory to the control.
DisplayPRGROMMemDump(hwndEdit);
break;
case 3:
// Dump the PPU memory to the control.
DisplayPPUMemDump(hwndEdit);
break;
case 4:
// Dump the Sprite memory to the control.
DisplaySpriteMemDump(hwndEdit);
break;
default:
break;
}
// Update the window by calling sending the size message.
GetClientRect(hwnd, &rc);
SendMessage(hwnd, WM_SIZE, SIZE_RESTORED, MAKELPARAM(rc.right-rc.left, rc.bottom-rc.top));
break;
}
case TCN_SELCHANGING:
DestroyWindow(hwndEdit);
DestroyWindow(hwndButton);
break;
}
break;
case WM_SIZE:
{
HDWP hdwp;
RECT rc;
// Calculate the display rectangle, assuming the
// tab control is the size of the client area.
SetRect(&rc, 0, 0, LOWORD(lParam), HIWORD(lParam));
TabCtrl_AdjustRect(hwndMemoryTab, FALSE, &rc);
// Size the tab control to fit the client area.
hdwp = BeginDeferWindowPos(3);
DeferWindowPos(hdwp, hwndMemoryTab, NULL, 0, 0,
LOWORD(lParam), HIWORD(lParam), SWP_NOMOVE | SWP_NOZORDER);
// Position and size the button control to fit at
// the bottom of the tab control window.
DeferWindowPos(hdwp, hwndButton, HWND_TOP, rc.left,
rc.bottom-rc.top, 70, 20, 0);
// Position and size the edit control to fit the
// tab control's display area minus some room for
// the button, and make sure the edit control is
// in front of the tab control.
DeferWindowPos(hdwp, hwndEdit, HWND_TOP, rc.left, rc.top,
rc.right-rc.left, rc.bottom-rc.top-30, 0);
EndDeferWindowPos(hdwp);
}
default:
return DefMDIChildProc(hwnd, uMsg, wParam, lParam);
}
return 0;
} // end WndProcMemory()
//------------------------------------------------------------------------------
// Name: WndProcRun()
// Desc: Our message handling procedure for windows messages.
//------------------------------------------------------------------------------
LRESULT CALLBACK WndProcRun(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
case WM_CLOSE:
// Tell the thread that runs the program to exit.
bRunning = FALSE;
break;
case WM_KEYDOWN:
switch (wParam)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -