diff --git a/Source/Project64/N64 System/N64 Rom Class.cpp b/Source/Project64/N64 System/N64 Rom Class.cpp index a116a277f..0bf2230a4 100644 --- a/Source/Project64/N64 System/N64 Rom Class.cpp +++ b/Source/Project64/N64 System/N64 Rom Class.cpp @@ -256,6 +256,78 @@ void CN64Rom::CalculateCicChip() } +void CN64Rom::CalculateRomCrc() +{ + DWORD t0, t1, t2, t3, t4, t5, t7; + DWORD a0, a1, a2, a3; + DWORD s0; + DWORD v0, v1; + + DWORD OldProtect; + VirtualProtect(m_ROMImage, m_RomFileSize, PAGE_READWRITE, &OldProtect); + + switch (m_CicChip) { + case CIC_NUS_6101: + case CIC_NUS_6102: + { + v1 = 0; + t0 = 0; + + t5 = 0x20; + + v0 = 0xF8CA4DDB + 1; // 0xFFFFFFFF & (0x3F * 0x5D588B65) + a3 = v0; + t2 = v0; + t3 = v0; + s0 = v0; + a2 = v0; + t4 = v0; + + for (t0 = 0, t1 = 0x1000; t0 < 0x00100000; t0 += 4, t1 += 4){ + v0 = *(DWORD *)(m_ROMImage + t1); + + v1 = a3 + v0; + a1 = v1; + + if (v1 < a3) t2 += 0x1; + v1 = v0 & 0x001F; + t7 = t5 - v1; + + a0 = (v0 << v1) | (v0 >> t7); + + a3 = a1; + t3 = t3 ^ v0; + + s0 = s0 + a0; + if (a2 < v0){ + a2 = a3 ^ v0 ^ a2; + } + else{ + a2 = a2 ^ a0; + } + + t4 = (v0 ^ s0) + t4; + } + a3 = a3 ^ t2 ^ t3; + s0 = s0 ^ a2 ^ t4; + + *(DWORD *)(m_ROMImage + 0x10) = a3; + *(DWORD *)(m_ROMImage + 0x14) = s0; + break; + } + case CIC_NUS_6103: + case CIC_NUS_6105: + case CIC_NUS_6106: + case CIC_NUS_8303: + case CIC_NUS_DDIPL: + case CIC_UNKNOWN: + default: + break; + } + + VirtualProtect(m_ROMImage, m_RomFileSize, PAGE_READONLY, &OldProtect); +} + CICChip CN64Rom::CicChipID() { return m_CicChip; @@ -471,6 +543,13 @@ bool CN64Rom::LoadN64Image ( const char * FileLoc, bool LoadBootCodeOnly ) { { SaveRomSettingID(false); } + + if (g_Settings->LoadBool(Game_CRC_Recalc)) + { + //Calculate ROM Header CRC + CalculateRomCrc(); + } + return true; } diff --git a/Source/Project64/N64 System/N64 Rom Class.h b/Source/Project64/N64 System/N64 Rom Class.h index a076e2b5f..363add814 100644 --- a/Source/Project64/N64 System/N64 Rom Class.h +++ b/Source/Project64/N64 System/N64 Rom Class.h @@ -33,6 +33,7 @@ class CN64Rom : void SetError ( LanguageStringID ErrorMsg ); static void __stdcall NotificationCB ( LPCWSTR Status, CN64Rom * _this ); void CalculateCicChip (); + void CalculateRomCrc (); public: CN64Rom(); diff --git a/Source/Project64/Settings.h b/Source/Project64/Settings.h index ad66e0a14..94b407a72 100644 --- a/Source/Project64/Settings.h +++ b/Source/Project64/Settings.h @@ -97,6 +97,7 @@ enum SettingID { Rdb_AiCountPerBytes, Rdb_AudioResetOnLoad, Rdb_AllowROMWrites, + Rdb_CRC_Recalc, //Individual Game Settings Game_IniKey, @@ -143,6 +144,7 @@ enum SettingID { Game_AiCountPerBytes, Game_AudioResetOnLoad, Game_AllowROMWrites, + Game_CRC_Recalc, // General Game running info GameRunning_LoadingInProgress, diff --git a/Source/Project64/Settings/Settings Class.cpp b/Source/Project64/Settings/Settings Class.cpp index 513a7a3f9..67609581a 100644 --- a/Source/Project64/Settings/Settings Class.cpp +++ b/Source/Project64/Settings/Settings Class.cpp @@ -169,6 +169,7 @@ void CSettings::AddHowToHandleSetting () AddHandler(Rdb_AiCountPerBytes, new CSettingTypeRomDatabase("AiCountPerBytes",400)); AddHandler(Rdb_AudioResetOnLoad, new CSettingTypeRDBYesNo("AudioResetOnLoad", false)); AddHandler(Rdb_AllowROMWrites, new CSettingTypeRDBYesNo("AllowROMWrites", false)); + AddHandler(Rdb_CRC_Recalc, new CSettingTypeRDBYesNo("CRC-Recalc", false)); AddHandler(Game_IniKey, new CSettingTypeTempString("")); AddHandler(Game_GameName, new CSettingTypeTempString("")); @@ -214,6 +215,7 @@ void CSettings::AddHowToHandleSetting () AddHandler(Game_AiCountPerBytes, new CSettingTypeGame("AiCountPerBytes",Rdb_AiCountPerBytes)); AddHandler(Game_AudioResetOnLoad, new CSettingTypeGame("AudioResetOnLoad", Rdb_AudioResetOnLoad)); AddHandler(Game_AllowROMWrites, new CSettingTypeGame("AllowROMWrites", Rdb_AllowROMWrites)); + AddHandler(Game_CRC_Recalc, new CSettingTypeGame("CRC-Recalc", Rdb_CRC_Recalc)); //User Interface AddHandler(UserInterface_BasicMode, new CSettingTypeApplication("","Basic Mode", (DWORD)true));