diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt index dc23e8e4..2d6400b1 100644 --- a/config/RSPE01_01/symbols.txt +++ b/config/RSPE01_01/symbols.txt @@ -6850,7 +6850,7 @@ fn_801831D0 = .text:0x801831D0; // type:function size:0x8 fn_801831D8 = .text:0x801831D8; // type:function size:0x8 fn_801831E0 = .text:0x801831E0; // type:function size:0x8 fn_801831E8 = .text:0x801831E8; // type:function size:0x8 -fn_801831F0 = .text:0x801831F0; // type:function size:0xD8 +systemShutDown__11RPSysSystemFv = .text:0x801831F0; // type:function size:0xD8 fn_801832C8 = .text:0x801832C8; // type:function size:0x28 fn_801832F0 = .text:0x801832F0; // type:function size:0x18 fn_80183308 = .text:0x80183308; // type:function size:0xC @@ -6958,7 +6958,7 @@ fn_80185CE0 = .text:0x80185CE0; // type:function size:0x48 fn_80185D28 = .text:0x80185D28; // type:function size:0xC fn_80185D34 = .text:0x80185D34; // type:function size:0x40 fn_80185D74 = .text:0x80185D74; // type:function size:0x190 -fn_80185F04 = .text:0x80185F04; // type:function size:0x14 +isDvdErrorApplicationEnd__13RPSysSceneMgrCFv = .text:0x80185F04; // type:function size:0x14 fn_80185F18 = .text:0x80185F18; // type:function size:0x20 fn_80185F38 = .text:0x80185F38; // type:function size:0x18 fn_80185F50 = .text:0x80185F50; // type:function size:0x14 @@ -7031,11 +7031,11 @@ fn_80187D78 = .text:0x80187D78; // type:function size:0x44 fn_80187DBC = .text:0x80187DBC; // type:function size:0x128 fn_80187EE4 = .text:0x80187EE4; // type:function size:0x40 fn_80187F24 = .text:0x80187F24; // type:function size:0x40 -fn_80187F64 = .text:0x80187F64; // type:function size:0x40 -fn_80187FA4 = .text:0x80187FA4; // type:function size:0x1E8 -fn_8018818C = .text:0x8018818C; // type:function size:0xD4 -fn_80188260 = .text:0x80188260; // type:function size:0x20 -fn_80188280 = .text:0x80188280; // type:function size:0xE8 +__dt__14RPSysDvdStatusFv = .text:0x80187F64; // type:function size:0x40 +draw__14RPSysDvdStatusFv = .text:0x80187FA4; // type:function size:0x1E8 +update__14RPSysDvdStatusFv = .text:0x8018818C; // type:function size:0xD4 +isErrorOccured__14RPSysDvdStatusCFv = .text:0x80188260; // type:function size:0x20 +CreateInstance__14RPSysDvdStatusFPQ23EGG4Heap = .text:0x80188280; // type:function size:0xE8 __dt__16RPSysSaveDataMgrFv = .text:0x80188368; // type:function size:0x58 __ct__16RPSysSaveDataMgrFPQ23EGG4Heap = .text:0x801883C0; // type:function size:0x130 saveDataFunc__16RPSysSaveDataMgrFPv = .text:0x801884F0; // type:function size:0x30 @@ -7525,7 +7525,7 @@ fn_8019B730 = .text:0x8019B730; // type:function size:0x8 fn_8019B738 = .text:0x8019B738; // type:function size:0x8 fn_8019B740 = .text:0x8019B740; // type:function size:0x54 fn_8019B794 = .text:0x8019B794; // type:function size:0x48 -fn_8019B7DC = .text:0x8019B7DC; // type:function size:0x44 +stopMotorAll__19RPSysCoreControllerFv = .text:0x8019B7DC; // type:function size:0x44 fn_8019B820 = .text:0x8019B820; // type:function size:0x4 fn_8019B824 = .text:0x8019B824; // type:function size:0x38 fn_8019B85C = .text:0x8019B85C; // type:function size:0x28C @@ -7661,7 +7661,7 @@ fn_801A40BC = .text:0x801A40BC; // type:function size:0x814 fn_801A48D0 = .text:0x801A48D0; // type:function size:0x60 fn_801A4930 = .text:0x801A4930; // type:function size:0x24 fn_801A4954 = .text:0x801A4954; // type:function size:0x2C -fn_801A4980 = .text:0x801A4980; // type:function size:0x390 +update__16RPSysHomeMenuMgrFv = .text:0x801A4980; // type:function size:0x390 fn_801A4D10 = .text:0x801A4D10; // type:function size:0x58 fn_801A4D68 = .text:0x801A4D68; // type:function size:0x124 fn_801A4E8C = .text:0x801A4E8C; // type:function size:0x12C @@ -15064,23 +15064,7 @@ lbl_80382606 = .rodata:0x80382606; // type:object size:0xD data:string lbl_80382613 = .rodata:0x80382613; // type:object size:0xE data:string lbl_80382621 = .rodata:0x80382621; // type:object size:0xD data:string lbl_8038262E = .rodata:0x8038262E; // type:object size:0x8A -lbl_803826B8 = .rodata:0x803826B8; // type:object size:0xB data:string -lbl_803826C3 = .rodata:0x803826C3; // type:object size:0x13 data:string -lbl_803826D6 = .rodata:0x803826D6; // type:object size:0xC data:string -lbl_803826E2 = .rodata:0x803826E2; // type:object size:0x5D data:string -lbl_8038273F = .rodata:0x8038273F; // type:object size:0x1 -lbl_80382740 = .rodata:0x80382740; // type:object size:0x1F -lbl_8038275F = .rodata:0x8038275F; // type:object size:0x2 data:string -lbl_80382761 = .rodata:0x80382761; // type:object size:0x6C -lbl_803827CD = .rodata:0x803827CD; // type:object size:0x13 data:string -lbl_803827E0 = .rodata:0x803827E0; // type:object size:0xB data:string -lbl_803827EB = .rodata:0x803827EB; // type:object size:0x74 data:string -lbl_8038285F = .rodata:0x8038285F; // type:object size:0x17 data:string -lbl_80382876 = .rodata:0x80382876; // type:object size:0x76 data:string -lbl_803828EC = .rodata:0x803828EC; // type:object size:0x15 data:string -lbl_80382901 = .rodata:0x80382901; // type:object size:0x6F -lbl_80382970 = .rodata:0x80382970; // type:object size:0x23 -lbl_80382993 = .rodata:0x80382993; // type:object size:0x4D +@stringBase0 = .rodata:0x803826B8; // type:object size:0x326 scope:local data:string lbl_803829E0 = .rodata:0x803829E0; // type:object size:0xB data:string lbl_803829EB = .rodata:0x803829EB; // type:object size:0x10 data:string lbl_803829FB = .rodata:0x803829FB; // type:object size:0x35 @@ -18587,9 +18571,15 @@ __vt__20RPSysResourceManager = .data:0x803B9860; // type:object size:0x10 scope: __vt__16RPSysQueuedScene = .data:0x803B9870; // type:object size:0x10 scope:global __vt__17RPSysCommonObject = .data:0x803B9880; // type:object size:0x14 scope:global __vt__11RPGrpScreen = .data:0x803B9894; // type:object size:0x14 scope:global -lbl_803B98A8 = .data:0x803B98A8; // type:object size:0x60 -jumptable_803B9908 = .data:0x803B9908; // type:object size:0x20 scope:local -lbl_803B9928 = .data:0x803B9928; // type:object size:0x10 +LANGUAGE_ENG__14RPSysDvdStatus = .data:0x803B98A8; // type:object size:0x10 +...data.0 = .data:0x803B98A8; // type:label scope:local +LANGUAGE_FRA__14RPSysDvdStatus = .data:0x803B98B8; // type:object size:0x10 scope:global +LANGUAGE_GER__14RPSysDvdStatus = .data:0x803B98C8; // type:object size:0x10 scope:global +LANGUAGE_ITA__14RPSysDvdStatus = .data:0x803B98D8; // type:object size:0x10 scope:global +LANGUAGE_SPA__14RPSysDvdStatus = .data:0x803B98E8; // type:object size:0x10 scope:global +LANGUAGE_JPN__14RPSysDvdStatus = .data:0x803B98F8; // type:object size:0x10 scope:global +@20963 = .data:0x803B9908; // type:object size:0x20 scope:local +__vt__14RPSysDvdStatus = .data:0x803B9928; // type:object size:0xC __vt__16RPSysSaveDataMgr = .data:0x803B9938; // type:object size:0x14 RES_FONT_NAMES__16RPSysFontManager = .data:0x803B9950; // type:object size:0x1C __vt__16RPSysFontManager = .data:0x803B996C; // type:object size:0xC @@ -20450,7 +20440,7 @@ scFileNames = .sdata:0x804BDB68; // type:object size:0x8 scope:local scFirstDirectory = .sdata:0x804BDB70; // type:object size:0x4 scope:local data:4byte scSecondDirectory = .sdata:0x804BDB74; // type:object size:0x4 scope:local data:4byte lbl_804BDB78 = .sdata:0x804BDB78; // type:object size:0x8 data:4byte -lbl_804BDB80 = .sdata:0x804BDB80; // type:object size:0x8 data:4byte +GAME_DISK_NAME__14RPSysDvdStatus = .sdata:0x804BDB80; // type:object size:0x4 data:4byte lbl_804BDB88 = .sdata:0x804BDB88; // type:object size:0x8 data:4byte lbl_804BDB90 = .sdata:0x804BDB90; // type:object size:0x8 data:4byte lbl_804BDB98 = .sdata:0x804BDB98; // type:object size:0x8 data:4byte @@ -21870,12 +21860,12 @@ lbl_804BF4C0 = .sbss:0x804BF4C0; // type:object size:0x4 data:4byte lbl_804BF4C4 = .sbss:0x804BF4C4; // type:object size:0x4 data:4byte lbl_804BF4C8 = .sbss:0x804BF4C8; // type:object size:0x8 data:4byte lbl_804BF4D0 = .sbss:0x804BF4D0; // type:object size:0x8 data:4byte -lbl_804BF4D8 = .sbss:0x804BF4D8; // type:object size:0x8 data:4byte +spInstance__13RPSysSceneMgr = .sbss:0x804BF4D8; // type:object size:0x8 data:4byte spInstance__17RPSysProjectLocal = .sbss:0x804BF4E0; // type:object size:0x4 data:4byte spInstance__15RPSysGameConfig = .sbss:0x804BF4E8; // type:object size:0x4 data:4byte spInstance__20RPSysResourceManager = .sbss:0x804BF4F0; // type:object size:0x8 data:4byte lbl_804BF4F8 = .sbss:0x804BF4F8; // type:object size:0x8 data:4byte -lbl_804BF500 = .sbss:0x804BF500; // type:object size:0x8 data:4byte +spInstance__14RPSysDvdStatus = .sbss:0x804BF500; // type:object size:0x4 data:4byte spInstance__16RPSysSaveDataMgr = .sbss:0x804BF508; // type:object size:0x8 data:4byte spInstance__16RPSysFontManager = .sbss:0x804BF510; // type:object size:0x8 data:4byte lbl_804BF518 = .sbss:0x804BF518; // type:object size:0x8 data:4byte @@ -21905,7 +21895,7 @@ lbl_804BF588 = .sbss:0x804BF588; // type:object size:0x8 data:4byte lbl_804BF590 = .sbss:0x804BF590; // type:object size:0x8 align:4 data:float lbl_804BF598 = .sbss:0x804BF598; // type:object size:0x8 data:4byte lbl_804BF5A0 = .sbss:0x804BF5A0; // type:object size:0x8 data:4byte -lbl_804BF5A8 = .sbss:0x804BF5A8; // type:object size:0x4 data:4byte +spInstance__16RPSysHomeMenuMgr = .sbss:0x804BF5A8; // type:object size:0x4 data:4byte lbl_804BF5AC = .sbss:0x804BF5AC; // type:object size:0x4 data:4byte sIsSyncing__22RPSysControllerSyncMgr = .sbss:0x804BF5B0; // type:object size:0x1 data:byte lbl_804BF5B8 = .sbss:0x804BF5B8; // type:object size:0x2 data:2byte @@ -23476,12 +23466,12 @@ lbl_804C1538 = .sdata2:0x804C1538; // type:object size:0x4 align:4 data:float lbl_804C153C = .sdata2:0x804C153C; // type:object size:0x4 align:4 data:float lbl_804C1540 = .sdata2:0x804C1540; // type:object size:0x8 align:4 data:float lbl_804C1548 = .sdata2:0x804C1548; // type:object size:0x8 align:4 data:float -lbl_804C1550 = .sdata2:0x804C1550; // type:object size:0x4 align:4 data:float -lbl_804C1554 = .sdata2:0x804C1554; // type:object size:0x4 align:4 data:float -lbl_804C1558 = .sdata2:0x804C1558; // type:object size:0x4 align:4 data:float -lbl_804C155C = .sdata2:0x804C155C; // type:object size:0x4 align:4 data:float -lbl_804C1560 = .sdata2:0x804C1560; // type:object size:0x4 align:4 data:float -lbl_804C1564 = .sdata2:0x804C1564; // type:object size:0x4 align:4 data:float +@20899 = .sdata2:0x804C1550; // type:object size:0x4 scope:local align:4 data:float +@20900 = .sdata2:0x804C1554; // type:object size:0x4 scope:local align:4 data:float +@20901 = .sdata2:0x804C1558; // type:object size:0x4 scope:local align:4 data:float +@20959 = .sdata2:0x804C155C; // type:object size:0x4 scope:local align:4 data:float +@20960 = .sdata2:0x804C1560; // type:object size:0x4 scope:local align:4 data:float +@20961 = .sdata2:0x804C1564; // type:object size:0x4 scope:local align:4 data:float @8740 = .sdata2:0x804C1568; // type:object size:0x4 scope:local align:4 data:float @8741 = .sdata2:0x804C156C; // type:object size:0x4 scope:local align:4 data:float lbl_804C1570 = .sdata2:0x804C1570; // type:object size:0x4 align:4 data:float diff --git a/configure.py b/configure.py index 34432d48..bd0396d6 100755 --- a/configure.py +++ b/configure.py @@ -1213,7 +1213,7 @@ def MatchingFor(*versions): Object(NonMatching, "Pack/RPSystem/RPSysResourceManager.cpp"), Object(NonMatching, "Pack/RPSystem/RPSysQueuedScene.cpp"), Object(NonMatching, "Pack/RPSystem/RPSysCommonObject.cpp"), - Object(NonMatching, "Pack/RPSystem/RPSysDvdStatus.cpp"), + Object(Matching, "Pack/RPSystem/RPSysDvdStatus.cpp"), Object(NonMatching, "Pack/RPSystem/RPSysSaveDataMgr.cpp"), Object(Matching, "Pack/RPSystem/RPSportsSystemData.cpp"), Object(Matching, "Pack/RPSystem/RPSportsPlayerData.cpp"), diff --git a/include/Pack/RPKernel.h b/include/Pack/RPKernel.h index 2b779036..1e5ff85f 100644 --- a/include/Pack/RPKernel.h +++ b/include/Pack/RPKernel.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Pack/RPKernel/RPSysController.h b/include/Pack/RPKernel/RPSysController.h index 94001dca..25e6fa54 100644 --- a/include/Pack/RPKernel/RPSysController.h +++ b/include/Pack/RPKernel/RPSysController.h @@ -41,6 +41,8 @@ class RPSysCoreController : public EGG::CoreController { public: bool isPrevDpdCtrlEnable(); + static void stopMotorAll(); + const RPSysCoreAddress& getAddress() const { return mAddress; } diff --git a/include/Pack/RPKernel/RPSysHomeMenuMgr.h b/include/Pack/RPKernel/RPSysHomeMenuMgr.h new file mode 100644 index 00000000..133bbfc6 --- /dev/null +++ b/include/Pack/RPKernel/RPSysHomeMenuMgr.h @@ -0,0 +1,22 @@ +#ifndef RP_KERNEL_HOME_MENU_MANAGER_H +#define RP_KERNEL_HOME_MENU_MANAGER_H +#include + +#include + +//! @addtogroup rp_kernel +//! @{ + +/** + * @brief HBM library manager + */ +class RPSysHomeMenuMgr { + RP_SINGLETON_DECL_EX(RPSysHomeMenuMgr); + +public: + void update(); +}; + +//! @} + +#endif diff --git a/include/Pack/RPSystem.h b/include/Pack/RPSystem.h index 9abd52f2..65aece80 100644 --- a/include/Pack/RPSystem.h +++ b/include/Pack/RPSystem.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Pack/RPSystem/RPSysDvdStatus.h b/include/Pack/RPSystem/RPSysDvdStatus.h new file mode 100644 index 00000000..56ff36e5 --- /dev/null +++ b/include/Pack/RPSystem/RPSysDvdStatus.h @@ -0,0 +1,98 @@ +#ifndef RP_SYSTEM_DVD_STATUS_H +#define RP_SYSTEM_DVD_STATUS_H +#include + +#include +#include + +#include + +//! @addtogroup rp_system +//! @{ + +/** + * @brief Disc drive status + */ +class RPSysDvdStatus { + RP_SINGLETON_DECL_EX(RPSysDvdStatus); + +public: + /** + * @brief Updates the status of the disc drive + * @return Whether the disc drive status is OK + */ + bool update(); + + /** + * @brief Displays the disc drive error message + */ + void draw(); + +private: + /** + * @brief Disc drive error type + */ + enum EErrorStatus { + EErrorStatus_Success = -2, + EErrorStatus_Busy, //!< Drive is busy + EErrorStatus_NoOrWrongDisk, //!< Disk is ejected or is the wrong game + EErrorStatus_DiskError, //!< Cannot read from the disk + EErrorStatus_Fatal //!< Fatal error + }; + + //! Number of error messages per language + static const int ERROR_MESSAGE_KIND_NUM = + (EErrorStatus_DiskError - EErrorStatus_NoOrWrongDisk) + 1; + + //! Number of strings per error message + static const int ERROR_MESSAGE_STRING_NUM = 2; + + //! Size of the error message buffer + static const int MESSAGE_BUFFER_SIZE = 256; + +private: + /** + * @brief Tests whether a disc drive error has occurred + * @typo + */ + bool isErrorOccured() const; + +private: + //! Game disc name + static const char* GAME_DISK_NAME; + + //! English error message language + static const char* LANGUAGE_ENG[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM]; + + //! French error message language + static const char* LANGUAGE_FRA[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM]; + + //! German error message language + static const char* LANGUAGE_GER[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM]; + + //! Italian error message language + static const char* LANGUAGE_ITA[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM]; + + //! Spanish error message language + static const char* LANGUAGE_SPA[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM]; + + //! Japanese error message language + static const char* LANGUAGE_JPN[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM]; + + //! DVD error status + EErrorStatus mErrorStatus; // at 0x8 + //! Error message text + char* mpErrorMessage; // at 0xC + //! Fader for the background + EGG::ColorFader* mpErrorFader; // at 0x10 +}; + +//! @} + +#endif diff --git a/include/Pack/RPSystem/RPSysSceneMgr.h b/include/Pack/RPSystem/RPSysSceneMgr.h index 3de33b66..183e5c6e 100644 --- a/include/Pack/RPSystem/RPSysSceneMgr.h +++ b/include/Pack/RPSystem/RPSysSceneMgr.h @@ -18,6 +18,7 @@ class RPSysSceneMgr : public EGG::SceneManager { public: bool isShutDownReserved() const; + bool isDvdErrorApplicationEnd() const; RPSysScene* getCurrentSceneRP() const; diff --git a/src/Pack/RPAudio/RPSndAudioMgr.cpp b/src/Pack/RPAudio/RPSndAudioMgr.cpp index fbc723ad..bcb5f53c 100644 --- a/src/Pack/RPAudio/RPSndAudioMgr.cpp +++ b/src/Pack/RPAudio/RPSndAudioMgr.cpp @@ -232,14 +232,8 @@ RPSndAudioMgr::attachArchive(const char* pPath, bool staticPath, pResMgr->GetGameSoundLocalPath(localPath, ARRAY_SIZE(localPath)); } - // @bug Unsafe string operations -#if defined(BUG_FIX) - std::strncat(commonPath, pPath, ARRAY_SIZE(commonPath)); - std::strncat(localPath, pPath, ARRAY_SIZE(localPath)); -#else std::strcat(commonPath, pPath); std::strcat(localPath, pPath); -#endif void* pMultiHandle = pResMgr->GetMultiHandle(); @@ -253,13 +247,7 @@ RPSndAudioMgr::attachArchive(const char* pPath, bool staticPath, // Fallback to the music experiment scene? std::strcpy(expPath, "Sound/RPMpeScene/"); - - // @bug Unsafe string operations -#if defined(BUG_FIX) - std::strcat(expPath, pPath, ARRAY_SIZE(expPath)); -#else std::strcat(expPath, pPath); -#endif if (pResMgr->IsExist(expPath)) { return openArchiveRP(expPath, pHeap, pMultiHandle); diff --git a/src/Pack/RPSystem/RPSysDvdStatus.cpp b/src/Pack/RPSystem/RPSysDvdStatus.cpp new file mode 100644 index 00000000..79518673 --- /dev/null +++ b/src/Pack/RPSystem/RPSysDvdStatus.cpp @@ -0,0 +1,291 @@ +#include +#include +#include + +#include +#include + +#include + +RP_SINGLETON_IMPL_EX(RPSysDvdStatus); + +/** + * @brief Game disc name + */ +#if defined(PACK_SPORTS) +const char* RPSysDvdStatus::GAME_DISK_NAME = "Wii Sports"; +#elif defined(PACK_PARTY) +const char* RPSysDvdStatus::GAME_DISK_NAME = "Wii Play"; +#endif + +/** + * @brief English error message language + */ +// clang-format off +const char* RPSysDvdStatus::LANGUAGE_ENG[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM] = { + "Please insert the ", + + "\nGame Disc.", + + "The Game Disc could not be read.\n" + "Please read the Wii Operations\n" + "Manual for more information.", + + "", +}; +// clang-format on + +/** + * @brief French error message language + */ +// clang-format off +const char* RPSysDvdStatus::LANGUAGE_FRA[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM] = { + "Veuillez ins\xE9""rer le disque de\n", + + ".", + + "La lecture du disque a \xE9""chou\xE9.\n" + "Veuillez vous r\xE9""f\xE9rer\n" + "au mode d'emploi Wii\n" + "pour de plus amples informations.", + + "", +}; +// clang-format on + +/** + * @brief German error message language + */ +// clang-format off +const char* RPSysDvdStatus::LANGUAGE_GER[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM] = { + "Bitte schiebe die\n", + + "-Disc ein.", + + "Diese Disc kann nicht gelesen werden.\n" + "Bitte lies die Wii-Bedienungsanleitung,\n" + "um weitere Informationen zu erhalten.", + + "", +}; +// clang-format on + +/** + * @brief Italian error message language + */ +// clang-format off +const char* RPSysDvdStatus::LANGUAGE_ITA[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM] = { + "Inserisci il disco di ", + + ".", + + "Impossibile leggere il disco di gioco.\n" + "Per maggiori informazioni consulta\n" + "il manuale di istruzioni della console Wii.", + + "", +}; +// clang-format on + +/** + * @brief Spanish error message language + */ +// clang-format off +const char* RPSysDvdStatus::LANGUAGE_SPA[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM] = { + "Inserta el disco de ", + + ".", + + "No se puede leer el disco.\n" + "Consulta el manual de\n" + "instrucciones de la consola Wii\n" + "para obtener m\xE1s informaci\xF3n.", + + "", +}; +// clang-format on + +/** + * @brief Japanese error message language + */ +// clang-format off +const char* RPSysDvdStatus::LANGUAGE_JPN[ERROR_MESSAGE_STRING_NUM] + [ERROR_MESSAGE_KIND_NUM] = { + "", + + " のディスクを\nセットしてください。", + + "ディスクを読めませんでした。\n" + "詳しくは、本体の取扱説明書を\n" + "お読みください。", + + "", +}; +// clang-format on + +/** + * @brief Tests whether a disc drive error has occurred + * @typo + */ +bool RPSysDvdStatus::isErrorOccured() const { + return mErrorStatus > EErrorStatus_Busy; +} + +/** + * @brief Updates the status of the disc drive + * @return Whether the disc drive status is OK + */ +bool RPSysDvdStatus::update() { + s32 status = DVDGetDriveStatus(); + + if (status == DVD_STATE_FATAL) { + mErrorStatus = EErrorStatus_Fatal; + } else if (status == DVD_STATE_DISK_ERROR) { + mErrorStatus = EErrorStatus_DiskError; + } else if (status == DVD_STATE_NO_DISK) { + mErrorStatus = EErrorStatus_NoOrWrongDisk; + } else if (status == DVD_STATE_WRONG_DISK_ID) { + mErrorStatus = EErrorStatus_NoOrWrongDisk; + } else if (status == DVD_STATE_BUSY) { + mErrorStatus = EErrorStatus_Busy; + } else { + mErrorStatus = EErrorStatus_Success; + } + + if (isErrorOccured()) { + RPSysCoreController::stopMotorAll(); + RP_GET_INSTANCE(RPSysHomeMenuMgr)->update(); + + if (RP_GET_INSTANCE(RPSysSceneMgr)->isDvdErrorApplicationEnd()) { + RP_GET_INSTANCE(RPSysSystem)->systemShutDown(); + } + + return false; + } + + return true; +} + +/** + * @brief Displays the disc drive error message + */ +void RPSysDvdStatus::draw() { + if (!isErrorOccured()) { + return; + } + + VISetBlack(FALSE); + mpErrorFader->draw(); + + if (mErrorStatus < ERROR_MESSAGE_KIND_NUM) { + RP_GET_INSTANCE(RPSysTextWriter)->SetupGX(); + + // Always pass the Z test (draw over everything) + GXSetZMode(GX_FALSE, GX_ALWAYS, GX_FALSE); + + RP_GET_INSTANCE(RPSysTextWriter) + ->SetDrawFlag(RPSysTextWriter::DRAWFLAG_ALIGN_H_CENTER | + RPSysTextWriter::DRAWFLAG_ALIGN_V_CENTER); + + RP_GET_INSTANCE(RPSysTextWriter)->SetScale(1.0f, 1.0f); + RP_GET_INSTANCE(RPSysTextWriter)->SetTextColor(nw4r::ut::Color::WHITE); + RP_GET_INSTANCE(RPSysTextWriter)->SetCursor(320.0f, 228.0f); + + const char** pLanguage = NULL; + + switch (RP_GET_INSTANCE(RPSysProjectLocal)->getLocale()) { + case RPSysProjectLocal::EArea_England: { + pLanguage = LANGUAGE_ENG[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_France: { + pLanguage = LANGUAGE_FRA[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_Germany: { + pLanguage = LANGUAGE_GER[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_Italy: { + pLanguage = LANGUAGE_ITA[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_Spain: { + pLanguage = LANGUAGE_SPA[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_Netherlands: { + pLanguage = LANGUAGE_ENG[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_Japan: { + pLanguage = LANGUAGE_JPN[mErrorStatus]; + break; + } + + case RPSysProjectLocal::EArea_USA: { + pLanguage = LANGUAGE_ENG[mErrorStatus]; + break; + } + + default: { + break; + } + } + +#if defined(BUG_FIX) + std::strncpy(mpErrorMessage, pLanguage[0], MESSAGE_BUFFER_SIZE); + + if (mErrorStatus == EErrorStatus_NoOrWrongDisk || + mErrorStatus == EErrorStatus_DiskError) { + + std::strcat(mpErrorMessage, GAME_DISK_NAME); + std::strcat(mpErrorMessage, pLanguage[1]); + } +#else + // @bug Unsafe string operations + std::strcpy(mpErrorMessage, pLanguage[0]); + + // @bug Same comparison twice (one should be EErrorStatus_DiskError) + if (mErrorStatus == EErrorStatus_NoOrWrongDisk || + mErrorStatus == EErrorStatus_NoOrWrongDisk) { + + std::strcat(mpErrorMessage, GAME_DISK_NAME); + std::strcat(mpErrorMessage, pLanguage[1]); + } +#endif + + RP_GET_INSTANCE(RPSysTextWriter) + ->Print(mpErrorMessage, std::strlen(mpErrorMessage)); + } +} + +/** + * @brief Constructor + * + * @param pHeap Parent heap + */ +RPSysDvdStatus::RPSysDvdStatus(EGG::Heap* pHeap) + : mpParentHeap(pHeap), mErrorStatus(EErrorStatus_Success) { + + mpErrorMessage = new (pHeap) char[MESSAGE_BUFFER_SIZE]; + + mpErrorFader = new (pHeap) EGG::ColorFader(0.0f, 0.0f, 640.0f, 456.0f); + mpErrorFader->setStatus(EGG::ColorFader::STATUS_PREPARE_IN); +} + +/** + * @brief Destructor + */ +RPSysDvdStatus::~RPSysDvdStatus() {}