mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-10-30 07:11:05 +00:00
Added error message for corrupted save data, removed Win32 message box on XamShowMessageBoxUI (#122)
* xam: remove Win32 message box on XamShowMessageBoxUI * CTitleStateIntro_patches: display error message on corrupted save data TitleMenuRemoveContinueOnCorruptSaveMidAsmHook by @DeaTh-G Co-Authored-By: DeaTh-G <55578911+DeaTh-G@users.noreply.github.com> --------- Co-authored-by: DeaTh-G <55578911+DeaTh-G@users.noreply.github.com>
This commit is contained in:
parent
c53df15578
commit
aacb9d259c
8 changed files with 105 additions and 24 deletions
|
|
@ -9,6 +9,7 @@ public:
|
||||||
static inline bool s_isMissingDLC;
|
static inline bool s_isMissingDLC;
|
||||||
static inline bool s_isLoading;
|
static inline bool s_isLoading;
|
||||||
static inline bool s_isWerehog;
|
static inline bool s_isWerehog;
|
||||||
|
static inline bool s_isSaveDataCorrupt;
|
||||||
|
|
||||||
static inline ELanguage s_language;
|
static inline ELanguage s_language;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,6 @@
|
||||||
#include <user/paths.h>
|
#include <user/paths.h>
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
#include <CommCtrl.h>
|
|
||||||
// Needed for commctrl
|
|
||||||
#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct XamListener : KernelObject
|
struct XamListener : KernelObject
|
||||||
{
|
{
|
||||||
uint32_t id{};
|
uint32_t id{};
|
||||||
|
|
@ -208,11 +202,12 @@ bool XNotifyGetNext(uint32_t hNotification, uint32_t dwMsgFilter, be<uint32_t>*
|
||||||
uint32_t XamShowMessageBoxUI(uint32_t dwUserIndex, be<uint16_t>* wszTitle, be<uint16_t>* wszText, uint32_t cButtons,
|
uint32_t XamShowMessageBoxUI(uint32_t dwUserIndex, be<uint16_t>* wszTitle, be<uint16_t>* wszText, uint32_t cButtons,
|
||||||
xpointer<be<uint16_t>>* pwszButtons, uint32_t dwFocusButton, uint32_t dwFlags, be<uint32_t>* pResult, XXOVERLAPPED* pOverlapped)
|
xpointer<be<uint16_t>>* pwszButtons, uint32_t dwFocusButton, uint32_t dwFlags, be<uint32_t>* pResult, XXOVERLAPPED* pOverlapped)
|
||||||
{
|
{
|
||||||
int button{};
|
*pResult = cButtons ? cButtons - 1 : 0;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#if _DEBUG
|
||||||
|
assert("XamShowMessageBoxUI encountered!" && false);
|
||||||
|
#else
|
||||||
std::vector<std::wstring> texts{};
|
std::vector<std::wstring> texts{};
|
||||||
std::vector<TASKDIALOG_BUTTON> buttons{};
|
|
||||||
|
|
||||||
texts.emplace_back(reinterpret_cast<wchar_t*>(wszTitle));
|
texts.emplace_back(reinterpret_cast<wchar_t*>(wszTitle));
|
||||||
texts.emplace_back(reinterpret_cast<wchar_t*>(wszText));
|
texts.emplace_back(reinterpret_cast<wchar_t*>(wszText));
|
||||||
|
|
@ -226,23 +221,27 @@ uint32_t XamShowMessageBoxUI(uint32_t dwUserIndex, be<uint16_t>* wszTitle, be<ui
|
||||||
ByteSwapInplace(text[i]);
|
ByteSwapInplace(text[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] If you are encountering this message and the game has ceased functioning,\n");
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] please create an issue at https://github.com/hedge-dev/UnleashedRecomp/issues.\n");
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] %ls\n", texts[0].c_str());
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] %ls\n", texts[1].c_str());
|
||||||
|
wprintf(L"[XamShowMessageBoxUI] ");
|
||||||
|
|
||||||
for (size_t i = 0; i < cButtons; i++)
|
for (size_t i = 0; i < cButtons; i++)
|
||||||
buttons.emplace_back(i, texts[2 + i].c_str());
|
{
|
||||||
|
wprintf(L"%ls", texts[2 + i].c_str());
|
||||||
|
|
||||||
XamNotifyEnqueueEvent(9, 1);
|
if (i != cButtons - 1)
|
||||||
|
wprintf(L" | ");
|
||||||
|
}
|
||||||
|
|
||||||
TASKDIALOGCONFIG config{};
|
wprintf(L"\n");
|
||||||
config.cbSize = sizeof(config);
|
wprintf(L"[XamShowMessageBoxUI] Defaulted to button: %d\n", pResult->get());
|
||||||
config.pszWindowTitle = texts[0].c_str();
|
wprintf(L"[XamShowMessageBoxUI] !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||||
config.pszContent = texts[1].c_str();
|
|
||||||
config.cButtons = cButtons;
|
|
||||||
config.pButtons = buttons.data();
|
|
||||||
|
|
||||||
TaskDialogIndirect(&config, &button, nullptr, nullptr);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*pResult = button;
|
|
||||||
|
|
||||||
if (pOverlapped)
|
if (pOverlapped)
|
||||||
{
|
{
|
||||||
pOverlapped->dwCompletionContext = GuestThread::GetCurrentThreadId();
|
pOverlapped->dwCompletionContext = GuestThread::GetCurrentThreadId();
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,20 @@ std::unordered_map<std::string, std::unordered_map<ELanguage, std::string>> g_lo
|
||||||
{ ELanguage::Italian, "Sei sicuro di voler uscire?" }
|
{ ELanguage::Italian, "Sei sicuro di voler uscire?" }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Notes: message appears when the SYS-DATA is corrupted (mismatching file size).
|
||||||
|
// To make this occur, open the file in any editor and just remove a large chunk of data.
|
||||||
|
// Do not localise this unless absolutely necessary, these strings are from the XEX.
|
||||||
|
"Title_Message_SaveDataCorrupt",
|
||||||
|
{
|
||||||
|
{ ELanguage::English, "The save file appears to be\ncorrupted and cannot be loaded." },
|
||||||
|
{ ELanguage::Japanese, "ゲームデータの読み込みに失敗しました。\nこのまま続けるとゲームデータをセーブすることはできません" },
|
||||||
|
{ ELanguage::German, "Diese Speicherdatei ist beschädigt\nund kann nicht geladen werden." },
|
||||||
|
{ ELanguage::French, "Le fichier de sauvegarde semble être\nendommagé et ne peut être chargé." },
|
||||||
|
{ ELanguage::Spanish, "El archivo parece estar dañado\ny no se puede cargar." },
|
||||||
|
{ ELanguage::Italian, "I file di salvataggio sembrano danneggiati\ne non possono essere caricati." }
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"Common_On",
|
"Common_On",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,6 @@ void WerehogBattleMusicMidAsmHook(PPCRegister& r11)
|
||||||
r11.u8 = 3;
|
r11.u8 = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StorageDevicePromptMidAsmHook() {}
|
|
||||||
|
|
||||||
/* Hook function that gets the game region
|
/* Hook function that gets the game region
|
||||||
and force result to zero for Japanese
|
and force result to zero for Japanese
|
||||||
to display the correct logos. */
|
to display the correct logos. */
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,8 @@ PPC_FUNC(sub_824E5170)
|
||||||
|
|
||||||
if (pSaveIcon->m_IsVisible)
|
if (pSaveIcon->m_IsVisible)
|
||||||
{
|
{
|
||||||
|
App::s_isSaveDataCorrupt = false;
|
||||||
|
|
||||||
if (!m_isSavedAchievementData)
|
if (!m_isSavedAchievementData)
|
||||||
{
|
{
|
||||||
LOGN("Saving achievements...");
|
LOGN("Saving achievements...");
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,21 @@
|
||||||
#include <locale/locale.h>
|
#include <locale/locale.h>
|
||||||
#include <ui/fader.h>
|
#include <ui/fader.h>
|
||||||
#include <ui/message_window.h>
|
#include <ui/message_window.h>
|
||||||
|
#include <user/paths.h>
|
||||||
#include <app.h>
|
#include <app.h>
|
||||||
|
|
||||||
static bool g_quitMessageOpen = false;
|
static bool g_quitMessageOpen = false;
|
||||||
static bool g_quitMessageFaderBegun = false;
|
static bool g_quitMessageFaderBegun = false;
|
||||||
static int g_quitMessageResult = -1;
|
static int g_quitMessageResult = -1;
|
||||||
|
|
||||||
|
static std::atomic<bool> g_corruptSaveMessageOpen = false;
|
||||||
|
static int g_corruptSaveMessageResult = -1;
|
||||||
|
|
||||||
static bool ProcessQuitMessage()
|
static bool ProcessQuitMessage()
|
||||||
{
|
{
|
||||||
|
if (g_corruptSaveMessageOpen)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (!g_quitMessageOpen)
|
if (!g_quitMessageOpen)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -37,6 +44,49 @@ static bool ProcessQuitMessage()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool ProcessCorruptSaveMessage()
|
||||||
|
{
|
||||||
|
if (!g_corruptSaveMessageOpen)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (MessageWindow::Open(Localise("Title_Message_SaveDataCorrupt"), &g_corruptSaveMessageResult) == MSG_CLOSED)
|
||||||
|
{
|
||||||
|
g_corruptSaveMessageOpen = false;
|
||||||
|
g_corruptSaveMessageOpen.notify_one();
|
||||||
|
g_corruptSaveMessageResult = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StorageDevicePromptMidAsmHook() {}
|
||||||
|
|
||||||
|
// Save data validation hook.
|
||||||
|
PPC_FUNC_IMPL(__imp__sub_822C4330);
|
||||||
|
PPC_FUNC(sub_822C4330)
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
auto saveFileSize = std::filesystem::file_size(GetSaveFilePath(true), ec);
|
||||||
|
|
||||||
|
auto expectedSize = ctx.r5.u32;
|
||||||
|
auto expectedSizeAdd = *(be<uint32_t>*)g_memory.Translate(0x83262110);
|
||||||
|
|
||||||
|
// TODO: check for backups here and restore them?
|
||||||
|
if (saveFileSize != expectedSize + expectedSizeAdd)
|
||||||
|
{
|
||||||
|
App::s_isSaveDataCorrupt = true;
|
||||||
|
|
||||||
|
g_corruptSaveMessageOpen = true;
|
||||||
|
g_corruptSaveMessageOpen.wait(true);
|
||||||
|
|
||||||
|
ctx.r3.u32 = 0;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.r3.u32 = 1;
|
||||||
|
}
|
||||||
|
|
||||||
// SWA::CTitleStateIntro::Update
|
// SWA::CTitleStateIntro::Update
|
||||||
PPC_FUNC_IMPL(__imp__sub_82587E50);
|
PPC_FUNC_IMPL(__imp__sub_82587E50);
|
||||||
PPC_FUNC(sub_82587E50)
|
PPC_FUNC(sub_82587E50)
|
||||||
|
|
@ -47,7 +97,7 @@ PPC_FUNC(sub_82587E50)
|
||||||
{
|
{
|
||||||
__imp__sub_82587E50(ctx, base);
|
__imp__sub_82587E50(ctx, base);
|
||||||
}
|
}
|
||||||
else
|
else if (!ProcessCorruptSaveMessage())
|
||||||
{
|
{
|
||||||
auto pInputState = SWA::CInputState::GetInstance();
|
auto pInputState = SWA::CInputState::GetInstance();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,10 @@ PPC_FUNC(sub_825882B8)
|
||||||
auto isOptionsIndex = pTitleState->m_pMember->m_pTitleMenu->m_CursorIndex == 2;
|
auto isOptionsIndex = pTitleState->m_pMember->m_pTitleMenu->m_CursorIndex == 2;
|
||||||
auto isInstallIndex = pTitleState->m_pMember->m_pTitleMenu->m_CursorIndex == 3;
|
auto isInstallIndex = pTitleState->m_pMember->m_pTitleMenu->m_CursorIndex == 3;
|
||||||
|
|
||||||
|
// Always default to New Game with corrupted save data.
|
||||||
|
if (App::s_isSaveDataCorrupt && pTitleState->m_pMember->m_pTitleMenu->m_CursorIndex == 1)
|
||||||
|
pTitleState->m_pMember->m_pTitleMenu->m_CursorIndex = 0;
|
||||||
|
|
||||||
if (!OptionsMenu::s_isVisible && isOptionsIndex)
|
if (!OptionsMenu::s_isVisible && isOptionsIndex)
|
||||||
{
|
{
|
||||||
if (OptionsMenu::s_isRestartRequired)
|
if (OptionsMenu::s_isRestartRequired)
|
||||||
|
|
@ -92,6 +96,14 @@ PPC_FUNC(sub_825882B8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TitleMenuRemoveContinueOnCorruptSaveMidAsmHook(PPCRegister& r3)
|
||||||
|
{
|
||||||
|
if (!App::s_isSaveDataCorrupt)
|
||||||
|
return;
|
||||||
|
|
||||||
|
r3.u64 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void TitleMenuRemoveStorageDeviceOptionMidAsmHook(PPCRegister& r11)
|
void TitleMenuRemoveStorageDeviceOptionMidAsmHook(PPCRegister& r11)
|
||||||
{
|
{
|
||||||
r11.u32 = 0;
|
r11.u32 = 0;
|
||||||
|
|
|
||||||
|
|
@ -663,3 +663,8 @@ registers = ["r3"]
|
||||||
name = "InspireSubtitleMidAsmHook"
|
name = "InspireSubtitleMidAsmHook"
|
||||||
address = 0x82B949B0
|
address = 0x82B949B0
|
||||||
registers = ["r3"]
|
registers = ["r3"]
|
||||||
|
|
||||||
|
[[midasm_hook]]
|
||||||
|
name = "TitleMenuRemoveContinueOnCorruptSaveMidAsmHook"
|
||||||
|
address = 0x82585470
|
||||||
|
registers = ["r3"]
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue