📄 main.c
字号:
Frame = 0;
LastTickCount = 0;
if (UseDirectDraw && RegistryInfo.EnableDirectDraw && FullScreenMode()) FlipToGDISurface(FALSE);
break;
case WM_PAINT:
if (UseDirectDraw && RegistryInfo.EnableDirectDraw)
{
PAINTSTRUCT PaintStruct;
BeginPaint(hwnd, &PaintStruct);
EndPaint(hwnd, &PaintStruct);
UpdateTexture();
DrawTexture();
FlipScreens();
}
else
{
HDC hDC;
HDRAWDIB hDrawDib;
PAINTSTRUCT PaintStruct;
int Scale = RegistryInfo.ScreenScale;
BeginPaint(hwnd, &PaintStruct);
EndPaint(hwnd, &PaintStruct);
hDC = GetDC(hwnd);
hDrawDib = DrawDibOpen();
if (cart.type == TYPE_GG)
{
DrawDibBegin(hDrawDib, hDC, Bmp.BitmapInfoHeader.biWidth - 96, Bmp.BitmapInfoHeader.biHeight - 48, &Bmp.BitmapInfoHeader,
Bmp.BitmapInfoHeader.biWidth, Bmp.BitmapInfoHeader.biHeight, DDF_BACKGROUNDPAL);
DrawDibDraw(hDrawDib, hDC, 0, 0, (Bmp.BitmapInfoHeader.biWidth - 96) * Scale, (Bmp.BitmapInfoHeader.biHeight - 48) * Scale,
&Bmp.BitmapInfoHeader, &BitmapData[0], 48, 24, Bmp.BitmapInfoHeader.biWidth - 96, Bmp.BitmapInfoHeader.biHeight - 48, DDF_BACKGROUNDPAL);
}
else
{
DrawDibBegin(hDrawDib, hDC, Bmp.BitmapInfoHeader.biWidth, Bmp.BitmapInfoHeader.biHeight, &Bmp.BitmapInfoHeader,
Bmp.BitmapInfoHeader.biWidth, Bmp.BitmapInfoHeader.biHeight, DDF_BACKGROUNDPAL);
DrawDibDraw(hDrawDib, hDC, 0, 0, Bmp.BitmapInfoHeader.biWidth * Scale, Bmp.BitmapInfoHeader.biHeight * Scale,
&Bmp.BitmapInfoHeader, &BitmapData[0], 0, 0, Bmp.BitmapInfoHeader.biWidth, Bmp.BitmapInfoHeader.biHeight, DDF_BACKGROUNDPAL);
}
DrawDibEnd(hDrawDib);
DrawDibClose(hDrawDib);
ReleaseDC(hwnd, hDC);
}
break;
case WM_CLOSE:
DeleteObject(hBitmap);
DestroyWindow(hwnd);
break;
case WM_DESTROY:
SaveSRAM();
PostQuitMessage(0);
break;
default:
if (msg == USER_MESSAGE)
{
SaveSRAM();
OpenROM((char *)lParam);
SendMessage(hwnd, WM_ACTIVATE, WA_CLICKACTIVE, (long)hwnd);
SendMessage(hwnd, WM_NCACTIVATE, TRUE, 0);
break;
}
else
{
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
return FALSE;
}
void AdjustWindowSize(void)
{
if (!FullScreenMode())
{
RECT Rect;
GetConsoleScreenRect(&Rect);
Rect.right = (Rect.right - Rect.left) * RegistryInfo.ScreenScale;
Rect.bottom = (Rect.bottom - Rect.top) * RegistryInfo.ScreenScale;
Rect.top = 0;
Rect.left = 0;
AdjustWindowRect(&Rect, GetWindowLong(hwnd, GWL_STYLE), GetMenu(hwnd)? TRUE : FALSE);
SetWindowPos(hwnd, NULL, 0, 0, Rect.right - Rect.left, Rect.bottom - Rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
if (UseDirectDraw && RegistryInfo.EnableDirectDraw) UpdateModeWindowCoords(hwnd);
}
void InitVRAM(void)
{
/* Initialize display bitmap */
memset(&bitmap, 0, sizeof(t_bitmap));
bitmap.width = 256;
bitmap.height = 192;
bitmap.depth = 8;
bitmap.pitch = (bitmap.width * (bitmap.depth >> 3));
bitmap.data = (unsigned char *)&BitmapData[0];
}
void UpdatePalette(void)
{
unsigned char r, g, b;
int index;
if (bitmap.pal.update == 0) return;
for (index = 0; index < 32; index++)
{
if(bitmap.pal.color[index])
{
if (UseDirectDraw && RegistryInfo.EnableDirectDraw)
{
b = bitmap.pal.color[index][0];
g = bitmap.pal.color[index][1];
r = bitmap.pal.color[index][2];
}
else
{
r = bitmap.pal.color[index][0];
g = bitmap.pal.color[index][1];
b = bitmap.pal.color[index][2];
}
r = (unsigned char)(255.0f * pow((float)r / 255.0f, 1.0f / RegistryInfo.Gamma) + 0.5f);
g = (unsigned char)(255.0f * pow((float)g / 255.0f, 1.0f / RegistryInfo.Gamma) + 0.5f);
b = (unsigned char)(255.0f * pow((float)b / 255.0f, 1.0f / RegistryInfo.Gamma) + 0.5f);
pixel[index] = MAKE_PIXEL(b, g, r);
Bmp.Palette[0x00 | index].rgbRed = r;
Bmp.Palette[0x00 | index].rgbGreen = g;
Bmp.Palette[0x00 | index].rgbBlue = b;
Bmp.Palette[0x20 | index].rgbRed = r;
Bmp.Palette[0x20 | index].rgbGreen = g;
Bmp.Palette[0x20 | index].rgbBlue = b;
Bmp.Palette[0x40 | index].rgbRed = r;
Bmp.Palette[0x40 | index].rgbGreen = g;
Bmp.Palette[0x40 | index].rgbBlue = b;
}
}
bitmap.pal.update = 0;
memset(bitmap.pal.dirty, 0, 32);
}
void OpenROM(char *pROM)
{
HANDLE FileHandle;
char Filename[MAX_PATH] = "";
int FileSize;
int BytesRead;
int i;
if (RecordingSound)
{
CloseSoundRecording();
RecordSound = FALSE;
RecordingSound = FALSE;
CheckMenuItem(hMenu, ID_MENU_CONFIG_SOUND_RECORD, MF_UNCHECKED);
}
if (pROM)
{
strcpy(Filename, pROM);
}
else
{
// Initialise the file dialog
InitFileDialog(hwnd, RegistryInfo.ROMPath, "Roms (*.gg, *.sms, *.zip)\0*.gg;*.sms;*.zip\0All Files (*.*)\0*.*\0", 0);
// Show the dialog, and return if it is cancelled
if (!GetLoadFileFromDialog(hwnd, "Open", Filename)) return;
}
if (!stricmp(&Filename[strlen(Filename) - 3], "zip"))
{
if (!DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_ZIP), hwnd, LoadZipProc, (long)Filename)) return;
if (!LoadSelectedFileFromZip(Filename)) return;
}
else
{
FileHandle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (FileHandle == INVALID_HANDLE_VALUE) return;
FileSize = GetFileSize(FileHandle, NULL);
if (FileSize < 0x8000)
{
CloseHandle(FileHandle);
return;
}
if ((FileSize / 512) & 1)
{
SetFilePointer(FileHandle, 512, 0, FILE_CURRENT);
FileSize -= 512;
}
if (!stricmp(&Filename[strlen(Filename) - 2], "gg"))
{
cart.type = TYPE_GG;
}
else
{
cart.type = TYPE_SMS;
}
cart.pages = (FileSize / 0x4000);
if (cart.rom) free(cart.rom);
cart.rom = malloc(FileSize);
if (!cart.rom)
{
CloseHandle(FileHandle);
return;
}
ReadFile(FileHandle, cart.rom, FileSize, &BytesRead, NULL);
CloseHandle(FileHandle);
}
system_init(RegistryInfo.SoundFrequency, RegistryInfo.UpdateFrequency);
system_reset();
sms.country = RegistryInfo.Region;
sms.use_fm = RegistryInfo.EnableFMSound;
snd.callback = UpdateSoundRecording;
for (i = strlen(Filename) - 1 ; i >= 0 ; i--)
{
if (Filename[i] == '\\' || Filename[i] == '/')
{
break;
}
}
strcpy(GameName, &Filename[i + 1]);
strcpy(strrchr(GameName, '.'), "");
LoadSRAM();
SetWindowText(hwnd, GameName);
AdjustWindowSize();
RunEmulation = TRUE;
if (RecordSound)
{
CreateSoundRecording();
RecordingSound = TRUE;
}
}
char *GetGameName(void)
{
return GameName;
}
char *GetBitmapInfoHeader(void)
{
return (char *)&Bmp;
}
char *GetBitmapData(void)
{
return BitmapData;
}
void LoadSRAM(void)
{
HANDLE FileHandle;
int BytesRead;
char Filename[MAX_PATH];
wsprintf(Filename, "%s%s.sav", RegistryInfo.SRAMPath, GameName);
FileHandle = CreateFile(Filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (FileHandle == INVALID_HANDLE_VALUE) return;
ReadFile(FileHandle, sms.sram, 0x8000, &BytesRead, NULL);
CloseHandle(FileHandle);
sms.save = 1;
}
void SaveSRAM(void)
{
HANDLE FileHandle;
int BytesWritten;
char Filename[MAX_PATH];
wsprintf(Filename, "%s%s.sav", RegistryInfo.SRAMPath, GameName);
if (sms.save && strlen(GameName))
{
FileHandle = CreateFile(Filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (FileHandle == INVALID_HANDLE_VALUE) return;
WriteFile(FileHandle, sms.sram, 0x8000, &BytesWritten, NULL);
CloseHandle (FileHandle);
}
}
LRESULT CALLBACK ConfigureControlsProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_INITDIALOG:
{
int i;
CenterWindowInParent(hwnd);
PopulateJoystickCombo(hwnd, PLAYER_1);
PopulateJoystickCombo(hwnd, PLAYER_2);
PopulateConfigureControls(hwnd);
CheckDlgButton(hwnd, IDC_P1_BUTTON1_RAPIDFIRE_CHECK, RegistryInfo.RapidFire[PLAYER_1][PAD_BUTTON1 - PAD_BUTTON1]? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwnd, IDC_P1_BUTTON2_RAPIDFIRE_CHECK, RegistryInfo.RapidFire[PLAYER_1][PAD_BUTTON2 - PAD_BUTTON1]? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwnd, IDC_P2_BUTTON1_RAPIDFIRE_CHECK, RegistryInfo.RapidFire[PLAYER_2][PAD_BUTTON1 - PAD_BUTTON1]? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwnd, IDC_P2_BUTTON2_RAPIDFIRE_CHECK, RegistryInfo.RapidFire[PLAYER_2][PAD_BUTTON2 - PAD_BUTTON1]? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwnd, IDC_P1_DISABLE_KEYS_CHECK, RegistryInfo.DisableKeys[PLAYER_1]? BST_CHECKED : BST_UNCHECKED);
CheckDlgButton(hwnd, IDC_P2_DISABLE_KEYS_CHECK, RegistryInfo.DisableKeys[PLAYER_2]? BST_CHECKED : BST_UNCHECKED);
EnableWindow(GetDlgItem(hwnd, IDC_P1_DISABLE_KEYS_CHECK), GetSelectedJoystick(PLAYER_1)? TRUE : FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_P2_DISABLE_KEYS_CHECK), GetSelectedJoystick(PLAYER_2)? TRUE : FALSE);
for (i = 0 ; i < MAX_PLAYERS ; i++)
{
HWND hCombo = (i == PLAYER_1)? GetDlgItem(hwnd, IDC_P1_RAPIDFIRE_COMBO) : GetDlgItem(hwnd, IDC_P2_RAPIDFIRE_COMBO);
int j;
SendMessage(hCombo, CB_RESETCONTENT, 0, 0);
for (j = 2 ; j <= 10 ; j++)
{
char String[32];
char PostFix[4];
if (j == 2) strcpy(PostFix, "nd");
else if (j == 3) strcpy(PostFix, "rd");
else strcpy(PostFix, "th");
wsprintf(String, "Every %d%s frame", j, PostFix);
SendMessage(hCombo, CB_ADDSTRING, 0, (long)String);
}
SendMessage(hCombo, CB_SETCURSEL, RegistryInfo.RapidFireRate[i] - 2, 0);
}
ShowWindow(hwnd, SW_SHOW);
}
break;
case WM_COMMAND:
{
switch (HIWORD(wParam))
{
case BN_CLICKED:
switch (LOWORD (wParam))
{
case IDC_P1_LEFT_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_LEFT, IDC_P1_LEFT, "'Player 1 Left'");
break;
case IDC_P1_RIGHT_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_RIGHT, IDC_P1_RIGHT, "'Player 1 Right'");
break;
case IDC_P1_UP_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_UP, IDC_P1_UP, "'Player 1 Up'");
break;
case IDC_P1_DOWN_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_DOWN, IDC_P1_DOWN, "'Player 1 Down'");
break;
case IDC_P1_BUTTON1_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_BUTTON1, IDC_P1_BUTTON1, "'Player 1 Button 1'");
break;
case IDC_P1_BUTTON2_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_BUTTON2, IDC_P1_BUTTON2, "'Player 1 Button 2'");
break;
case IDC_P1_START_BUTTON:
ConfigureButton(hwnd, PLAYER_1, PAD_START, IDC_P1_START, "'Player 1 Start / Pause'");
break;
case IDC_P2_LEFT_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_LEFT, IDC_P2_LEFT, "'Player 2 Left'");
break;
case IDC_P2_RIGHT_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_RIGHT, IDC_P2_RIGHT, "'Player 2 Right'");
break;
case IDC_P2_UP_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_UP, IDC_P2_UP, "'Player 2 Up'");
break;
case IDC_P2_DOWN_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_DOWN, IDC_P2_DOWN, "'Player 2 Down'");
break;
case IDC_P2_BUTTON1_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_BUTTON1, IDC_P2_BUTTON1, "'Player 2 Button 1'");
break;
case IDC_P2_BUTTON2_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_BUTTON2, IDC_P2_BUTTON2, "'Player 2 Button 2'");
break;
case IDC_P2_START_BUTTON:
ConfigureButton(hwnd, PLAYER_2, PAD_START, IDC_P2_START, "'Player 2 Start / Pause'");
break;
case IDC_P1_BUTTON1_RAPIDFIRE_CHECK:
RegistryInfo.RapidFire[PLAYER_1][PAD_BUTTON1 - PAD_BUTTON1] ^= 1;
break;
case IDC_P1_BUTTON2_RAPIDFIRE_CHECK:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -