mirror of
https://github.com/pj64team/Project64-Legacy.git
synced 2026-04-02 04:36:25 +00:00
Changes to Recent Rom and Rom Directory Lists, Save State Numbering and shortcut, Input default changed to NRage Legacy. Removed Release_External and replaced with Release.
1529 lines
44 KiB
C
1529 lines
44 KiB
C
/*
|
|
* Project 64 - A Nintendo 64 emulator.
|
|
*
|
|
* (c) Copyright 2001 zilmar (zilmar@emulation64.com) and
|
|
* Jabo (jabo@emulation64.com).
|
|
*
|
|
* pj64 homepage: www.pj64.net
|
|
*
|
|
* Permission to use, copy, modify and distribute Project64 in both binary and
|
|
* source form, for non-commercial purposes, is hereby granted without fee,
|
|
* providing that this license information and copyright notice appear with
|
|
* all copies and any derived work.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty. In no event shall the authors be held liable for any damages
|
|
* arising from the use of this software.
|
|
*
|
|
* Project64 is freeware for PERSONAL USE only. Commercial users should
|
|
* seek permission of the copyright holders first. Commercial use includes
|
|
* charging money for Project64 or software derived from Project64.
|
|
*
|
|
* The copyright holders request that bug fixes and improvements to the code
|
|
* should be forwarded to them so if they want them.
|
|
*
|
|
*/
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include <stdio.h>
|
|
#include "main.h"
|
|
#include "cpu.h"
|
|
#include "memory.h"
|
|
#include "debugger.h"
|
|
#include "plugin.h"
|
|
#include "cheats.h"
|
|
#include "Compression/unzip.h"
|
|
#include "EmulateAI.h"
|
|
#include "resource.h"
|
|
#include "RomTools_Common.h"
|
|
|
|
#define MenuLocOfUsedFiles 12
|
|
#define MenuLocOfUsedDirs (MenuLocOfUsedFiles + 1)
|
|
|
|
DWORD RomFileSize;
|
|
int RomRamSize, RomSaveUsing, RomCPUType, RomSelfMod,
|
|
RomUseTlb, RomUseLinking, RomCF, RomUseLargeBuffer, RomUseCache,
|
|
RomDelaySI, RomSPHack, RomAudioSignal, RomEmulateAI, RomModVIS;
|
|
char CurrentFileName[MAX_PATH + 1] = { "" }, RomName[MAX_PATH + 1] = { "" }, RomFullName[MAX_PATH + 1] = { "" };
|
|
char LastRoms[10][MAX_PATH + 1], LastDirs[10][MAX_PATH + 1];
|
|
BYTE RomHeader[0x1000];
|
|
DWORD PrevCRC1, PrevCRC2;
|
|
|
|
BOOL IsValidRomImage(BYTE Test[4]);
|
|
|
|
void AddRecentDir(HWND hWnd, char* addition) {
|
|
int count;
|
|
|
|
if (addition != NULL && RomDirsToRemember > 0) {
|
|
char Dir[MAX_PATH + 1];
|
|
BOOL bFound = FALSE;
|
|
|
|
strcpy(Dir, addition);
|
|
for (count = 0; count < RomDirsToRemember && !bFound; count++) {
|
|
if (strcmp(addition, LastDirs[count]) == 0) {
|
|
if (count != 0) {
|
|
memmove(&LastDirs[1], &LastDirs[0], sizeof(LastDirs[0]) * count);
|
|
}
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bFound == FALSE) { memmove(&LastDirs[1], &LastDirs[0], sizeof(LastDirs[0]) * (RomDirsToRemember - 1)); }
|
|
strcpy(LastDirs[0], Dir);
|
|
SaveRecentDirs();
|
|
}
|
|
SetupMenu(hMainWindow);
|
|
}
|
|
|
|
void AddRecentFile(HWND hWnd, char* addition) {
|
|
int count;
|
|
|
|
if (addition != NULL && RomsToRemember > 0) {
|
|
char Rom[MAX_PATH + 1];
|
|
BOOL bFound = FALSE;
|
|
|
|
strcpy(Rom, addition);
|
|
for (count = 0; count < RomsToRemember && !bFound; count++) {
|
|
if (strcmp(addition, LastRoms[count]) == 0) {
|
|
if (count != 0) {
|
|
memmove(&LastRoms[1], &LastRoms[0], sizeof(LastRoms[0]) * count);
|
|
}
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if (bFound == FALSE) { memmove(&LastRoms[1], &LastRoms[0], sizeof(LastRoms[0]) * (RomsToRemember - 1)); }
|
|
strcpy(LastRoms[0], Rom);
|
|
SaveRecentFiles();
|
|
}
|
|
SetupMenu(hMainWindow);
|
|
}
|
|
|
|
void ByteSwapRom(BYTE* Rom, DWORD RomLen) {
|
|
DWORD count;
|
|
|
|
// Comment this out for now, otherwise it causes a hang with the new LoadRomRecalcCRCs
|
|
//SendMessage( hStatusWnd, SB_SETTEXT, 0, (LPARAM)GS(MSG_BYTESWAP) );
|
|
switch (*((DWORD*)&Rom[0])) {
|
|
case 0x12408037:
|
|
for (count = 0; count < RomLen; count += 4) {
|
|
Rom[count] ^= Rom[count + 2];
|
|
Rom[count + 2] ^= Rom[count];
|
|
Rom[count] ^= Rom[count + 2];
|
|
Rom[count + 1] ^= Rom[count + 3];
|
|
Rom[count + 3] ^= Rom[count + 1];
|
|
Rom[count + 1] ^= Rom[count + 3];
|
|
}
|
|
break;
|
|
case 0x40072780:
|
|
case 0x40123780:
|
|
for (count = 0; count < RomLen; count += 4) {
|
|
Rom[count] ^= Rom[count + 3];
|
|
Rom[count + 3] ^= Rom[count];
|
|
Rom[count] ^= Rom[count + 3];
|
|
Rom[count + 1] ^= Rom[count + 2];
|
|
Rom[count + 2] ^= Rom[count + 1];
|
|
Rom[count + 1] ^= Rom[count + 2];
|
|
}
|
|
break;
|
|
case 0x80371240: break;
|
|
//default:
|
|
//DisplayError(GS(MSG_UNKNOWN_FILE_FORMAT));
|
|
}
|
|
}
|
|
|
|
int ChooseN64RomToOpen(void) {
|
|
OPENFILENAME openfilename;
|
|
char FileName[256], Directory[255];
|
|
|
|
memset(&FileName, 0, sizeof(FileName));
|
|
memset(&openfilename, 0, sizeof(openfilename));
|
|
|
|
Settings_GetDirectory(RomDir, Directory, sizeof(Directory));
|
|
|
|
openfilename.lStructSize = sizeof(openfilename);
|
|
openfilename.hwndOwner = hMainWindow;
|
|
openfilename.lpstrFilter = "N64 ROMs (*.zip, *.?64, *.rom, *.usa, *.jap, *.pal, *.bin)\0*.?64;*.zip;*.bin;*.rom;*.usa;*.jap;*.pal\0All files (*.*)\0*.*\0";
|
|
openfilename.lpstrFile = FileName;
|
|
openfilename.lpstrInitialDir = Directory;
|
|
openfilename.nMaxFile = MAX_PATH;
|
|
openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
|
|
|
|
if (GetOpenFileName(&openfilename)) {
|
|
strcpy(CurrentFileName, FileName);
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void EnableOpenMenuItems(void) {
|
|
SetupMenu(hMainWindow);
|
|
}
|
|
|
|
BOOL IsValidRomImage(BYTE Test[4]) {
|
|
if (*((DWORD*)&Test[0]) == 0x40123780) { return TRUE; }
|
|
if (*((DWORD*)&Test[0]) == 0x12408037) { return TRUE; }
|
|
if (*((DWORD*)&Test[0]) == 0x80371240) { return TRUE; }
|
|
if (*((DWORD*)&Test[0]) == 0x40072780) { return TRUE; }
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL LoadDataFromRomFile(char* FileName, BYTE* Data, int DataLen, int* RomSize) {
|
|
BYTE Test[4];
|
|
int count;
|
|
|
|
if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0) {
|
|
int len, port = 0, FoundRom;
|
|
unz_file_info info;
|
|
char zname[132];
|
|
unzFile file;
|
|
file = unzOpen(FileName);
|
|
if (file == NULL) { return FALSE; }
|
|
|
|
port = unzGoToFirstFile(file);
|
|
FoundRom = FALSE;
|
|
while (port == UNZ_OK && FoundRom == FALSE) {
|
|
unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0);
|
|
if (unzLocateFile(file, zname, 1) != UNZ_OK) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
if (unzOpenCurrentFile(file) != UNZ_OK) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
unzReadCurrentFile(file, Test, 4);
|
|
if (IsValidRomImage(Test)) {
|
|
FoundRom = TRUE;
|
|
RomFileSize = info.uncompressed_size;
|
|
memcpy(Data, Test, 4);
|
|
len = unzReadCurrentFile(file, &Data[4], DataLen - 4) + 4;
|
|
|
|
if ((int)DataLen != len) {
|
|
unzCloseCurrentFile(file);
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
*RomSize = info.uncompressed_size;
|
|
if (unzCloseCurrentFile(file) == UNZ_CRCERROR) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
unzClose(file);
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzCloseCurrentFile(file);
|
|
port = unzGoToNextFile(file);
|
|
}
|
|
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
DWORD dwRead;
|
|
HANDLE hFile;
|
|
|
|
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) { return FALSE; }
|
|
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
ReadFile(hFile, Test, 4, &dwRead, NULL);
|
|
if (!IsValidRomImage(Test)) { CloseHandle(hFile); return FALSE; }
|
|
RomFileSize = GetFileSize(hFile, NULL);
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
if (!ReadFile(hFile, Data, DataLen, &dwRead, NULL)) { CloseHandle(hFile); return FALSE; }
|
|
*RomSize = GetFileSize(hFile, NULL);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
switch (*((DWORD*)&Data[0])) {
|
|
case 0x12408037:
|
|
for (count = 0; count < DataLen; count += 4) {
|
|
Data[count] ^= Data[count + 2];
|
|
Data[count + 2] ^= Data[count];
|
|
Data[count] ^= Data[count + 2];
|
|
Data[count + 1] ^= Data[count + 3];
|
|
Data[count + 3] ^= Data[count + 1];
|
|
Data[count + 1] ^= Data[count + 3];
|
|
}
|
|
break;
|
|
case 0x40072780:
|
|
case 0x40123780:
|
|
for (count = 0; count < DataLen; count += 4) {
|
|
Data[count] ^= Data[count + 3];
|
|
Data[count + 3] ^= Data[count];
|
|
Data[count] ^= Data[count + 3];
|
|
Data[count + 1] ^= Data[count + 2];
|
|
Data[count + 2] ^= Data[count + 1];
|
|
Data[count + 1] ^= Data[count + 2];
|
|
}
|
|
break;
|
|
case 0x80371240: break;
|
|
}
|
|
|
|
// Made a bad assumption here, this function is also called by the rom browser on scan so doing a full check of the crc causes a massive slowdown
|
|
// Only do a check when the CRCs both read 0
|
|
PrevCRC1 = *(DWORD*)&Data[0x10];
|
|
PrevCRC2 = *(DWORD*)&Data[0x14];
|
|
if (*(DWORD*)&Data[0x10] == 0 && *(DWORD*)&Data[0x14] == 0) {
|
|
LoadRomRecalcCRCs(FileName, &Data[0x10], &Data[0x14]);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CreateRecentDirList(HMENU hMenu) {
|
|
char String[256], * read;
|
|
int count;
|
|
HMENU hSubMenu;
|
|
MENUITEMINFO menuinfo;
|
|
|
|
for (count = 0; count < RomDirsToRemember; count++) {
|
|
sprintf(String, "RecentDir%d", count + 1);
|
|
Settings_Read(APPS_NAME, "Directories", String, "", &read);
|
|
strncpy(LastDirs[count], read, sizeof(LastDirs[count]));
|
|
if (read) free(read);
|
|
}
|
|
|
|
hSubMenu = GetSubMenu(hMenu, 0);
|
|
DeleteMenu(hSubMenu, MenuLocOfUsedDirs, MF_BYPOSITION);
|
|
if (BasicMode || !RomListVisible()) { return; }
|
|
memset(&menuinfo, 0, sizeof(MENUITEMINFO));
|
|
menuinfo.cbSize = sizeof(MENUITEMINFO);
|
|
menuinfo.fMask = MIIM_TYPE | MIIM_ID;
|
|
menuinfo.fType = MFT_STRING;
|
|
menuinfo.fState = MFS_ENABLED;
|
|
menuinfo.dwTypeData = String;
|
|
menuinfo.cch = 256;
|
|
|
|
sprintf(String, "None");
|
|
InsertMenuItem(hSubMenu, MenuLocOfUsedDirs, TRUE, &menuinfo);
|
|
hSubMenu = CreateMenu();
|
|
|
|
if (strlen(LastDirs[0]) == 0) {
|
|
menuinfo.wID = ID_FILE_RECENT_DIR;
|
|
sprintf(String, "None");
|
|
InsertMenuItem(hSubMenu, 0, TRUE, &menuinfo);
|
|
}
|
|
menuinfo.fMask = MIIM_TYPE | MIIM_ID;
|
|
for (count = 0; count < RomDirsToRemember; count++) {
|
|
if (strlen(LastDirs[count]) == 0) { break; }
|
|
menuinfo.wID = ID_FILE_RECENT_DIR + count;
|
|
|
|
// Changed (count + 1) % 10, to (count + 1), So it no longer forces Rom 10 to Rom 0 position in Recent List, because that makes more sense right? - Icepir8
|
|
|
|
sprintf(String, "&%d %s", (count + 1), LastDirs[count]);
|
|
InsertMenuItem(hSubMenu, count, TRUE, &menuinfo);
|
|
}
|
|
ModifyMenu(GetSubMenu(hMenu, 0), MenuLocOfUsedDirs, MF_POPUP | MF_BYPOSITION, (DWORD)hSubMenu, GS(MENU_RECENT_DIR));
|
|
if (strlen(LastDirs[0]) == 0 || CPURunning || RomDirsToRemember == 0) {
|
|
EnableMenuItem(GetSubMenu(hMenu, 0), MenuLocOfUsedDirs, MF_BYPOSITION | MFS_DISABLED);
|
|
}
|
|
else {
|
|
EnableMenuItem(GetSubMenu(hMenu, 0), MenuLocOfUsedDirs, MF_BYPOSITION | MFS_ENABLED);
|
|
}
|
|
}
|
|
|
|
void CreateRecentFileList(HMENU hMenu) {
|
|
char String[256], * read;
|
|
int count;
|
|
|
|
for (count = 0; count < RomsToRemember; count++) {
|
|
sprintf(String, "RecentFile%d", count + 1);
|
|
Settings_Read(APPS_NAME, "Directories", String, "", &read);
|
|
strncpy(LastRoms[count], read, sizeof(LastRoms[count]));
|
|
if (read) free(read);
|
|
}
|
|
|
|
if (BasicMode || !RomListVisible()) {
|
|
HMENU hSubMenu;
|
|
MENUITEMINFO menuinfo;
|
|
|
|
hSubMenu = GetSubMenu(hMenu, 0);
|
|
DeleteMenu(hSubMenu, MenuLocOfUsedFiles, MF_BYPOSITION);
|
|
if (strlen(LastRoms[0]) == 0) {
|
|
DeleteMenu(hSubMenu, MenuLocOfUsedFiles, MF_BYPOSITION);
|
|
}
|
|
|
|
memset(&menuinfo, 0, sizeof(MENUITEMINFO));
|
|
menuinfo.cbSize = sizeof(MENUITEMINFO);
|
|
menuinfo.fMask = MIIM_TYPE | MIIM_ID;
|
|
menuinfo.fType = MFT_STRING;
|
|
menuinfo.fState = MFS_ENABLED;
|
|
menuinfo.dwTypeData = String;
|
|
menuinfo.cch = 256;
|
|
for (count = 0; count < RomsToRemember; count++) {
|
|
if (strlen(LastRoms[count]) == 0) { break; }
|
|
menuinfo.wID = ID_FILE_RECENT_FILE + count;
|
|
|
|
// Changed (count + 1) % 10, to (count + 1), So it no longer forces Rom 10 to Rom 0 position in Recent List, because that makes more sense right? - Icepir8
|
|
|
|
sprintf(String, "&%d %s", (count + 1), LastRoms[count]);
|
|
InsertMenuItem(hSubMenu, MenuLocOfUsedFiles + count, TRUE, &menuinfo);
|
|
}
|
|
}
|
|
else {
|
|
HMENU hSubMenu;
|
|
MENUITEMINFO menuinfo;
|
|
|
|
memset(&menuinfo, 0, sizeof(MENUITEMINFO));
|
|
menuinfo.cbSize = sizeof(MENUITEMINFO);
|
|
menuinfo.fMask = MIIM_TYPE | MIIM_ID;
|
|
menuinfo.fType = MFT_STRING;
|
|
menuinfo.fState = MFS_ENABLED;
|
|
menuinfo.dwTypeData = String;
|
|
menuinfo.cch = 256;
|
|
|
|
hSubMenu = GetSubMenu(hMenu, 0);
|
|
DeleteMenu(hSubMenu, MenuLocOfUsedFiles, MF_BYPOSITION);
|
|
sprintf(String, "None");
|
|
InsertMenuItem(hSubMenu, MenuLocOfUsedFiles, TRUE, &menuinfo);
|
|
hSubMenu = CreateMenu();
|
|
|
|
if (strlen(LastRoms[0]) == 0) {
|
|
menuinfo.wID = ID_FILE_RECENT_DIR;
|
|
sprintf(String, "None");
|
|
InsertMenuItem(hSubMenu, 0, TRUE, &menuinfo);
|
|
}
|
|
menuinfo.fMask = MIIM_TYPE | MIIM_ID;
|
|
for (count = 0; count < RomsToRemember; count++) {
|
|
if (strlen(LastRoms[count]) == 0) { break; }
|
|
menuinfo.wID = ID_FILE_RECENT_FILE + count;
|
|
|
|
// Changed (count + 1) % 10, to (count + 1), So it no longer forces Rom 10 to Rom 0 position in Recent List, because that makes more sense right? - Icepir8
|
|
|
|
sprintf(String, "&%d %s", (count + 1), LastRoms[count]);
|
|
InsertMenuItem(hSubMenu, count, TRUE, &menuinfo);
|
|
}
|
|
ModifyMenu(GetSubMenu(hMenu, 0), MenuLocOfUsedFiles, MF_POPUP | MF_BYPOSITION, (DWORD)hSubMenu, GS(MENU_RECENT_ROM));
|
|
if (strlen(LastRoms[0]) == 0) {
|
|
EnableMenuItem(GetSubMenu(hMenu, 0), MenuLocOfUsedFiles, MF_BYPOSITION | MFS_DISABLED);
|
|
}
|
|
else {
|
|
EnableMenuItem(GetSubMenu(hMenu, 0), MenuLocOfUsedFiles, MF_BYPOSITION | MFS_ENABLED);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LoadRecentRom(DWORD Index) {
|
|
DWORD ThreadID;
|
|
|
|
Index -= ID_FILE_RECENT_FILE;
|
|
if (Index < 0 || Index >(DWORD)RomsToRemember) { return; }
|
|
strcpy(CurrentFileName, LastRoms[Index]);
|
|
CreateThread(NULL, 0, OpenChosenFile, NULL, 0, &ThreadID);
|
|
}
|
|
|
|
|
|
BOOL LoadRomHeader(void) {
|
|
char drive[_MAX_DRIVE], FileName[_MAX_DIR], dir[_MAX_DIR], ext[_MAX_EXT];
|
|
BYTE Test[4];
|
|
int count;
|
|
|
|
if (_strnicmp(&CurrentFileName[strlen(CurrentFileName) - 4], ".ZIP", 4) == 0) {
|
|
int port = 0, FoundRom;
|
|
unz_file_info info;
|
|
char zname[132];
|
|
unzFile file;
|
|
file = unzOpen(CurrentFileName);
|
|
if (file == NULL) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
return FALSE;
|
|
}
|
|
|
|
port = unzGoToFirstFile(file);
|
|
FoundRom = FALSE;
|
|
while (port == UNZ_OK && FoundRom == FALSE) {
|
|
unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0);
|
|
if (unzLocateFile(file, zname, 1) != UNZ_OK) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_ZIP));
|
|
return FALSE;
|
|
}
|
|
if (unzOpenCurrentFile(file) != UNZ_OK) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
return FALSE;
|
|
}
|
|
unzReadCurrentFile(file, Test, 4);
|
|
if (IsValidRomImage(Test)) {
|
|
RomFileSize = info.uncompressed_size;
|
|
FoundRom = TRUE;
|
|
memcpy(RomHeader, Test, 4);
|
|
unzReadCurrentFile(file, &RomHeader[4], sizeof(RomHeader) - 4);
|
|
if (unzCloseCurrentFile(file) == UNZ_CRCERROR) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
return FALSE;
|
|
}
|
|
_splitpath(CurrentFileName, drive, dir, FileName, ext);
|
|
unzClose(file);
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzCloseCurrentFile(file);
|
|
port = unzGoToNextFile(file);
|
|
}
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
DWORD dwRead;
|
|
HANDLE hFile;
|
|
|
|
hFile = CreateFile(CurrentFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
return FALSE;
|
|
}
|
|
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
ReadFile(hFile, Test, 4, &dwRead, NULL);
|
|
if (!IsValidRomImage(Test)) {
|
|
CloseHandle(hFile);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_IMAGE));
|
|
return FALSE;
|
|
}
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
ReadFile(hFile, RomHeader, sizeof(RomHeader), &dwRead, NULL);
|
|
RomFileSize = GetFileSize(hFile, NULL); // Read rom size for uncompressed roms
|
|
CloseHandle(hFile);
|
|
}
|
|
ByteSwapRom(RomHeader, sizeof(RomHeader));
|
|
GetRomName(RomName, RomHeader);
|
|
if (strlen(RomName) == 0)
|
|
_splitpath(CurrentFileName, NULL, NULL, RomName, NULL);
|
|
GetRomFullName(RomFullName, RomHeader, CurrentFileName);
|
|
|
|
// Bad CRCs, we are forced to recalculate (This means loading the entire rom into memory)
|
|
PrevCRC1 = *(DWORD*)&RomHeader[0x10];
|
|
PrevCRC2 = *(DWORD*)&RomHeader[0x14];
|
|
if (*(DWORD*)&RomHeader[0x10] == 0 || *(DWORD*)&RomHeader[0x14] == 0)
|
|
LoadRomRecalcCRCs(CurrentFileName, &RomHeader[0x10], &RomHeader[0x14]);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void LoadRomOptions(void) {
|
|
DWORD NewRamSize;
|
|
|
|
ReadRomOptions();
|
|
|
|
NewRamSize = RomRamSize;
|
|
if ((int)RomRamSize < 0) { NewRamSize = SystemRdramSize; }
|
|
|
|
if (RomUseLargeBuffer) {
|
|
if (VirtualAlloc(RecompCode, LargeCompileBufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE) == NULL) {
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
ExitThread(0);
|
|
}
|
|
}
|
|
else {
|
|
VirtualFree(RecompCode, LargeCompileBufferSize, MEM_DECOMMIT);
|
|
if (VirtualAlloc(RecompCode, NormalCompileBufferSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE) == NULL) {
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
ExitThread(0);
|
|
}
|
|
}
|
|
if (NewRamSize != RdramSize) {
|
|
if (RdramSize == 0x400000) {
|
|
if (VirtualAlloc(N64MEM + 0x400000, 0x400000, MEM_COMMIT, PAGE_READWRITE) == NULL) {
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
ExitThread(0);
|
|
}
|
|
if (VirtualAlloc((BYTE*)JumpTable + 0x400000, 0x400000, MEM_COMMIT, PAGE_READWRITE) == NULL) {
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
ExitThread(0);
|
|
}
|
|
if (VirtualAlloc((BYTE*)DelaySlotTable + (0x400000 >> 0xA), (0x400000 >> 0xA), MEM_COMMIT, PAGE_READWRITE) == NULL) {
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
ExitThread(0);
|
|
}
|
|
}
|
|
else {
|
|
VirtualFree(N64MEM + 0x400000, 0x400000, MEM_DECOMMIT);
|
|
VirtualFree((BYTE*)JumpTable + 0x400000, 0x400000, MEM_DECOMMIT);
|
|
VirtualFree((BYTE*)DelaySlotTable + (0x400000 >> 0xA), (0x400000 >> 0xA), MEM_DECOMMIT);
|
|
}
|
|
}
|
|
RdramSize = NewRamSize;
|
|
CPU_Type = SystemCPU_Type;
|
|
if (HaveDebugger) { CPU_Type = CPU_Interpreter; }
|
|
else if (RomCPUType != CPU_Default) { CPU_Type = RomCPUType; }
|
|
CountPerOp = RomCF;
|
|
if (CountPerOp < 1 || CountPerOp > 6)
|
|
CountPerOp = Default_CountPerOp;
|
|
|
|
SaveUsing = RomSaveUsing;
|
|
SelfModCheck = SystemSelfModCheck;
|
|
if (RomSelfMod != ModCode_Default) { SelfModCheck = RomSelfMod; }
|
|
UseTlb = RomUseTlb;
|
|
DelaySI = RomDelaySI;
|
|
EmulateAI = RomEmulateAI;
|
|
AudioSignal = RomAudioSignal;
|
|
SPHack = RomSPHack;
|
|
UseLinking = SystemABL;
|
|
DisableRegCaching = !RomUseCache;
|
|
if (RomUseLinking == 0) { UseLinking = TRUE; }
|
|
if (RomUseLinking == 1) { UseLinking = FALSE; }
|
|
ModVI = RomModVIS;
|
|
|
|
switch (GetRomRegion(ROM)) {
|
|
case PAL_Region:
|
|
EmuAI_SetFrameRate(50);
|
|
Timer_Initialize((double)50); break;
|
|
case NTSC_Region:
|
|
default:
|
|
EmuAI_SetFrameRate(60);
|
|
Timer_Initialize((double)60); break;
|
|
}
|
|
}
|
|
|
|
void RemoveRecentDirList(HWND hWnd) {
|
|
HMENU hMenu;
|
|
int count;
|
|
|
|
hMenu = GetMenu(hWnd);
|
|
for (count = 0; count < RomDirsToRemember; count++) {
|
|
DeleteMenu(hMenu, ID_FILE_RECENT_DIR + count, MF_BYCOMMAND);
|
|
}
|
|
memset(LastRoms[0], 0, sizeof(LastRoms[0]));
|
|
}
|
|
|
|
void RemoveRecentList(HWND hWnd) {
|
|
HMENU hMenu;
|
|
int count;
|
|
|
|
hMenu = GetMenu(hWnd);
|
|
for (count = 0; count < RomsToRemember; count++) {
|
|
DeleteMenu(hMenu, ID_FILE_RECENT_FILE + count, MF_BYCOMMAND);
|
|
}
|
|
memset(LastRoms[0], 0, sizeof(LastRoms[0]));
|
|
}
|
|
|
|
void ReadRomOptions(void) {
|
|
RomRamSize = 0x800000;
|
|
RomSaveUsing = Auto;
|
|
RomCF = -1;
|
|
RomCPUType = CPU_Default;
|
|
RomSelfMod = ModCode_Default;
|
|
RomUseTlb = TRUE;
|
|
RomDelaySI = FALSE;
|
|
RomAudioSignal = FALSE;
|
|
RomSPHack = FALSE;
|
|
RomUseCache = TRUE;
|
|
RomUseLargeBuffer = FALSE;
|
|
RomUseLinking = -1;
|
|
RomEmulateAI = FALSE;
|
|
RomModVIS = 1500;
|
|
|
|
if (strlen(RomFullName) != 0) {
|
|
char Identifier[100], * String = NULL;
|
|
|
|
LoadRomRecalcCRCs(CurrentFileName, (DWORD*)&RomHeader[0x10], (DWORD*)&RomHeader[0x14]);
|
|
|
|
RomID(Identifier, RomHeader);
|
|
|
|
if (!Settings_EntryExists(RDS_NAME, Identifier))
|
|
return;
|
|
|
|
RomCF = Settings_ReadInt(RDS_NAME, Identifier, "Counter Factor", -1);
|
|
if (RomCF > 6 || RomCF < 1)
|
|
RomCF = -1;
|
|
|
|
Settings_Read(RDS_NAME, Identifier, "Save Type", "", &String);
|
|
if (strcmp(String, "4kbit Eeprom") == 0) { RomSaveUsing = Eeprom_4K; }
|
|
else if (strcmp(String, "16kbit Eeprom") == 0) { RomSaveUsing = Eeprom_16K; }
|
|
else if (strcmp(String, "Sram") == 0) { RomSaveUsing = Sram; }
|
|
else if (strcmp(String, "FlashRam") == 0) { RomSaveUsing = FlashRam; }
|
|
else { RomSaveUsing = Auto; }
|
|
if (String) free(String);
|
|
|
|
Settings_Read(RDS_NAME, Identifier, STR_CPUTYPE, "", &String);
|
|
if (strcmp(String, "Interpreter") == 0) { RomCPUType = CPU_Interpreter; }
|
|
else if (strcmp(String, "Recompiler") == 0) { RomCPUType = CPU_Recompiler; }
|
|
else if (strcmp(String, "SyncCores") == 0) { RomCPUType = CPU_SyncCores; }
|
|
else { RomCPUType = CPU_Default; }
|
|
if (String) free(String);
|
|
|
|
Settings_Read(RDS_NAME, Identifier, "Self-modifying code Method", "", &String);
|
|
if (strcmp(String, "None") == 0) { RomSelfMod = ModCode_None; }
|
|
else if (strcmp(String, "Cache") == 0) { RomSelfMod = ModCode_Cache; }
|
|
else if (strcmp(String, "Protected Memory") == 0) { RomSelfMod = ModCode_ProtectedMemory; }
|
|
else if (strcmp(String, "Check Memory") == 0) { RomSelfMod = ModCode_CheckMemoryCache; }
|
|
else if (strcmp(String, "Check Memory & cache") == 0) { RomSelfMod = ModCode_CheckMemoryCache; }
|
|
else if (strcmp(String, "Check Memory Advance") == 0) { RomSelfMod = ModCode_CheckMemory2; }
|
|
else if (strcmp(String, "Change Memory") == 0) { RomSelfMod = ModCode_ChangeMemory; }
|
|
else { RomSelfMod = ModCode_Default; }
|
|
if (String) free(String);
|
|
|
|
Settings_Read(RDS_NAME, Identifier, "Linking", "", &String);
|
|
if (strcmp(String, "On") == 0) { RomUseLinking = 0; }
|
|
if (strcmp(String, "Off") == 0) { RomUseLinking = 1; }
|
|
if (String) free(String);
|
|
|
|
if (Settings_HasSetting(RDS_NAME, Identifier, "ExpansionPak"))
|
|
RomRamSize = 0x800000;
|
|
else
|
|
RomRamSize = 0x400000;
|
|
|
|
RomUseTlb = !Settings_HasSetting(RDS_NAME, Identifier, "Disable TLB");
|
|
RomDelaySI = Settings_HasSetting(RDS_NAME, Identifier, "Delay SI");
|
|
RomAudioSignal = Settings_HasSetting(RDS_NAME, Identifier, "Audio Signal");
|
|
RomSPHack = Settings_HasSetting(RDS_NAME, Identifier, "SP Hack");
|
|
RomUseCache = !Settings_HasSetting(RDS_NAME, Identifier, "Disable Reg Cache");
|
|
RomUseLargeBuffer = Settings_HasSetting(RDS_NAME, Identifier, "Use Large Buffer");
|
|
RomEmulateAI = Settings_HasSetting(RDS_NAME, Identifier, "Emulate AI");
|
|
RomModVIS = Settings_ReadInt(RDS_NAME, Identifier, "VI", RomModVIS);
|
|
// To do!
|
|
// Provide a defined way of setting a minimum and maximum value for VI, using 500 and 4500 for now (3x lower and 3x higher)
|
|
if (RomModVIS > 4500 || RomModVIS < 500)
|
|
RomModVIS = 1500;
|
|
}
|
|
}
|
|
|
|
void OpenN64Image(void) {
|
|
DWORD ThreadID;
|
|
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)GS(MSG_CHOOSE_IMAGE));
|
|
if (ChooseN64RomToOpen()) {
|
|
CreateThread(NULL, 0, OpenChosenFile, NULL, 0, &ThreadID);
|
|
}
|
|
else {
|
|
EnableOpenMenuItems();
|
|
}
|
|
}
|
|
|
|
void SetNewFileDirectory(void) {
|
|
char Directory[255], CurrentDir[255], drive[_MAX_DRIVE], dir[_MAX_DIR], * String = NULL;
|
|
|
|
Settings_Read(APPS_NAME, "Directories", "Use Default Rom", STR_TRUE, &String);
|
|
|
|
if (strcmp(String, STR_FALSE) == 0) {
|
|
free(String);
|
|
return;
|
|
}
|
|
if (String) free(String);
|
|
|
|
_splitpath(CurrentFileName, drive, dir, NULL, NULL);
|
|
sprintf(Directory, "%s%s", drive, dir);
|
|
|
|
Settings_GetDirectory(RomDir, CurrentDir, sizeof(CurrentDir));
|
|
if (strcmp(CurrentDir, Directory) == 0) { return; }
|
|
SetRomDirectory(Directory);
|
|
RefreshRomBrowser();
|
|
}
|
|
|
|
DWORD WINAPI OpenChosenFile(LPVOID lpArgs) {
|
|
#define ReadFromRomSection 0x40000000 // Adjusted from 40000 to 400000
|
|
char drive[_MAX_DRIVE], FileName[_MAX_DIR], dir[_MAX_DIR], ext[_MAX_EXT];
|
|
char WinTitle[300], MapFile[_MAX_PATH];
|
|
char Message[100];
|
|
BYTE Test[4];
|
|
int count;
|
|
|
|
if (!PluginsInitilized) {
|
|
DisplayError(GS(MSG_PLUGIN_NOT_INIT));
|
|
return 0;
|
|
}
|
|
EnableMenuItem(hMainMenu, ID_FILE_OPEN_ROM, MFS_DISABLED | MF_BYCOMMAND);
|
|
for (count = 0; count < (int)RomsToRemember; count++) {
|
|
if (strlen(LastRoms[count]) == 0) { break; }
|
|
EnableMenuItem(hMainMenu, ID_FILE_RECENT_FILE + count, MFS_DISABLED | MF_BYCOMMAND);
|
|
}
|
|
HideRomBrowser();
|
|
CloseCheatWindow();
|
|
|
|
{
|
|
HMENU hMenu = GetMenu(hMainWindow);
|
|
for (count = 0; count < 10; count++) {
|
|
EnableMenuItem(hMenu, count, MFS_DISABLED | MF_BYPOSITION);
|
|
}
|
|
DrawMenuBar(hMainWindow);
|
|
}
|
|
Sleep(100); // Adjusted down to 100ms from 1000ms
|
|
CloseCpu();
|
|
if (HaveDebugger)
|
|
ResetMappings();
|
|
SetNewFileDirectory();
|
|
strcpy(MapFile, CurrentFileName);
|
|
if (_strnicmp(&CurrentFileName[strlen(CurrentFileName) - 4], ".ZIP", 4) == 0) {
|
|
int len, port = 0, FoundRom;
|
|
unz_file_info info;
|
|
char zname[132];
|
|
unzFile file;
|
|
file = unzOpen(CurrentFileName);
|
|
if (file == NULL) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
|
|
port = unzGoToFirstFile(file);
|
|
FoundRom = FALSE;
|
|
while (port == UNZ_OK && FoundRom == FALSE) {
|
|
unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0);
|
|
if (unzLocateFile(file, zname, 1) != UNZ_OK) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_ZIP));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
if (unzOpenCurrentFile(file) != UNZ_OK) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
unzReadCurrentFile(file, Test, 4);
|
|
if (IsValidRomImage(Test)) {
|
|
FoundRom = TRUE;
|
|
RomFileSize = info.uncompressed_size;
|
|
if (!Allocate_ROM()) {
|
|
unzCloseCurrentFile(file);
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
memcpy(ROM, Test, 4);
|
|
//len = unzReadCurrentFile(file,&ROM[4],RomFileSize - 4) + 4;
|
|
len = 4;
|
|
for (count = 4; count < (int)RomFileSize; count += ReadFromRomSection) {
|
|
len += unzReadCurrentFile(file, &ROM[count], ReadFromRomSection);
|
|
sprintf(Message, "%s: %.2f%c", GS(MSG_LOADED), ((float)len / (float)RomFileSize) * 100.0f, '%');
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)Message);
|
|
Sleep(10); // Adjusted down to 10ms from 100ms
|
|
}
|
|
if ((int)RomFileSize != len) {
|
|
unzCloseCurrentFile(file);
|
|
unzClose(file);
|
|
switch (len) {
|
|
case UNZ_ERRNO:
|
|
case UNZ_EOF:
|
|
case UNZ_PARAMERROR:
|
|
case UNZ_BADZIPFILE:
|
|
case UNZ_INTERNALERROR:
|
|
case UNZ_CRCERROR:
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
break;
|
|
}
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
if (unzCloseCurrentFile(file) == UNZ_CRCERROR) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
AddRecentFile(hMainWindow, CurrentFileName);
|
|
_splitpath(CurrentFileName, drive, dir, FileName, ext);
|
|
unzClose(file);
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzCloseCurrentFile(file);
|
|
port = unzGoToNextFile(file);
|
|
}
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
unzClose(file);
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
if (HaveDebugger && AutoLoadMapFile) {
|
|
OpenZipMapFile(MapFile);
|
|
}
|
|
}
|
|
else {
|
|
DWORD dwRead, dwToRead, TotalRead;
|
|
HANDLE hFile;
|
|
|
|
hFile = CreateFile(CurrentFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
ReadFile(hFile, Test, 4, &dwRead, NULL);
|
|
if (!IsValidRomImage(Test)) {
|
|
CloseHandle(hFile);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_IMAGE));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
RomFileSize = GetFileSize(hFile, NULL);
|
|
|
|
if (!Allocate_ROM()) {
|
|
CloseHandle(hFile);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)GS(MSG_LOADING));
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
|
|
TotalRead = 0;
|
|
for (count = 0; count < (int)RomFileSize; count += ReadFromRomSection) {
|
|
dwToRead = RomFileSize - count;
|
|
if (dwToRead > ReadFromRomSection) { dwToRead = ReadFromRomSection; }
|
|
|
|
if (!ReadFile(hFile, &ROM[count], dwToRead, &dwRead, NULL)) {
|
|
CloseHandle(hFile);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
TotalRead += dwRead;
|
|
sprintf(Message, "%s: %.2f%c", GS(MSG_LOADED), ((float)TotalRead / (float)RomFileSize) * 100.0f, '%');
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)Message);
|
|
Sleep(10); // Adjusted down to 10ms from 100ms
|
|
}
|
|
dwRead = TotalRead;
|
|
|
|
if (RomFileSize != dwRead) {
|
|
CloseHandle(hFile);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
EnableOpenMenuItems();
|
|
ShowRomList(hMainWindow);
|
|
return 0;
|
|
}
|
|
CloseHandle(hFile);
|
|
AddRecentFile(hMainWindow, CurrentFileName);
|
|
_splitpath(CurrentFileName, drive, dir, FileName, ext);
|
|
}
|
|
ByteSwapRom(ROM, RomFileSize);
|
|
memcpy(RomHeader, ROM, sizeof(RomHeader));
|
|
RecalculateCRCs(ROM, RomFileSize);
|
|
|
|
// Blind copy of the recalculated CRC1 and CRC2, no checks needed really
|
|
*(DWORD*)&RomHeader[0x10] = *(DWORD*)&ROM[0x10];
|
|
*(DWORD*)&RomHeader[0x14] = *(DWORD*)&ROM[0x14];
|
|
|
|
// Bypass hardware checks on ALECK64
|
|
if (GetCicChipID(ROM) == CIC_NUS_8401) {
|
|
ROM[0x67c] = 0;
|
|
ROM[0x67d] = 0;
|
|
ROM[0x67e] = 0;
|
|
ROM[0x67f] = 0;
|
|
}
|
|
|
|
#ifdef ROM_IN_MAPSPACE
|
|
{
|
|
DWORD OldProtect;
|
|
VirtualProtect(ROM, RomFileSize, PAGE_READONLY, &OldProtect);
|
|
}
|
|
#endif
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
if (HaveDebugger && AutoLoadMapFile) {
|
|
char* p;
|
|
|
|
p = strrchr(MapFile, '.');
|
|
if (p != NULL) {
|
|
*p = '\0';
|
|
}
|
|
strcat(MapFile, ".cod");
|
|
if (OpenMapFile(MapFile)) {
|
|
p = strrchr(MapFile, '.');
|
|
if (p != NULL) {
|
|
*p = '\0';
|
|
}
|
|
strcat(MapFile, ".map");
|
|
OpenMapFile(MapFile);
|
|
}
|
|
}
|
|
|
|
GetRomName(RomName, ROM);
|
|
if (strlen(RomName) == 0)
|
|
strcpy(RomName, FileName);
|
|
|
|
GetRomFullName(RomFullName, ROM, FileName);
|
|
sprintf(WinTitle, "%s - %s", RomFullName, AppName);
|
|
|
|
for (count = 0; count < (int)strlen(RomName); count++) {
|
|
switch (RomName[count]) {
|
|
case '/':
|
|
case '\\':
|
|
RomName[count] = '-';
|
|
break;
|
|
case ':':
|
|
RomName[count] = ';';
|
|
break;
|
|
}
|
|
}
|
|
SetWindowText(hMainWindow, WinTitle);
|
|
|
|
if (!RememberCheats) { DisableAllCheats(); }
|
|
EnableOpenMenuItems();
|
|
//if (RomBrowser) { SetupPlugins(hMainWindow); }
|
|
SetCurrentSaveState(hMainWindow, ID_CURRENTSAVE_DEFAULT);
|
|
sprintf(WinTitle, "%s - [ %s ]", GS(MSG_LOADED), FileName);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)WinTitle);
|
|
if (AutoStart) {
|
|
StartEmulation();
|
|
Sleep(100);
|
|
if (AutoFullScreen) {
|
|
char Status[100], Identifier[100], result[100], * read;
|
|
|
|
RomID(Identifier, RomHeader);
|
|
|
|
Settings_Read(RDS_NAME, Identifier, "Status", Default_RomStatus, &read);
|
|
strncpy(Status, read, sizeof(Status));
|
|
if (read) free(read);
|
|
|
|
strcat(Status, ".AutoFullScreen");
|
|
Settings_Read(RDS_NAME, Identifier, Status, STR_TRUE, &read);
|
|
strncpy(result, read, sizeof(result));
|
|
if (read) free(read);
|
|
if (strcmp(result, STR_TRUE) == 0) {
|
|
SendMessage(hMainWindow, WM_COMMAND, ID_OPTIONS_FULLSCREEN, 0);
|
|
}
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void SaveRecentDirs(void) {
|
|
char String[200];
|
|
int count;
|
|
|
|
for (count = 0; count < RomDirsToRemember; count++) {
|
|
if (strlen(LastDirs[count]) == 0)
|
|
break;
|
|
sprintf(String, "RecentDir%d", count + 1);
|
|
Settings_Write(APPS_NAME, "Directories", String, LastDirs[count]);
|
|
}
|
|
}
|
|
|
|
void SaveRecentFiles(void) {
|
|
char String[200];
|
|
int count;
|
|
|
|
for (count = 0; count < RomsToRemember; count++) {
|
|
if (strlen(LastRoms[count]) == 0)
|
|
break;
|
|
sprintf(String, "RecentFile%d", count + 1);
|
|
Settings_Write(APPS_NAME, "Directories", String, LastRoms[count]);
|
|
}
|
|
}
|
|
|
|
// Note!!! Due to changes any setting not being explicitly written must be deleted!!!
|
|
void SaveRomOptions(void) {
|
|
char Identifier[100], String[100];
|
|
|
|
if (strlen(RomName) == 0)
|
|
return;
|
|
|
|
RomID(Identifier, RomHeader);
|
|
|
|
// Internal Rom Name
|
|
Settings_Write(RDS_NAME, Identifier, "Name", RomFullName);
|
|
|
|
// Expansion Pak
|
|
if (RomRamSize == 0x800000)
|
|
Settings_Write(RDS_NAME, Identifier, "ExpansionPak", "");
|
|
else
|
|
Settings_Delete(RDS_NAME, Identifier, "ExpansionPak");
|
|
|
|
// Counter Factor
|
|
if (RomCF <= 6 && RomCF >= 1)
|
|
sprintf(String, "%d", RomCF);
|
|
else
|
|
sprintf(String, "Default");
|
|
Settings_Write(RDS_NAME, Identifier, "Counter Factor", String);
|
|
|
|
// Save Type
|
|
switch (RomSaveUsing) {
|
|
case Eeprom_4K:
|
|
sprintf(String, "4kbit Eeprom"); break;
|
|
case Eeprom_16K:
|
|
sprintf(String, "16kbit Eeprom"); break;
|
|
case Sram:
|
|
sprintf(String, "Sram"); break;
|
|
case FlashRam:
|
|
sprintf(String, "FlashRam"); break;
|
|
default:
|
|
sprintf(String, "First Save Type"); break;
|
|
}
|
|
Settings_Write(RDS_NAME, Identifier, "Save Type", String);
|
|
|
|
// Cpu Type
|
|
switch (RomCPUType) {
|
|
case CPU_Interpreter:
|
|
sprintf(String, "Interpreter"); break;
|
|
case CPU_Recompiler:
|
|
sprintf(String, "Recompiler"); break;
|
|
case CPU_SyncCores:
|
|
sprintf(String, "SyncCores"); break;
|
|
default:
|
|
sprintf(String, "Default"); break;
|
|
}
|
|
Settings_Write(RDS_NAME, Identifier, STR_CPUTYPE, String);
|
|
|
|
// Recompiler self code modification
|
|
switch (RomSelfMod) {
|
|
case ModCode_None:
|
|
sprintf(String, "None"); break;
|
|
case ModCode_Cache:
|
|
sprintf(String, "Cache"); break;
|
|
case ModCode_ProtectedMemory:
|
|
sprintf(String, "Protected Memory"); break;
|
|
case ModCode_CheckMemoryCache:
|
|
sprintf(String, "Check Memory & cache"); break;
|
|
case ModCode_CheckMemory2:
|
|
sprintf(String, "Check Memory Advance"); break;
|
|
case ModCode_ChangeMemory:
|
|
sprintf(String, "Change Memory"); break;
|
|
default:
|
|
sprintf(String, "Default"); break;
|
|
}
|
|
Settings_Write(RDS_NAME, Identifier, "Self-modifying code Method", String);
|
|
|
|
if (!RomUseCache) Settings_Write(RDS_NAME, Identifier, "Disable Reg Cache", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "Disable Reg Cache");
|
|
if (!RomUseTlb) Settings_Write(RDS_NAME, Identifier, "Disable TLB", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "Disable TLB");
|
|
if (RomDelaySI) Settings_Write(RDS_NAME, Identifier, "Delay SI", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "Delay SI");
|
|
if (RomEmulateAI) Settings_Write(RDS_NAME, Identifier, "Emulate AI", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "Emulate AI");
|
|
if (RomAudioSignal) Settings_Write(RDS_NAME, Identifier, "Audio Signal", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "Audio Signal");
|
|
if (RomSPHack) Settings_Write(RDS_NAME, Identifier, "SP Hack", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "SP Hack");
|
|
if (RomUseLargeBuffer)
|
|
Settings_Write(RDS_NAME, Identifier, "Use Large Buffer", "");
|
|
else Settings_Delete(RDS_NAME, Identifier, "Use Large Buffer");
|
|
|
|
switch (RomUseLinking) {
|
|
case 0:
|
|
Settings_Write(RDS_NAME, Identifier, "Linking", "On"); break;
|
|
case 1:
|
|
Settings_Write(RDS_NAME, Identifier, "Linking", "Off"); break;
|
|
default:
|
|
Settings_Write(RDS_NAME, Identifier, "Linking", "Global"); break;
|
|
}
|
|
|
|
if (RomModVIS == 1500)
|
|
Settings_Delete(RDS_NAME, Identifier, "VI");
|
|
else {
|
|
sprintf(String, "%d", RomModVIS);
|
|
Settings_Write(RDS_NAME, Identifier, "VI", String);
|
|
}
|
|
}
|
|
|
|
void SetRecentRomDir(DWORD Index) {
|
|
Index -= ID_FILE_RECENT_DIR;
|
|
if (Index < 0 || Index >(DWORD)RomDirsToRemember) { return; }
|
|
SetRomDirectory(LastDirs[Index]);
|
|
RefreshRomBrowser();
|
|
}
|
|
|
|
void SetRomDirectory(char* Directory) {
|
|
Settings_Write(APPS_NAME, "Directories", "Rom", Directory);
|
|
AddRecentDir(hMainWindow, Directory);
|
|
}
|
|
|
|
void RecalculateCRCs(BYTE* data, DWORD data_size) {
|
|
int i;
|
|
unsigned int seed, crc[2];
|
|
unsigned int t1, t2, t3, t4, t5, t6, r, d, j;
|
|
enum CIC_CHIP chip;
|
|
|
|
chip = GetCicChipID(data);
|
|
|
|
switch (chip) {
|
|
case CIC_NUS_6101:
|
|
case CIC_NUS_6102:
|
|
seed = 0xF8CA4DDC; break;
|
|
case CIC_NUS_6103:
|
|
seed = 0xA3886759; break;
|
|
case CIC_NUS_6105:
|
|
seed = 0xDF26F436; break;
|
|
case CIC_NUS_6106:
|
|
seed = 0x1FEA617A; break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
t1 = t2 = t3 = t4 = t5 = t6 = seed;
|
|
|
|
for (i = 0x00001000; i < 0x00101000; i += 4) {
|
|
if ((unsigned int)(i + 3) > data_size)
|
|
d = 0;
|
|
else
|
|
d = data[i + 3] << 24 | data[i + 2] << 16 | data[i + 1] << 8 | data[i];
|
|
if ((t6 + d) < t6)
|
|
t4++;
|
|
t6 += d;
|
|
t3 ^= d;
|
|
r = (d << (d & 0x1F)) | (d >> (32 - (d & 0x1F)));
|
|
t5 += r;
|
|
if (t2 > d)
|
|
t2 ^= r;
|
|
else
|
|
t2 ^= t6 ^ d;
|
|
|
|
if (chip == CIC_NUS_6105) {
|
|
j = 0x40 + 0x0710 + (i & 0xFF);
|
|
t1 += (data[j + 3] << 24 | data[j + 2] << 16 | data[j + 1] << 8 | data[j]) ^ d;
|
|
}
|
|
else
|
|
t1 += t5 ^ d;
|
|
}
|
|
|
|
if (chip == CIC_NUS_6103) {
|
|
crc[0] = (t6 ^ t4) + t3;
|
|
crc[1] = (t5 ^ t2) + t1;
|
|
}
|
|
else if (chip == CIC_NUS_6106) {
|
|
crc[0] = (t6 * t4) + t3;
|
|
crc[1] = (t5 * t2) + t1;
|
|
}
|
|
else {
|
|
crc[0] = t6 ^ t4 ^ t3;
|
|
crc[1] = t5 ^ t2 ^ t1;
|
|
}
|
|
|
|
if (*(DWORD*)&data[0x10] != crc[0] || *(DWORD*)&data[0x14] != crc[1]) {
|
|
/*if (ShowDebugMessages)
|
|
DisplayError("Calculated CRC does not match CRC1 and CRC2.");
|
|
*/
|
|
data[0x13] = (crc[0] & 0xFF000000) >> 24;
|
|
data[0x12] = (BYTE)((crc[0] & 0x00FF0000) >> 16);
|
|
data[0x11] = (crc[0] & 0x0000FF00) >> 8;
|
|
data[0x10] = (crc[0] & 0x000000FF);
|
|
|
|
data[0x17] = (crc[1] & 0xFF000000) >> 24;
|
|
data[0x16] = (BYTE)((crc[1] & 0x00FF0000) >> 16);
|
|
data[0x15] = (crc[1] & 0x0000FF00) >> 8;
|
|
data[0x14] = (crc[1] & 0x000000FF);
|
|
}
|
|
}
|
|
|
|
void LoadRomRecalcCRCs(char* FileName, BYTE* CRC1, BYTE* CRC2) {
|
|
BYTE* data = NULL;
|
|
DWORD data_size = 0, count;
|
|
|
|
// As much as this pains me, this is mostly a copy of code that already exists as a copy and paste nightmare
|
|
// Some of the code has been reduced because the checks have already been performed
|
|
// This code will, currently, only be called when the CRC1 and CRC2 of a loaded Rom Header are read as 0's
|
|
if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0) {
|
|
int len, port = 0, FoundRom;
|
|
unz_file_info info;
|
|
char zname[132];
|
|
unzFile file;
|
|
BYTE Test[4];
|
|
|
|
// Should not happen at this point, the file should have been opened once already
|
|
file = unzOpen(FileName);
|
|
if (file == NULL) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
return;
|
|
}
|
|
|
|
port = unzGoToFirstFile(file);
|
|
FoundRom = FALSE;
|
|
while (port == UNZ_OK && FoundRom == FALSE) {
|
|
unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0);
|
|
|
|
if (unzLocateFile(file, zname, 1) != UNZ_OK) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_ZIP));
|
|
return;
|
|
}
|
|
|
|
if (unzOpenCurrentFile(file) != UNZ_OK) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
return;
|
|
}
|
|
|
|
unzReadCurrentFile(file, Test, 4);
|
|
if (IsValidRomImage(Test)) {
|
|
FoundRom = TRUE;
|
|
data_size = info.uncompressed_size;
|
|
|
|
data = (BYTE*)malloc(sizeof(BYTE) * data_size);
|
|
if (!data) {
|
|
unzCloseCurrentFile(file);
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
return;
|
|
}
|
|
memcpy(data, Test, 4);
|
|
//len = unzReadCurrentFile(file,&ROM[4],RomFileSize - 4) + 4;
|
|
len = 4;
|
|
for (count = 4; count < data_size; count += ReadFromRomSection) {
|
|
len += unzReadCurrentFile(file, &data[count], ReadFromRomSection);
|
|
}
|
|
if ((int)data_size != len) {
|
|
unzCloseCurrentFile(file);
|
|
unzClose(file);
|
|
switch (len) {
|
|
case UNZ_ERRNO:
|
|
case UNZ_EOF:
|
|
case UNZ_PARAMERROR:
|
|
case UNZ_BADZIPFILE:
|
|
case UNZ_INTERNALERROR:
|
|
case UNZ_CRCERROR:
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
if (unzCloseCurrentFile(file) == UNZ_CRCERROR) {
|
|
unzClose(file);
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
return;
|
|
}
|
|
unzClose(file);
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzCloseCurrentFile(file);
|
|
port = unzGoToNextFile(file);
|
|
}
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_ZIP));
|
|
unzClose(file);
|
|
return;
|
|
}
|
|
}
|
|
else {
|
|
DWORD dwRead, dwToRead, TotalRead;
|
|
HANDLE hFile;
|
|
BYTE Test[4];
|
|
|
|
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
return;
|
|
}
|
|
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
ReadFile(hFile, Test, 4, &dwRead, NULL);
|
|
if (!IsValidRomImage(Test)) {
|
|
CloseHandle(hFile);
|
|
DisplayError(GS(MSG_FAIL_IMAGE));
|
|
return;
|
|
}
|
|
data_size = GetFileSize(hFile, NULL);
|
|
|
|
data = (BYTE*)malloc(sizeof(BYTE) * data_size);
|
|
if (!data) {
|
|
CloseHandle(hFile);
|
|
DisplayError(GS(MSG_MEM_ALLOC_ERROR));
|
|
return;
|
|
}
|
|
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
|
|
TotalRead = 0;
|
|
for (count = 0; count < RomFileSize; count += ReadFromRomSection) {
|
|
dwToRead = RomFileSize - count;
|
|
if (dwToRead > ReadFromRomSection) { dwToRead = ReadFromRomSection; }
|
|
|
|
if (!ReadFile(hFile, &data[count], dwToRead, &dwRead, NULL)) {
|
|
CloseHandle(hFile);
|
|
SendMessage(hStatusWnd, SB_SETTEXT, 0, (LPARAM)"");
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
return;
|
|
}
|
|
TotalRead += dwRead;
|
|
}
|
|
dwRead = TotalRead;
|
|
|
|
if (RomFileSize != dwRead) {
|
|
CloseHandle(hFile);
|
|
DisplayError(GS(MSG_FAIL_OPEN_IMAGE));
|
|
return;
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
ByteSwapRom(data, data_size);
|
|
|
|
// Finished loading the rom into our temporary byte array, can recalculate now
|
|
RecalculateCRCs(data, data_size);
|
|
|
|
// No checks needed, this function only gets called on an as needed basis
|
|
*(DWORD*)CRC1 = *(DWORD*)&data[0x10];
|
|
*(DWORD*)CRC2 = *(DWORD*)&data[0x14];
|
|
|
|
// Make sure to free allocated space
|
|
if (data != NULL)
|
|
free(data);
|
|
}
|
|
|
|
// This was a test, unzipping is a limiting factor when calculating the xxhash
|
|
// Leaving the code as this will likely be used again in the future
|
|
BOOL LoadDataForRomBrowser(char* FileName, BYTE* Data, int DataLen, int* RomSize) {
|
|
BYTE* data = NULL;
|
|
DWORD data_size = 0;
|
|
char hash[100];
|
|
|
|
if (_strnicmp(&FileName[strlen(FileName) - 4], ".ZIP", 4) == 0) {
|
|
int len, port = 0, FoundRom;
|
|
unz_file_info info;
|
|
char zname[132];
|
|
unzFile file;
|
|
BYTE Test[4];
|
|
|
|
// Should not happen at this point, the file should have been opened once already
|
|
file = unzOpen(FileName);
|
|
if (file == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
port = unzGoToFirstFile(file);
|
|
FoundRom = FALSE;
|
|
while (port == UNZ_OK && FoundRom == FALSE) {
|
|
unzGetCurrentFileInfo(file, &info, zname, 128, NULL, 0, NULL, 0);
|
|
|
|
if (unzLocateFile(file, zname, 1) != UNZ_OK) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
|
|
if (unzOpenCurrentFile(file) != UNZ_OK) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
|
|
unzReadCurrentFile(file, Test, 4);
|
|
if (IsValidRomImage(Test)) {
|
|
FoundRom = TRUE;
|
|
data_size = info.uncompressed_size;
|
|
|
|
data = (BYTE*)malloc(sizeof(BYTE) * data_size);
|
|
if (!data) {
|
|
unzCloseCurrentFile(file);
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
|
|
memcpy(data, Test, 4);
|
|
unzReadCurrentFile(file, data + 4, data_size - 4);
|
|
*RomSize = data_size;
|
|
|
|
if (unzCloseCurrentFile(file) == UNZ_CRCERROR) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
unzClose(file);
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzCloseCurrentFile(file);
|
|
port = unzGoToNextFile(file);
|
|
}
|
|
}
|
|
if (FoundRom == FALSE) {
|
|
unzClose(file);
|
|
return FALSE;
|
|
}
|
|
}
|
|
else {
|
|
DWORD dwRead, dwToRead, TotalRead;
|
|
HANDLE hFile;
|
|
BYTE Test[4];
|
|
|
|
hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, NULL,
|
|
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
|
|
NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
|
|
// Read the first 4 bytes (This will let us know if the file is a valid rom)
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
if (!ReadFile(hFile, Test, 4, &dwRead, NULL)) {
|
|
CloseHandle(hFile);
|
|
return FALSE;
|
|
}
|
|
|
|
// Test the first 4 bytes and only continue if it is a valid rom
|
|
if (!IsValidRomImage(Test)) {
|
|
CloseHandle(hFile);
|
|
return FALSE;
|
|
}
|
|
|
|
// Allocate memory for the buffer
|
|
data_size = GetFileSize(hFile, NULL);
|
|
data = (BYTE*)malloc(sizeof(BYTE) * data_size);
|
|
if (!data) {
|
|
CloseHandle(hFile);
|
|
return FALSE;
|
|
}
|
|
|
|
// Read the entire file into memory
|
|
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
|
|
if (!ReadFile(hFile, data, data_size, &dwRead, NULL)) {
|
|
CloseHandle(hFile);
|
|
return FALSE;
|
|
}
|
|
*RomSize = data_size;
|
|
|
|
// Failed to read the entire file, abort
|
|
if (data_size != dwRead) {
|
|
CloseHandle(hFile);
|
|
return FALSE;
|
|
}
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
ByteSwapRom(data, data_size);
|
|
|
|
// This is the new Identifier for the ROM, xxhash
|
|
RomHASH(hash, data, data_size);
|
|
|
|
// Since the rom is fully loaded into memory do the CRC recalculation
|
|
RecalculateCRCs(data, data_size);
|
|
|
|
// The rom browser only needs the first 0x1000 bytes
|
|
memcpy(Data, data, DataLen);
|
|
|
|
free(data);
|
|
|
|
return TRUE;
|
|
} |