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

📄 main.c

📁 DC的SEGA_GG模拟器源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
#include "shared.h"
#include "commctrl.h"
#include "state.h"
#include "dinput.h"
#include "vfw.h"
#include "stdio.h"
#include "resource.h"
#include "file.h"
#include "audio.h"
#include "input.h"
#include "main.h"
#include "zip.h"
#include "registry.h"
#include "modes.h"

static BMP			Bmp;
static HWND			hwnd;
static HINSTANCE	hInstance;
static HMENU		hMenu;
static BOOL			RunEmulation = FALSE;
static BOOL			Paused = FALSE;
static HANDLE		Mutex = NULL;
static unsigned int	USER_MESSAGE = 0;
unsigned char		BitmapData[256 * 256 * 2];
static HBITMAP		hBitmap = NULL;

static char			GameName[MAX_PATH] = "";
static unsigned int	Frame		   = 0;
static unsigned int	LastTickCount  = 0;
static BOOL			RecordSound	   = FALSE;
static BOOL			RecordingSound = FALSE;
static BOOL			UseDirectDraw  = FALSE;
static BOOL			DirectDrawAvail= FALSE;

static unsigned int FrameTime[]		= {0, 0, 0};
static unsigned int	FrameTime60hz[] = {17, 17, 16};
static unsigned int	FrameTime50hz[] = {20, 20, 20};

extern short		pixel[];

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
	WNDCLASS    WindowClass;
	MSG			msg;
	int			QuitFlag = FALSE;

	if (CreateSingleInstance(szCmdLine))
	{
		// Clear the window class structure
		memset(&WindowClass, 0, sizeof(WindowClass));

		// Set up window class attributes
		WindowClass.style                   = CS_HREDRAW | CS_VREDRAW;				// Window styles
		WindowClass.lpfnWndProc				= MainWindowProc;						// Windows messaging function
		WindowClass.hInstance				= hInstance;							// Application instance
		WindowClass.hIcon                   = LoadIcon(hinstance, MAKEINTRESOURCE(IDI_ICON1));		// Icon to display on title bar
		WindowClass.hCursor                 = LoadCursor(NULL, IDC_ARROW);			// Cursor to use over window
		WindowClass.hbrBackground			= CreateSolidBrush(0);					// Colour to use for window background
		WindowClass.lpszMenuName			= NULL;									// Menu to use
		WindowClass.lpszClassName			= SMS_CLASS_NAME;						// Class name

		// Register window class
		if (!RegisterClass(&WindowClass))
		{
			// Return unsuccessful
			return FALSE;
		}

		InitRegistryEntries();
		LoadRegistryEntries();

		// Create the main window for our application
		hInstance = hinstance;
		hwnd = CreateWindowEx(0,									// Extended window style
							  SMS_CLASS_NAME,			            // Pointer to registered class name
							  "SMS Plus",							// Pointer to window name 
							  WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,	// Window style
							  0,                                    // X Pos
							  0,                                    // Y Pos
							  0,									// Width
							  0,							        // Height
							  NULL,                                 // Handle to parent or owner window
							  NULL,                                 // Handle to menu, or child window
							  hInstance,					        // Application instance
							  NULL);                                // Pointer to window creation data

		// Load the menu to use for the application and set it
		hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU));
		SetMenu(hwnd, hMenu);

		InitVRAM();
		InitAudio(hwnd, RegistryInfo.SoundFrequency, FREQ_60HZ);
		InitInput(hwnd, hInstance);

		DirectDrawAvail = InitModes();
		if (DirectDrawAvail && RegistryInfo.EnableDirectDraw) UseDirectDraw = ChangeMode(RegistryInfo.FullScreenMode, RegistryInfo.FullScreen);

		CheckMenuItem(hMenu, ID_MENU_CONFIG_SCREEN_SMOOTHING, RegistryInfo.ScreenSmoothing? MF_CHECKED : MF_UNCHECKED);
		CheckMenuItem(hMenu, ID_MENU_CONFIG_SOUND_ENABLE, RegistryInfo.EnableSound? MF_CHECKED : MF_UNCHECKED);
		EnableMenuItem(hMenu, ID_MENU_CONFIG_SCREEN_FULL, UseDirectDraw? MF_BYCOMMAND | MF_ENABLED : MF_BYCOMMAND | MF_GRAYED);
		EnableMenuItem(hMenu, ID_MENU_CONFIG_SCREEN_SMOOTHING, UseDirectDraw? MF_BYCOMMAND | MF_ENABLED : MF_BYCOMMAND | MF_GRAYED);
		EnableMenuItem(hMenu, ID_MENU_CONFIG_SOUND_RECORD, RegistryInfo.EnableSound? MF_BYCOMMAND | MF_ENABLED : MF_BYCOMMAND | MF_GRAYED);

		if ((!UseDirectDraw || !RegistryInfo.EnableDirectDraw) && (RegistryInfo.ScreenScale == 0))
		{
			RegistryInfo.ScreenScale = 1;
		}

		SetFrameTime(RegistryInfo.UpdateFrequency);
		SetScreenScale(RegistryInfo.ScreenScale);
		SetScreenSmoothing(RegistryInfo.ScreenSmoothing);
		SetUpdateFrequency(RegistryInfo.UpdateFrequency);
		SetFrameSkip(RegistryInfo.FrameSkip);
		SetSoundFrequency(RegistryInfo.SoundFrequency);
		SetRegion(RegistryInfo.Region);
		CenterWindowInParent(hwnd);
		ShowWindow(hwnd, SW_SHOW);

		if (strlen(szCmdLine))
		{
			if (!stricmp(&szCmdLine[strlen(szCmdLine) - 2], "gg") ||
				!stricmp(&szCmdLine[strlen(szCmdLine) - 3], "sms") ||
				!stricmp(&szCmdLine[strlen(szCmdLine) - 3], ".zip"))
			{
				OpenROM(szCmdLine);
			}
		}
	}
	else
	{
		QuitFlag = TRUE;
	}

	// Main program loop
    while (QuitFlag == FALSE)
    {
		unsigned int		TickCount;
		unsigned int		Skip = (Frame % (RegistryInfo.FrameSkip + 1))? 1 : 0;

		TickCount = GetTickCount();

		if (LastTickCount == 0) LastTickCount = TickCount;

		if (TickCount - LastTickCount >= FrameTime[Frame % 3])
		{
			// Auto frame skip
			if (RegistryInfo.FrameSkip == 0)
			{
				if (TickCount - LastTickCount >= (FrameTime[Frame % 3] * 2)) Skip = TRUE;
			}

			if (RunEmulation && !Paused)
			{
			    sms_frame(Skip);

				if (RegistryInfo.EnableSound) UpdateAudio(snd.buffer, snd.bufsize, Frame);

				if (!Skip)
				{
					UpdatePalette();
					UpdateKeyboard();
					UpdateSpecialKeys();
					UpdateJoysticks();
					UpdateRapidFire(Frame);
					SendMessage(hwnd, WM_PAINT, 0, 0);
				}
			}

			if ((TickCount - LastTickCount) >= (FrameTime[0] * (NO_OF_AUDIO_BUFFERS / 2)))
			{
				LastTickCount = 0;
				Frame		  = 0;
			}
			else
			{
				LastTickCount = TickCount - ((TickCount - LastTickCount) - FrameTime[Frame % 3]);
				Frame++;
			}
		}
		else
		{
			if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
		    {
				if (GetMessage(&msg, NULL, 0, 0))
				{
					TranslateMessage(&msg);
					DispatchMessage(&msg);
			    }
				else
				{
					// GetMessage returning FALSE implies exit message
					QuitFlag = TRUE;
				}
			}
		}
    }
	
	SaveRegistryEntries();
	TidyModes();
	TidyInput();
	TidyAudio();
	system_shutdown();

	if (hMenu) DestroyMenu(hMenu);
	DestroySingleInstance();

	return msg.wParam;
}

LRESULT CALLBACK MainWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
	case WM_CREATE:
		{
			HDC			hDC;

			memset(&Bmp, 0, sizeof(BMP));

			Bmp.BitmapInfoHeader.biSize			= sizeof(BITMAPINFOHEADER);
			Bmp.BitmapInfoHeader.biWidth		= 256;
			Bmp.BitmapInfoHeader.biHeight		= 192;
			Bmp.BitmapInfoHeader.biPlanes		= 1;
			Bmp.BitmapInfoHeader.biBitCount		= 8;
			Bmp.BitmapInfoHeader.biCompression	= BI_RGB;
			Bmp.BitmapInfoHeader.biClrUsed		= 256;
				
			hDC = GetDC(hwnd);
			hBitmap = CreateDIBitmap(hDC, &Bmp.BitmapInfoHeader, 0, &BitmapData[0], (BITMAPINFO *)&Bmp, DIB_PAL_COLORS);
			ReleaseDC(hwnd, hDC);
		}
		break;

	case WM_SETFOCUS:
		if (UseDirectDraw && RegistryInfo.EnableDirectDraw && FullScreenMode()) FlipToGDISurface(FALSE);
		break;

	case WM_KILLFOCUS:
		if (UseDirectDraw && RegistryInfo.EnableDirectDraw && FullScreenMode()) FlipToGDISurface(TRUE);
		break;

	case WM_ACTIVATEAPP:
		if (wParam)
		{
			Paused = FALSE;

			// Restore Sync (+ Restart Audio)
			Frame		  = 0;
			LastTickCount = 0;

			// Restore Input
			InitInput(hwnd, hInstance);
		}
		else
		{
			Paused = TRUE;
			StopAudio();
			TidyInput();
		}
		break;

	case WM_MOVE:
		if (UseDirectDraw && RegistryInfo.EnableDirectDraw && !FullScreenMode()) UpdateModeWindowCoords(hwnd);
		break;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case ID_MENU_FILE_OPEN:
		    SaveSRAM();
			OpenROM(NULL);
			break;

		case ID_MENU_FILE_EXIT:
			SendMessage(hwnd, WM_CLOSE, 0, 0);
			break;

		case ID_MENU_CPU_RESET:
			SaveSRAM();
			input.system = INPUT_HARD_RESET;
			if (RecordSound) RecordingSound = TRUE;
			break;

		case ID_MENU_CPU_LOAD_STATE:
			LoadState();
			break;
		
		case ID_MENU_CPU_SAVE_STATE:
			SaveState();
			break;

		case ID_MENU_CONFIG_SCREEN_FULL:
			SetScreenScale(RegistryInfo.ScreenScale = 0);
			break;

		case ID_MENU_CONFIG_SCREEN_X1:
			SetScreenScale(RegistryInfo.ScreenScale = 1);
			break;

		case ID_MENU_CONFIG_SCREEN_X2:
			SetScreenScale(RegistryInfo.ScreenScale = 2);
			break;

		case ID_MENU_CONFIG_SCREEN_X3:
			SetScreenScale(RegistryInfo.ScreenScale = 3);
			break;

		case ID_MENU_CONFIG_UPDATE_50HZ:
			SetUpdateFrequency(RegistryInfo.UpdateFrequency = FREQ_50HZ);
			break;

		case ID_MENU_CONFIG_UPDATE_60HZ:
			SetUpdateFrequency(RegistryInfo.UpdateFrequency = FREQ_60HZ);
			break;

		case ID_MENU_CONFIG_SKIP_AUTO:
			SetFrameSkip(RegistryInfo.FrameSkip = 0);
			break;

		case ID_MENU_CONFIG_SKIP_1:
			SetFrameSkip(RegistryInfo.FrameSkip = 1);
			break;

		case ID_MENU_CONFIG_SKIP_2:
			SetFrameSkip(RegistryInfo.FrameSkip = 2);
			break;

		case ID_MENU_CONFIG_SKIP_3:
			SetFrameSkip(RegistryInfo.FrameSkip = 3);
			break;

		case ID_MENU_CONFIG_SKIP_4:
			SetFrameSkip(RegistryInfo.FrameSkip = 4);
			break;

		case ID_MENU_CONFIG_SCREEN_SMOOTHING:
			if (GetMenuState(hMenu, ID_MENU_CONFIG_SCREEN_SMOOTHING, MF_BYCOMMAND) == MF_CHECKED)
			{
				CheckMenuItem(hMenu, ID_MENU_CONFIG_SCREEN_SMOOTHING, MF_UNCHECKED);
				SetScreenSmoothing(RegistryInfo.ScreenSmoothing = FALSE);
			}
			else
			{
				CheckMenuItem(hMenu, ID_MENU_CONFIG_SCREEN_SMOOTHING, MF_CHECKED);
				SetScreenSmoothing(RegistryInfo.ScreenSmoothing = TRUE);
			}
			break;

		case ID_MENU_CONFIG_SOUND_ENABLE:
			if (GetMenuState(hMenu, ID_MENU_CONFIG_SOUND_ENABLE, MF_BYCOMMAND) == MF_CHECKED)
			{
				RegistryInfo.EnableSound = FALSE;
				CheckMenuItem(hMenu, ID_MENU_CONFIG_SOUND_ENABLE, MF_UNCHECKED);
				EnableMenuItem(hMenu, ID_MENU_CONFIG_SOUND_RECORD, MF_BYCOMMAND | MF_GRAYED);
			}
			else
			{
				RegistryInfo.EnableSound = TRUE;
				CheckMenuItem(hMenu, ID_MENU_CONFIG_SOUND_ENABLE, MF_CHECKED);
				EnableMenuItem(hMenu, ID_MENU_CONFIG_SOUND_RECORD, MF_BYCOMMAND | MF_ENABLED);
			}
			break;

		case ID_MENU_CONFIG_SOUND_RECORD:
			if (GetMenuState(hMenu, ID_MENU_CONFIG_SOUND_RECORD, MF_BYCOMMAND) == MF_CHECKED)
			{
				RecordSound    = FALSE;
				RecordingSound = FALSE;
				CheckMenuItem(hMenu, ID_MENU_CONFIG_SOUND_RECORD, MF_UNCHECKED);
			}
			else
			{
				RecordSound = TRUE;
				MessageBox(hwnd, "Sound will begin recording when the\nnext game is loaded, or the CPU is reset.", "Record sound output", MB_OK | MB_ICONEXCLAMATION);
				CheckMenuItem(hMenu, ID_MENU_CONFIG_SOUND_RECORD, RecordSound? MF_CHECKED : MF_UNCHECKED);
			}
			break;

		case ID_MENU_CONFIG_SOUND_44100:
			SetSoundFrequency(RegistryInfo.SoundFrequency = 44100);
			break;

		case ID_MENU_CONFIG_SOUND_22050:
			// Pick nearest divisible by 50 & 60
			SetSoundFrequency(RegistryInfo.SoundFrequency = 22200);
			break;

		case ID_MENU_CONFIG_SOUND_11025:
			// Pick nearest divisible by 50 & 60
			SetSoundFrequency(RegistryInfo.SoundFrequency = 11100);
			break;

		case ID_MENU_CONFIG_REGION_JAPAN:
			SetRegion(RegistryInfo.Region = sms.country = TYPE_DOMESTIC);
			break;

		case ID_MENU_CONFIG_REGION_EUROPEUS:
			SetRegion(RegistryInfo.Region = sms.country = TYPE_OVERSEAS);
			break;

		case ID_MENU_CONFIG_CONTROLS:
			DialogBox(hInstance, MAKEINTRESOURCE(IDD_CONTROLS), hwnd, ConfigureControlsProc);
			TidyInput();
			InitInput(hwnd, hInstance);
			break;

		case ID_MENU_CONFIG_SETTINGS:
			DialogBox(hInstance, MAKEINTRESOURCE(IDD_SETTINGS), hwnd, SettingsProc);
			break;

		case ID_MENU_HELP_ABOUT:
			DialogBox(hInstance, MAKEINTRESOURCE(IDD_ABOUT), hwnd, AboutProc);
			break;

		default:
			return TRUE;
		}
		break;

	case WM_ENTERMENULOOP:
		{
			char			Filename[MAX_PATH];
			int				Found;
			int				AppendPos;

			wsprintf(Filename, "%s%s", RegistryInfo.SaveStatePath, GetGameName());
			Found = CountSaveStateFiles(Filename, &AppendPos);

			EnableMenuItem(hMenu, ID_MENU_CPU_LOAD_STATE, Found? (MF_BYCOMMAND | MF_ENABLED) : (MF_BYCOMMAND | MF_GRAYED));
			EnableMenuItem(hMenu, ID_MENU_CPU_SAVE_STATE, RunEmulation? (MF_BYCOMMAND | MF_ENABLED) : (MF_BYCOMMAND | MF_GRAYED));
		
			StopAudio();
			
			if (UseDirectDraw && RegistryInfo.EnableDirectDraw && FullScreenMode()) FlipToGDISurface(TRUE);
		}
		break;

	case WM_EXITMENULOOP:

⌨️ 快捷键说明

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