⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nestreme.cpp

📁 nes游戏模拟器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	DWORD dwEndTime   = 0; // The ending time of our frame.
	DWORD dwTotalTime = 0; // The total time of our frame.
	DWORD dwFrames    = 0; // The number of frames drawn in a second.
	MSG   msg;             // Message structure.
	
	DWORD dwSoundFrameSkip = OPTIONS_NUM_AUDIOFRAMESKIP;
	DWORD dwGfxFrameSkip = OPTIONS_NUM_GFXFRAMESKIP;

	char strFrameCount[128] = {0};
	

	// Create the child window for running the program.
	hwndRunWnd = CreateWindowEx(WS_EX_MDICHILD,
							    strRunClassName,
								strRunTitleName,
								WS_CHILD,
								CW_USEDEFAULT,
								CW_USEDEFAULT,
								CW_USEDEFAULT,
								CW_USEDEFAULT,
								hwndMDIClient,
								NULL,
								g_hInstance,
								NULL);
	if (hwndRunWnd == NULL)
		FATAL(hwndMDIClient, "Couldn't Create the run window");

	// Create DirectDraw for the window.
	CreateDirectDraw(hwndRunWnd);

	// Create and initialize DirectSound.
	CreateSound(hwndRunWnd);

	// Keep running the program until the user has chosen to stop.
	while (bRunning == TRUE)
	{
		// If there is a message for this window, then we need
		// to process it. Otherwise, we are free to run then 
		// NES ROM until the user has chosen to stop. (bRunning == FALSE)
		if (PeekMessage(&msg, hwndRunWnd, 0, 0, PM_REMOVE))
		{
			DispatchMessage(&msg);
			TranslateMessage(&msg);
		}
		else
		{	
			// If we are back at the beginning of the screen
			// then clear the screen to the background color.
			if (wScanline == 0)
			{
				// Start our FPS counter.
				dwBeginTime = GetTickCount();

				// Initialize the surface to do our drawing.
				if (!dwGfxFrameSkip)
				{
					BeginDrawing();
				}

				// Draw all the sprites behind the background.
				if (!dwGfxFrameSkip)
				{
					if (Options_bSpritesEnabled)
						DrawSprites(SPRITE_BEHIND);
				}
			}

			// Single step the cpu.
			RunCPU(RUNCPU_RUN);

			// Do all the cyclic tasks.
			CPU_DoCyclicTasks();

			// Draw the scanline if its one of the scanlines on the screen.
			// i.e Don't draw the scanlines in VBlank.
			if (!dwGfxFrameSkip)
			{
				if ((wScanline < 240) && (CPU.Memory[0x2001] & 0x08) && Options_bBackgroundEnabled)
					DrawScanline();
			}

			// Flip the surfaces if we are done drawing the frame.
			if (wScanline == NUM_SCANLINES_SCREEN)
			{
				// Draw all the sprites in front of the background.
				if (!dwGfxFrameSkip)
				{
					if (Options_bSpritesEnabled)
						DrawSprites(SPRITE_INFRONT);
				}

				// Output the number of frames per second.
				OutputText(strFrameCount, 0, 0, RGB(255, 255, 255), 0);

				// Now that everything has been drawn.
				if (!dwGfxFrameSkip)
				{
					EndDrawing();
				}

				// Update our sound for the frame.
				if (!dwSoundFrameSkip)
					APU_DoFrame();

				if ((dwSoundFrameSkip--) == 0)
					dwSoundFrameSkip = OPTIONS_NUM_AUDIOFRAMESKIP;

				if ((dwGfxFrameSkip--) == 0)
					dwGfxFrameSkip = OPTIONS_NUM_GFXFRAMESKIP;
			}
			else if (wScanline == (NUM_SCANLINES_VBLANK+NUM_SCANLINES_SCREEN-1))
			{
				// Wait so we only go 60 FPS.
				//DWORD dwTemp = GetTickCount();
				//if ((dwTemp - dwBeginTime) < 16)
				//	Wait(16 - (dwTemp - dwBeginTime));

				// Calculate the FPS.
				dwFrames++;
				dwEndTime = GetTickCount();
				dwTotalTime += dwEndTime - dwBeginTime;

				// Display the FPS every 1 second.
				if (dwTotalTime >= 1000)
				{
					sprintf(strFrameCount, "Fps = %d", dwFrames);
					dwFrames = 0;
					dwTotalTime = 0;
				}
			}
		}
	}

	// Clean up DirectDraw, DirectSound and destroy the window.
	DestroyDirectDraw();
	DestroySound();
	DestroyWindow(hwndRunWnd);

	return 0;
} // end CPU_Run()


//------------------------------------------------------------------------------
// Name: CPU_RunUntilBreak()
// Desc: Runs the NES in debug mode until a breakpoint is encountered or
//       the user selects the break command.
//------------------------------------------------------------------------------
DWORD WINAPI CPU_RunUntilBreak(LPVOID lpParam)
{
	// As long as the user hasn't pressed break or we havn't
	// encountered a breakpoint, keep executing.
	while (bBreak == FALSE)
	{
		// Single step the cpu.
		RunCPU(RUNCPU_STEP);

		// Do all the cyclic tasks.
		CPU_DoCyclicTasks();

		// Check for breakpoints and tell the loop to break
		// if the PC is at a breakpoint.
		for (int i = 0; i < OPTIONS_NUM_BREAKPOINTS; i++)
		{
			if (CPU.P == awBreakpoints[i])
			{
				bBreak = TRUE;
				break;
			}
		}
	}

	// Update all the debugging information and reset the break command.
	UpdateDebugInfo();
	bBreak = FALSE;

	return 0;
} // end CPU_RunUntilBreak()


//------------------------------------------------------------------------------
// Name: CPU_Step()
// Desc: Single steps through instructions in debug mode.
//------------------------------------------------------------------------------
HRESULT CPU_Step()
{
	// Single step the cpu.
	RunCPU(RUNCPU_STEP);

	// Do all the cyclic tasks.
	CPU_DoCyclicTasks();

	// Update all the debugging information.
	UpdateDebugInfo();

	return S_OK;
} // end CPU_Step()


//------------------------------------------------------------------------------
// Name: SetListViewText()
// Desc: Sets the text of an item in a list view control.
//------------------------------------------------------------------------------
HRESULT SetListViewText(HWND hwndLV, UINT uRow, UINT uCol, LPSTR strText)
{
	LV_ITEM lvI; // List view item structure.

	// Fill out the item structure.
	lvI.mask = LVIF_TEXT;
	lvI.iItem = uRow;
	lvI.iSubItem = uCol;
	lvI.pszText = strText;
	lvI.state = 0;
	lvI.stateMask = 0;
    
	// Set the text of the item
	if (ListView_SetItem(hwndLV, &lvI) == FALSE)
		return ERROR;

	return S_OK;
} // end SetListViewText()


//------------------------------------------------------------------------------
// Name: ToggleBreakpoint()
// Desc: Turns a breakpoint on or off.
//------------------------------------------------------------------------------
HRESULT ToggleBreakpoint(UINT uItem)
{
	char strPC[5];      // Text to hold the PC address of the item.
	char strAddress[5]; // Text to hold the address of the breakpoint.

	// Get the address that the user has selected to add a breakpoint.
	ListView_GetItemText(hwndCodeLV, uItem, 0, strPC, 5);
	
	// Loop through and see if a breakpoint is already added on this line.
	for (int i = 0; i < OPTIONS_NUM_BREAKPOINTS; i++)
	{
		// Convert the breakpoint address to a string.
		sprintf(strAddress, "%04X", awBreakpoints[i]);

		// If the breakpoint is already on this line, then we
		// need to disable it.
		if (strcmp(strAddress, strPC) == 0)
			return DisableBreakpoint(i, uItem);
	}

	// If the breakpoint does not exist on this line, 
	// then we must add a breakpoint.
	return AddBreakpoint((WORD)strtoul(strPC, NULL, 16), uItem);
} // end ToggleBreakpoint()


//------------------------------------------------------------------------------
// Name: UpdateInstrCursorPos()
// Desc: Places the selection marker of the code list view on the
//       current instruction.
//------------------------------------------------------------------------------
HRESULT UpdateInstrCursorPos()
{
	LVFINDINFO lvfi;      // List view find item info.
	DWORD      dwItem;    // Current item to be selected.
	char       strPC[10]; // String of the PC's value.

	// Convert the PC's value to a hexadecimal string
	sprintf(strPC, "%04X:", CPU.P);

	// Initialize the structure to find our PC string.
	lvfi.flags = LVFI_STRING;
	lvfi.psz   = strPC;
	
	// Find the item in the list view.
	dwItem = ListView_FindItem(hwndCodeLV, -1, &lvfi);

	// If the item is not found then we need to dissassemble the rom
	// again because the program counter is out of range, then select
	// the first instruction.
	if (dwItem == -1)
	{
		DissassembleROM();
		dwItem = 0;
	}

	// Select the item.
	SetFocus(hwndCodeLV);
	ListView_SetItemState(hwndCodeLV, dwItem, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);

	return S_OK;
} // end UpdateInstrCursorPos()


//------------------------------------------------------------------------------
// Name: UpdateDebugInfo()
// Desc: Updates all the debugging information in the Registers List View.
//------------------------------------------------------------------------------
HRESULT UpdateDebugInfo()
{
	// Update all the registers.
	UpdateRegisters();

	// Select the current instruction line.
	UpdateInstrCursorPos();

	return S_OK;
} // end UpdateDebugInfo()


//------------------------------------------------------------------------------
// Name: UpdateRegisters()
// Desc: Updates all the register values in the register list view.
//------------------------------------------------------------------------------
HRESULT UpdateRegisters()
{
	char strText[128]; // Text to hold the info to be added.

	// Update the A register.
	UPDATE_VAR_IN_REG_LISTVIEW(0, "A", CPU.A);
	// Update the X register.
	UPDATE_VAR_IN_REG_LISTVIEW(1, "X", CPU.X);
	// Update the Y register.
	UPDATE_VAR_IN_REG_LISTVIEW(2, "Y", CPU.Y);
	// Update the SP register.
	UPDATE_VAR_IN_REG_LISTVIEW(3, "SP", CPU.S);
	// Update the PC register.
	UPDATE_VAR_IN_REG_LISTVIEW(4, "PC", CPU.P);	
	// Update the flags register.
	sprintf(strText, "Flags");
	SetListViewText(hwndRegsLV, 5, 0, strText);
	sprintf(&strText[0], "%c", (CPU.F & 0x80) ? 'S' : 's');
	sprintf(&strText[1], "%c", (CPU.F & 0x40) ? 'V' : 'v');
	sprintf(&strText[2], "%c", ' ');
	sprintf(&strText[3], "%c", (CPU.F & 0x10) ? 'B' : 'b');
	sprintf(&strText[4], "%c", (CPU.F & 0x08) ? 'D' : 'd');
	sprintf(&strText[5], "%c", (CPU.F & 0x04) ? 'I' : 'i');
	sprintf(&strText[6], "%c", (CPU.F & 0x02) ? 'Z' : 'z');
	sprintf(&strText[7], "%c", (CPU.F & 0x01) ? 'C' : 'c');
	SetListViewText(hwndRegsLV, 5, 1, strText);

	// Update the Nintendo registers.
	UPDATE_VAR_IN_REG_LISTVIEW(7, "$2000", CPU.Memory[0x2000]);
	UPDATE_VAR_IN_REG_LISTVIEW(8, "$2001", CPU.Memory[0x2001]);
	UPDATE_VAR_IN_REG_LISTVIEW(9, "$2002", CPU.Memory[0x2002]);
	UPDATE_VAR_IN_REG_LISTVIEW(10, "$2003", CPU.Memory[0x2003]);
	UPDATE_VAR_IN_REG_LISTVIEW(11, "$2004", CPU.Memory[0x2004]);
	UPDATE_VAR_IN_REG_LISTVIEW(12, "$2005", CPU.Memory[0x2005]);
	UPDATE_VAR_IN_REG_LISTVIEW(13, "$2006", CPU.Memory[0x2006]);
	UPDATE_VAR_IN_REG_LISTVIEW(14, "$2007", CPU.Memory[0x2007]);
	UPDATE_VAR_IN_REG_LISTVIEW(15, "$4000", CPU.Memory[0x4000]);
	UPDATE_VAR_IN_REG_LISTVIEW(16, "$4001", CPU.Memory[0x4001]);
	UPDATE_VAR_IN_REG_LISTVIEW(17, "$4002", CPU.Memory[0x4002]);
	UPDATE_VAR_IN_REG_LISTVIEW(18, "$4003", CPU.Memory[0x4003]);
	UPDATE_VAR_IN_REG_LISTVIEW(19, "$4004", CPU.Memory[0x4004]);
	UPDATE_VAR_IN_REG_LISTVIEW(20, "$4005", CPU.Memory[0x4005]);
	UPDATE_VAR_IN_REG_LISTVIEW(21, "$4006", CPU.Memory[0x4006]);
	UPDATE_VAR_IN_REG_LISTVIEW(22, "$4007", CPU.Memory[0x4007]);
	UPDATE_VAR_IN_REG_LISTVIEW(23, "$4008", CPU.Memory[0x4008]);
	UPDATE_VAR_IN_REG_LISTVIEW(24, "$4009", CPU.Memory[0x4009]);
	UPDATE_VAR_IN_REG_LISTVIEW(25, "$4010", CPU.Memory[0x4010]);
	UPDATE_VAR_IN_REG_LISTVIEW(26, "$4011", CPU.Memory[0x4011]);
	UPDATE_VAR_IN_REG_LISTVIEW(27, "$4012", CPU.Memory[0x4012]);
	UPDATE_VAR_IN_REG_LISTVIEW(28, "$4013", CPU.Memory[0x4013]);
	UPDATE_VAR_IN_REG_LISTVIEW(29, "$4014", CPU.Memory[0x4014]);
	UPDATE_VAR_IN_REG_LISTVIEW(30, "$4015", CPU.Memory[0x4015]);
	UPDATE_VAR_IN_REG_LISTVIEW(31, "$4016", CPU.Memory[0x4016]);
	UPDATE_VAR_IN_REG_LISTVIEW(32, "$4017", CPU.Memory[0x4017]);

	// Update the number of cpu cycles.
	sprintf(strText, "Cycles");
	SetListViewText(hwndRegsLV, 34, 0, strText);
	sprintf(strText, "%d", CPU.byCycles);
	SetListViewText(hwndRegsLV, 34, 1, strText);
	// Update the scanline number.
	sprintf(strText, "Scanline");
	SetListViewText(hwndRegsLV, 35, 0, strText);
	sprintf(strText, "%d", wScanline);
	SetListViewText(hwndRegsLV, 35, 1, strText);
	// Update the VRAM Address.
	UPDATE_VAR_IN_REG_LISTVIEW(36, "VRAM Address", wVRAMAddress);
	return S_OK;
} // end UpdateRegisters()


//------------------------------------------------------------------------------
// Name: Wait()
// Desc: Waits the number of milliseconds passed into the function.
//------------------------------------------------------------------------------
__inline VOID Wait(DWORD dwTime)
{
	DWORD dwBegin = GetTickCount();
	while ((GetTickCount() - dwBegin) <= dwTime);
} // end Wait()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -