diff --git a/config/RSPE01_01/symbols.txt b/config/RSPE01_01/symbols.txt index 7f654f05d..397a537ea 100644 --- a/config/RSPE01_01/symbols.txt +++ b/config/RSPE01_01/symbols.txt @@ -7660,19 +7660,19 @@ fn_801A3F08 = .text:0x801A3F08; // type:function size:0x10C fn_801A4014 = .text:0x801A4014; // type:function size:0xA8 fn_801A40BC = .text:0x801A40BC; // type:function size:0x814 fn_801A48D0 = .text:0x801A48D0; // type:function size:0x60 -beginDrawScreen__16RPSysHomeMenuMgrFv = .text:0x801A4930; // type:function size:0x24 +drawBanIcon__16RPSysHomeMenuMgrFv = .text:0x801A4930; // type:function size:0x24 draw__16RPSysHomeMenuMgrFv = .text:0x801A4954; // type:function size:0x2C update__16RPSysHomeMenuMgrFv = .text:0x801A4980; // type:function size:0x390 -startBlackOut__16RPSysHomeMenuMgrFv = .text:0x801A4D10; // type:function size:0x58 -clearMenu__16RPSysHomeMenuMgrFv = .text:0x801A4D68; // type:function size:0x124 -updateOutside__16RPSysHomeMenuMgrFv = .text:0x801A4E8C; // type:function size:0x12C -LoadResource__16RPSysHomeMenuMgrFv = .text:0x801A4FB8; // type:function size:0x224 +softReset__16RPSysHomeMenuMgrFv = .text:0x801A4D10; // type:function size:0x58 +checkMenuEnd__16RPSysHomeMenuMgrFv = .text:0x801A4D68; // type:function size:0x124 +checkMenuStart__16RPSysHomeMenuMgrFv = .text:0x801A4E8C; // type:function size:0x12C +initHomeButtonInfo__16RPSysHomeMenuMgrFv = .text:0x801A4FB8; // type:function size:0x224 init__16RPSysHomeMenuMgrFv = .text:0x801A51DC; // type:function size:0x68 __dt__16RPSysHomeMenuMgrFv = .text:0x801A5244; // type:function size:0x40 __ct__16RPSysHomeMenuMgrFPQ23EGG4Heap = .text:0x801A5284; // type:function size:0x1AC -soundCallBack__16RPSysHomeMenuMgrFiUl = .text:0x801A5430; // type:function size:0x54 -drawScreen__Q216RPSysHomeMenuMgr12fileAccessorFv = .text:0x801A5484; // type:function size:0x158 -fn_801A55DC = .text:0x801A55DC; // type:function size:0x11C +soundCallback__16RPSysHomeMenuMgrFii = .text:0x801A5430; // type:function size:0x54 +draw__Q216RPSysHomeMenuMgr7BanIconFv = .text:0x801A5484; // type:function size:0x158 +calc__Q216RPSysHomeMenuMgr7BanIconFv = .text:0x801A55DC; // type:function size:0x11C CreateInstance__16RPSysHomeMenuMgrFPQ23EGG4Heap = .text:0x801A56F8; // type:function size:0x60 GetValidNum__15RPSysOfficialDBFv = .text:0x801A5758; // type:function size:0xA8 Reset__15RPSysOfficialDBFv = .text:0x801A5800; // type:function size:0x7C @@ -20454,7 +20454,7 @@ lbl_804BDBD8 = .sdata:0x804BDBD8; // type:object size:0x8 lbl_804BDBE0 = .sdata:0x804BDBE0; // type:object size:0x8 lbl_804BDBE8 = .sdata:0x804BDBE8; // type:object size:0x8 lbl_804BDBF0 = .sdata:0x804BDBF0; // type:object size:0x8 -lbl_804BDBF8 = .sdata:0x804BDBF8; // type:object size:0x8 data:4byte +sSoundHeapSize__16RPSysHomeMenuMgr = .sdata:0x804BDBF8; // type:object size:0x4 data:4byte sSuccess__17RPSysNWC24Manager = .sdata:0x804BDC00; // type:object size:0x4 data:4byte lbl_804BDC08 = .sdata:0x804BDC08; // type:object size:0x4 data:4byte lbl_804BDC0C = .sdata:0x804BDC0C; // type:object size:0x4 data:4byte diff --git a/include/Pack/RPAudio/RPSndHomeMenuArcMgr.h b/include/Pack/RPAudio/RPSndHomeMenuArcMgr.h index c1620125f..e6365bf44 100644 --- a/include/Pack/RPAudio/RPSndHomeMenuArcMgr.h +++ b/include/Pack/RPAudio/RPSndHomeMenuArcMgr.h @@ -35,6 +35,16 @@ class RPSndHomeMenuArcMgr : public EGG::SoundHeapMgr, public EGG::ArcPlayer { */ bool setupArchive(const void* pBinary); + /** + * @brief Attempts to start the specified sound + * + * @param id Sound ID + * @return Success + */ + bool startSe(u32 id) { + return startSound(&mSoundHandle, id); + } + private: //! Active sound handle nw4r::snd::SoundHandle mSoundHandle; // at 0x6A4 diff --git a/include/Pack/RPKernel/RPSysHomeMenuMgr.h b/include/Pack/RPKernel/RPSysHomeMenuMgr.h index a18f5a5cb..0c76e5051 100644 --- a/include/Pack/RPKernel/RPSysHomeMenuMgr.h +++ b/include/Pack/RPKernel/RPSysHomeMenuMgr.h @@ -12,79 +12,219 @@ //! @{ /** - * @brief Home menu manager + * @brief HOME Menu manager */ class RPSysHomeMenuMgr { RP_SINGLETON_DECL_EX(RPSysHomeMenuMgr); public: - //! This uses its own scheme instead of HBMSelectBtnNum for some reason - enum homeButtonState { - BUTTON_NONE, // used when inactive or returning to Wii Menu - BUTTON_OPEN, - BUTTON_CLOSE, // exiting Home Menu, but game still running - BUTTON_RESET, - BUTTON_MAX + /** + * @brief Icon when HOME Menu is disabled + */ + class BanIcon { + public: + /** + * @brief Constructor + */ + BanIcon(); + + /** + * @brief Updates this icon's state + */ + void calc(); + + /** + * @brief Renders this icon's state + */ + void draw(); + + /** + * @brief Resets this icon's state + */ + void clear() { + mState = EState_Hide; + mTimer = 0; + mAlpha = 0; + } + + /** + * @brief Enables this icon + */ + void switchOn() { + mState = EState_FadeIn; + mTimer = 0; + mAlpha = 0; + } + + /** + * @brief Tests whether this icon is visible + */ + bool isDisp() const { + return mState != EState_Hide; + } + + /** + * @brief Attaches a texture to this icon + * + * @param pTexture Icon texture + */ + void setTexture(const EGG::ResTIMG* pTexture) { + mpTexture = pTexture; + } + + private: + /** + * @brief State machine state + */ + enum EState { + EState_Hide, //!< Icon is not displaying + EState_FadeIn, //!< Icon is appearing + EState_Disp, //!< Icon is fully visible + EState_FadeOut, //!< Icon is disappearing + }; + + //! Time to fade in/out the icon, in frames + static const int FADE_LENGTH = 15; + //! Time to fully display the icon, in frames + static const int DISP_LENGTH = 60; + + private: + //! Ban icon texture + const EGG::ResTIMG* mpTexture; // at 0x0 + + //! State machine state + EState mState; // at 0x4 + //! Duration of the current state + s16 mTimer; // at 0x8 + + //! Calculated icon transparency + u16 mAlpha; // at 0xA }; - struct fileAccessor { - void* file; - BOOL UNK_0x04; // set to 1 if DVD error occurs in function 801A4E8C - u16 UNK_0x08; - u16 UNK_0x0A; - void drawScreen(); + /** + * @brief HOME Menu state + */ + enum EMenuState { + EMenuState_End, //!< Menu is closing + EMenuState_Start, //!< Menu is opening + EMenuState_Open, //!< Menu is interactable + EMenuState_Reset, //!< Menu is performing a soft reset }; - bool soundCallBack(int unk, u32 id); +public: + /** + * @brief Initializes this manager's state + */ void init(); - void LoadResource(); - void updateOutside(); - void clearMenu(); - BOOL startBlackOut(); + + /** + * @brief Initializes the HBM library + */ + void initHomeButtonInfo(); + + /** + * @brief Performs a soft reset + * + * @return Whether HBM will perform the reset + */ + bool softReset(); + + /** + * @brief Updates this manager's state + */ void update(); + + /** + * @brief Renders the HOME Menu if it is visible + */ void draw(); - void beginDrawScreen(); - bool isOpen() const { - return mIsOpen; + /** + * @brief Renders the ban icon if it is visible + */ + void drawBanIcon(); + + /** + * @brief Toggles whether the HOME Menu is disabled + * + * @param disable Whether to disable the menu + */ + void disable(bool disable) { + mIsDisabled = disable; + } + + /** + * @brief Tests whether the HOME Menu is currently active + */ + bool isActive() const { + return mIsActive; } private: + //! HBM work memory size + static const u32 HBM_WORK_SIZE = OS_MEM_KB_TO_B(512); + //! Size of the HBM config.txt file + static const u32 HBM_CONFIG_SIZE = 0x23; + +private: + /** + * @brief HBM library sound callback + * + * @param event HBM event + * @param arg Event argument + * @return Whether this callback handled the playback for HBM + */ + static BOOL soundCallback(int event, int arg); + + /** + * @brief Checks whether the HOME Menu should be opened + */ + void checkMenuStart(); - bool mResLoaded; // at 0x08 - bool mUNK_0x09; - bool mUNK_0x0A; - bool mIsOpen; // at 0x0B - u8 mUNK_0x0C; - bool mBlackOutCalled; // at 0x0D - homeButtonState mButtonState; // at 0x10 - u16 mUNK_0x14; - RPSysProjectLocal* mProjectLocal; // at 0x18 - fileAccessor* mFileAccessor; // at 0x1C - HBMDataInfo* mMenuDataInfo; // at 0x20 - u32 mUNK_0x24; - u32 mUNK_0x28; - u32 mUNK_0x2C; - void* mUNK_0x30; - void* mSoundCallback; // at 0x34 - u32 mUNK_0x38; - u32 mUNK_0x3C; - u32 mUNK_0x40; - u32 mUNK_0x44; // Seemingly skipped in constructor? - u32 mUNK_0x48; - u32 mUNK_0x4C; - f32 mUNK_0x50; // Set to 1.2 if the console is in PAL 50 Hz mode, - // otherwise 1.0 - f32 mScaleX; - f32 mAdjScaleX; - u32 mUNK_0x5C; - const HBMControllerData* mHbmControllerData; - Vec2 mVec2; - u8 mUNK_0x6C[50]; - KPADStatus mKpadStatus; //todo(texline) why is this duped? - u8 mPadding[396]; + /** + * @brief Checks whether the HOME Menu should be closed + */ + void checkMenuEnd(); +private: + //! HOME Menu sound archive manager static RPSndHomeMenuArcMgr* spHomeMenuArcMgr; + //! Sound archive heap size + static u32 sSoundHeapSize; + + //! Whether the HBM resources have been initialized + bool mIsInitialized; // at 0x8 + + //! Whether the menu is disabled + bool mIsDisabled; // at 0x9 + //! Whether the menu is opening due to a button press + bool mIsStarting; // at 0xA + //! Whether the menu is interactable + bool mIsActive; // at 0xB + //! Whether the menu should be drawn + bool mIsVisible; // at 0xC + + //! Whether a soft reset is in progress + bool mIsSoftReset; // at 0xD + + //! Current state machine state + EMenuState mMenuState; // at 0x10 + //! Current state duration + s16 mStateTimer; // at 0x14 + + //! Runtime project localization + RPSysProjectLocal* mpProjectLocal; // at 0x18 + + //! Menu ban icon + BanIcon* mpBanIcon; // at 0x1C + + //! HBM library configuration + HBMDataInfo mHBMDataInfo; // at 0x20 + + //! HBM controller input state + HBMControllerData mHBMControllerData; // at 0x60 + //! Local controller input state + KPADStatus mKPADStatus[KPAD_MAX_CONTROLLERS]; // at 0xA0 }; //! @} diff --git a/include/Pack/RPSystem/RPSysProjectLocal.h b/include/Pack/RPSystem/RPSysProjectLocal.h index f2ad93880..0b77da7d6 100644 --- a/include/Pack/RPSystem/RPSysProjectLocal.h +++ b/include/Pack/RPSystem/RPSysProjectLocal.h @@ -41,6 +41,14 @@ class RPSysProjectLocal { EArea_USA }; + /** + * @brief Target framerate + */ + enum EFrameRate { + EFrameRate_60Hz, //!< NTSC/PAL60 (60Hz) + EFrameRate_50Hz, //!< PAL50 (50Hz) + }; + /** * @brief Storage device */ @@ -105,10 +113,10 @@ class RPSysProjectLocal { } /** - * @brief Tests whether the game is expected to run at 50Hz + * @brief Gets the target framerate */ - bool isPal50() const { - return mIsPal50; + EFrameRate getFrameRate() const { + return mFrameRate; } /** @@ -127,8 +135,8 @@ class RPSysProjectLocal { EArea mLocale; // at 0x10 //! Game language EArea mLanguage; // at 0x14 - //! Whether the display is 50Hz - BOOL mIsPal50; // at 0x18 + //! Target framerate + EFrameRate mFrameRate; // at 0x18 //! Sound archive storage device EStorage mSoundStorage; // at 0x1C }; diff --git a/include/homebuttonMiniLib/HBMTypes.h b/include/homebuttonMiniLib/HBMTypes.h index 8ac2a0cf7..f0366c95e 100644 --- a/include/homebuttonMiniLib/HBMTypes.h +++ b/include/homebuttonMiniLib/HBMTypes.h @@ -78,7 +78,7 @@ typedef struct HBMDataInfo { BOOL backFlag; // at 0x18 int region; // at 0x1C BOOL cursor; // at 0x20 - BOOL messageFlag; // at 0x24 + int messageFlag; // at 0x24 u32 configBufSize; // at 0x28 u32 memSize; // at 0x2C f32 frameDelta; // at 0x30 diff --git a/src/Pack/RPKernel/RPSysHomeMenuMgr.cpp b/src/Pack/RPKernel/RPSysHomeMenuMgr.cpp index 643f6bce8..753e11f37 100644 --- a/src/Pack/RPKernel/RPSysHomeMenuMgr.cpp +++ b/src/Pack/RPKernel/RPSysHomeMenuMgr.cpp @@ -1,296 +1,595 @@ #include +#include #include #include #include +#include + +#include +#include + #include RP_SINGLETON_IMPL_EX(RPSysHomeMenuMgr); +/****************************************************************************** + * + * BanIcon + * + ******************************************************************************/ + +//! X-origin of the ban icon +#define BANICON_X 552.0f +//! Y-origin of the ban icon +#define BANICON_Y 388.0f + +//! Width of the ban icon +#define BANICON_SIZE 28.0f + +/** + * @brief Constructor + */ +RPSysHomeMenuMgr::BanIcon::BanIcon() + : mpTexture(NULL), mState(EState_Hide), mTimer(0), mAlpha(0) {} + +/** + * @brief Updates this icon's state + */ +void RPSysHomeMenuMgr::BanIcon::calc() { + switch (mState) { + case EState_Hide: { + break; + } + + case EState_FadeIn: { + if (++mTimer < FADE_LENGTH) { + mAlpha = mTimer * 255 / FADE_LENGTH; + } else { + mState = EState_Disp; + mTimer = 0; + mAlpha = 255; + } + break; + } + + case EState_Disp: { + if (++mTimer >= DISP_LENGTH) { + mState = EState_FadeOut; + mTimer = 0; + } + + mAlpha = 255; + break; + } + + case EState_FadeOut: { + if (++mTimer < FADE_LENGTH) { + mAlpha = 255 - mTimer * 255 / FADE_LENGTH; + } else { + clear(); + } + break; + } + } +} + +/** + * @brief Renders this icon's state + */ +void RPSysHomeMenuMgr::BanIcon::draw() { + GXColor color; + color.r = color.g = color.b = 255; + color.a = mAlpha; + + RPGrpScreen screen; + screen.SetCanvasMode(RPGrpScreen::CANVAS_CC); + screen.SetNearZ(-10000.0f); + screen.SetFarZ(10000.0f); + screen.SetProjectionType(RPGrpScreen::PROJ_ORTHO); + screen.SetProjectionGX(); + + f32 x = BANICON_X; + f32 y = BANICON_Y; + + f32 current = RPGrpScreen::GetSizeXMax(); + f32 standard = RPGrpScreen::GetSizeYMax(RPGrpScreen::TV_MODE_STD); + + nw4r::ut::Rect rect( // + x * (current / standard) * 0.5f - BANICON_SIZE, // + -y * 0.5f + BANICON_SIZE, // + x * (current / standard), // + y // + ); + + screen.BeginDrawQuadTexture(false); + + screen.DrawQuadTexture( // + rect.left - BANICON_SIZE, // + rect.top + BANICON_SIZE, // + rect.left + BANICON_SIZE, // + rect.top - BANICON_SIZE, // + mpTexture, // + color // + ); +} + +/****************************************************************************** + * + * RPSysHomeMenuMgr + * + ******************************************************************************/ + +/** + * @brief HOME Menu sound archive manager + */ +RPSndHomeMenuArcMgr* RPSysHomeMenuMgr::spHomeMenuArcMgr = NULL; + +/** + * @brief Sound archive heap size + */ +u32 RPSysHomeMenuMgr::sSoundHeapSize = 0x7D000; + +/** + * @brief HBM library sound callback + * + * @param event HBM event + * @param arg Event argument + * @return Whether this callback handled the playback for HBM + */ +BOOL RPSysHomeMenuMgr::soundCallback(int event, int arg) { + switch (event) { + case HBM_SOUND_PLAY: { + spHomeMenuArcMgr->startSe(static_cast(arg)); + return TRUE; + } + + default: { + return FALSE; + } + } +} + +/** + * @brief Constructor + * + * @param pHeap Parent heap + */ +RPSysHomeMenuMgr::RPSysHomeMenuMgr(EGG::Heap* pHeap) : mpParentHeap(pHeap) { + mIsInitialized = false; + mIsDisabled = false; + mIsStarting = false; + + mpBanIcon = new (pHeap) BanIcon(); + init(); + + std::memset(&mHBMDataInfo, 0, sizeof(mHBMDataInfo)); + std::memset(&mHBMControllerData, 0, sizeof(mHBMControllerData)); + + mpProjectLocal = RP_GET_INSTANCE(RPSysProjectLocal); + + mHBMDataInfo.layoutBuf = NULL; + mHBMDataInfo.spkSeBuf = NULL; + mHBMDataInfo.msgBuf = NULL; + mHBMDataInfo.configBuf = NULL; + mHBMDataInfo.mem = new (pHeap) u8[HBM_WORK_SIZE]; + mHBMDataInfo.sound_callback = soundCallback; + mHBMDataInfo.backFlag = FALSE; + mHBMDataInfo.region = SC_LANG_EN; + mHBMDataInfo.cursor = FALSE; + mHBMDataInfo.configBufSize = HBM_CONFIG_SIZE; + mHBMDataInfo.memSize = HBM_WORK_SIZE; + if (mpProjectLocal->getFrameRate() == RPSysProjectLocal::EFrameRate_50Hz) { + mHBMDataInfo.frameDelta = 60.0f / 50.0f; + } else { + mHBMDataInfo.frameDelta = 60.0f / 60.0f; + } + mHBMDataInfo.pAllocator = NULL; + mHBMDataInfo.adjust.x = 1.0f; + mHBMDataInfo.adjust.y = 1.0f; + + std::memset(mHBMDataInfo.mem, 0, HBM_WORK_SIZE); + + spHomeMenuArcMgr = new (pHeap) RPSndHomeMenuArcMgr(); + spHomeMenuArcMgr->createSoundHeap(pHeap, sSoundHeapSize); +} + /** * @brief Destructor */ RPSysHomeMenuMgr::~RPSysHomeMenuMgr() {} /** - * @brief Initializes the class. + * @brief Initializes this manager's state */ void RPSysHomeMenuMgr::init() { - fileAccessor* arcStruct; - - mUNK_0x09 = FALSE; - mIsOpen = FALSE; - mUNK_0x0C = FALSE; - mBlackOutCalled = FALSE; - mButtonState = BUTTON_NONE; - mUNK_0x14 = NULL; + mIsDisabled = false; + mIsActive = false; + mIsVisible = false; + mIsSoftReset = false; + + mMenuState = EMenuState_End; + mStateTimer = 0; + VISetBlack(FALSE); - mUNK_0x09 = FALSE; // @bug Initialized twice - arcStruct = mFileAccessor; - arcStruct->UNK_0x04 = 0; - arcStruct->UNK_0x08 = 0; - arcStruct->UNK_0x0A = 0; + disable(false); + mpBanIcon->clear(); } /** - * @brief Loads the files used in the home menu itself. + * @brief Initializes the HBM library */ -void RPSysHomeMenuMgr::LoadResource() { - HBMDataInfo* menuDataInfo = (HBMDataInfo *)&mMenuDataInfo; - EGG::Archive* staComArc = RP_GET_INSTANCE(RPSysResourceManager) - ->GetStaticCommonArchive(); - EGG::Archive* staLocArc = RP_GET_INSTANCE(RPSysResourceManager) - ->GetStaticLocalArchive(); - mFileAccessor->file = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staComArc, "/HomeMenu/homeBtnIcon.bti"); - - switch (mProjectLocal->getLanguage()) { - case RPSysProjectLocal::EArea_France: { - menuDataInfo->region = SC_LANG_FR; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn_FRA.arc"); - break; - } - case RPSysProjectLocal::EArea_Germany: { - menuDataInfo->region = SC_LANG_DE; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn_GER.arc"); - break; - } - case RPSysProjectLocal::EArea_Italy: { - menuDataInfo->region = SC_LANG_IT; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn_ITA.arc"); - break; - } - case RPSysProjectLocal::EArea_Spain: { - menuDataInfo->region = SC_LANG_SP; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn_SPA.arc"); - break; - } - case RPSysProjectLocal::EArea_Netherlands: { - menuDataInfo->region = SC_LANG_NL; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn_NED.arc"); - break; - } - case RPSysProjectLocal::EArea_Japan: { - menuDataInfo->region = SC_LANG_JP; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn.arc"); - break; - } - default: { - menuDataInfo->region = SC_LANG_EN; - menuDataInfo->layoutBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staLocArc, "/HomeMenu/homeBtn_ENG.arc"); - break; - } +void RPSysHomeMenuMgr::initHomeButtonInfo() { + // TODO(kiwi) Inline? + HBMDataInfo* pHBMDataInfo = &mHBMDataInfo; + + EGG::Archive* pCommonArchive = + RP_GET_INSTANCE(RPSysResourceManager)->GetStaticCommonArchive(); + + EGG::Archive* pLocalArchive = + RP_GET_INSTANCE(RPSysResourceManager)->GetStaticLocalArchive(); + + void* pIconTexture = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pCommonArchive, "/HomeMenu/homeBtnIcon.bti"); + + mpBanIcon->setTexture(static_cast(pIconTexture)); + + switch (mpProjectLocal->getLanguage()) { + case RPSysProjectLocal::EArea_France: { + pHBMDataInfo->region = SC_LANG_FR; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, + "/HomeMenu/homeBtn_FRA.arc"); + break; + } + + case RPSysProjectLocal::EArea_Germany: { + pHBMDataInfo->region = SC_LANG_DE; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, + "/HomeMenu/homeBtn_GER.arc"); + break; + } + + case RPSysProjectLocal::EArea_Italy: { + pHBMDataInfo->region = SC_LANG_IT; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, + "/HomeMenu/homeBtn_ITA.arc"); + break; + } + + case RPSysProjectLocal::EArea_Spain: { + pHBMDataInfo->region = SC_LANG_SP; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, + "/HomeMenu/homeBtn_SPA.arc"); + break; + } + + case RPSysProjectLocal::EArea_Netherlands: { + pHBMDataInfo->region = SC_LANG_NL; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, + "/HomeMenu/homeBtn_NED.arc"); + break; + } + + case RPSysProjectLocal::EArea_Japan: { + pHBMDataInfo->region = SC_LANG_JP; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, "/HomeMenu/homeBtn.arc"); + break; } - menuDataInfo->spkSeBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staComArc, "/HomeMenu/SpeakerSe.arc"); - menuDataInfo->msgBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staComArc, "/HomeMenu/home_nosave.csv"); + default: { + pHBMDataInfo->region = SC_LANG_EN; + + pHBMDataInfo->layoutBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pLocalArchive, + "/HomeMenu/homeBtn_ENG.arc"); + break; + } + } - menuDataInfo->configBuf = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staComArc, "/HomeMenu/config.txt"); + pHBMDataInfo->spkSeBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pCommonArchive, "/HomeMenu/SpeakerSe.arc"); - HBMCreate(menuDataInfo); + pHBMDataInfo->msgBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pCommonArchive, "/HomeMenu/home_nosave.csv"); + + pHBMDataInfo->configBuf = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pCommonArchive, "/HomeMenu/config.txt"); + + HBMCreate(pHBMDataInfo); HBMSetAdjustFlag(TRUE); - void *seFile = RP_GET_INSTANCE(RPSysResourceManager) - ->GetFileFromArchive(staComArc, "/HomeMenu/HomeButtonSe.brsar"); - spHomeMenuArcMgr->setupArchive(seFile); + void* pSoundArchive = + RP_GET_INSTANCE(RPSysResourceManager) + ->GetFileFromArchive(pCommonArchive, + "/HomeMenu/HomeButtonSe.brsar"); + + spHomeMenuArcMgr->setupArchive(pSoundArchive); - if (mProjectLocal->getPack() == RPSysSceneCreator::EPackID_HealthPack) { - HBMSetBlackOutColor(0xFF, 0xFF, 0xFF); + if (mpProjectLocal->getPack() == RPSysSceneCreator::EPackID_HealthPack) { + HBMSetBlackOutColor(255, 255, 255); } - mResLoaded = TRUE; + + mIsInitialized = true; } /** - * @brief Runs every frame when the user is not in the home menu. + * @brief Checks whether the HOME Menu should be opened */ -void RPSysHomeMenuMgr::updateOutside() { - BOOL unk = FALSE; - fileAccessor* arcStruct; +void RPSysHomeMenuMgr::checkMenuStart() { + bool pressedBtn = false; + + for (int index = 0; index < RP_MAX_CONTROLLERS; index++) { + if (RP_GET_CORE_CTRL(index)->getCoreStatus()->getTrigger() & + EGG::cCORE_BUTTON_HOME) { - for (int index = 0; index < 4; index++) { - if ((RP_GET_CORE_CTRL(index)->getCoreStatus()->getTrigger() & EGG::cCORE_BUTTON_HOME)) { - unk = TRUE; + pressedBtn = true; break; } } - - if (unk || mUNK_0x0A) { - if (RP_GET_INSTANCE(RPSysSceneMgr)->getCurrentSceneRP()->isSceneChangeEnable()) { - if (!(mUNK_0x09 || RP_GET_INSTANCE(RPSysDvdStatus)->isErrorOccured())) { - mButtonState = BUTTON_OPEN; - mUNK_0x14 = 0; - mIsOpen = TRUE; - mUNK_0x0C = FALSE; - RP_GET_INSTANCE(RPSndAudioMgr)->enterMenu(); - } else { - arcStruct = mFileAccessor; - arcStruct->UNK_0x04 = 1; - arcStruct->UNK_0x08 = 0; - arcStruct->UNK_0x0A = 0; - } - mUNK_0x0A = FALSE; - } else if (RP_GET_INSTANCE(RPSysDvdStatus)->isErrorOccured()) { - arcStruct = mFileAccessor; - arcStruct->UNK_0x04 = 1; - arcStruct->UNK_0x08 = 0; - arcStruct->UNK_0x0A = 0; + + if (!pressedBtn && !mIsStarting) { + return; + } + + if (RP_GET_INSTANCE(RPSysSceneMgr) + ->getCurrentSceneRP() + ->isSceneChangeEnable()) { + + if (!mIsDisabled && + !RP_GET_INSTANCE(RPSysDvdStatus)->isErrorOccured()) { + + mMenuState = EMenuState_Start; + mStateTimer = 0; + mIsActive = true; + mIsVisible = false; + + RP_GET_INSTANCE(RPSndAudioMgr)->enterMenu(); + } else { - mUNK_0x0A = TRUE; + mpBanIcon->switchOn(); } + + mIsStarting = false; + + } else if (RP_GET_INSTANCE(RPSysDvdStatus)->isErrorOccured()) { + mpBanIcon->switchOn(); + + } else { + mIsStarting = true; } } -void RPSysHomeMenuMgr::clearMenu() { - RPSysCoreController* con; +/** + * @brief Checks whether the HOME Menu should be closed + */ +void RPSysHomeMenuMgr::checkMenuEnd() { + mIsVisible = true; - mUNK_0x0C = TRUE; - switch (HBMCalc(mHbmControllerData)) { - //! Reset (yes, the code checks this case first) - case (HBM_SELECT_BTN2): { - mButtonState = BUTTON_RESET; - RP_GET_INSTANCE(RPSysSceneMgr)->softReset(TRUE); - RP_GET_INSTANCE(RPSndAudioMgr)->stopAllSoundOnPauseOff(); - break; - } - //! Return to Wii Menu - case (HBM_SELECT_BTN1): { - RP_GET_INSTANCE(RPSysSceneMgr)->returnToMenu(TRUE); - mButtonState = BUTTON_NONE; - mIsOpen = FALSE; - mUNK_0x0C = FALSE; - RP_GET_INSTANCE(RPSndAudioMgr)->exitMenu(); - con->popDpdCtrlStackAll(); - con->popKPADParamStackAll(); - if (RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { - return; - } - break; - } - case (HBM_SELECT_BTN3): { - return; + switch (HBMCalc(&mHBMControllerData)) { + case HBM_SELECT_BTN2: { + mMenuState = EMenuState_Reset; + RP_GET_INSTANCE(RPSysSceneMgr)->softReset(true); + RP_GET_INSTANCE(RPSndAudioMgr)->stopAllSoundOnPauseOff(); + break; + } + + case HBM_SELECT_BTN1: { + RP_GET_INSTANCE(RPSysSceneMgr)->returnToMenu(true); + + mMenuState = EMenuState_End; + mIsActive = false; + mIsVisible = false; + + RP_GET_INSTANCE(RPSndAudioMgr)->exitMenu(); + + RPSysCoreController::popDpdCtrlStackAll(); + RPSysCoreController::popKPADParamStackAll(); + + // Avoid firing pauseCallback if it would be untrue + if (!RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { + RP_GET_INSTANCE(RPSysSceneMgr) + ->getCurrentSceneRP() + ->pauseCallBack(false); } - default: { - break; + break; + } + + case HBM_SELECT_HOMEBTN: { + mMenuState = EMenuState_End; + mIsActive = false; + mIsVisible = false; + + RP_GET_INSTANCE(RPSndAudioMgr)->exitMenu(); + + RPSysCoreController::popDpdCtrlStackAll(); + RPSysCoreController::popKPADParamStackAll(); + + // Avoid firing pauseCallback if it would be untrue + if (!RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { + RP_GET_INSTANCE(RPSysSceneMgr) + ->getCurrentSceneRP() + ->pauseCallBack(false); } + break; + } + + case HBM_SELECT_NULL: + default: { + break; + } } - RPSysScene* sceneRP = RP_GET_INSTANCE(RPSysSceneMgr)->getCurrentSceneRP(); - //! RPSysSceneMgr enables overriding pauseCallBack, but RPSysScene leaves it stubbed - sceneRP->pauseCallBack(FALSE); } /** - * @brief Makes the screen fade out. - * - * @return Home menu status. + * @brief Performs a soft reset + * + * @return Whether HBM will perform the reset */ -BOOL RPSysHomeMenuMgr::startBlackOut() { - BOOL openState; - - if (mIsOpen && !mBlackOutCalled) { +bool RPSysHomeMenuMgr::softReset() { + if (mIsActive && !mIsSoftReset) { HBMStartBlackOut(); - mBlackOutCalled = TRUE; + mIsSoftReset = true; } - openState = mIsOpen; - mUNK_0x0A = FALSE; //todo(texline) what does this indicate? - return openState; + + mIsStarting = false; + return mIsActive; } +/** + * @brief Updates this manager's state + */ void RPSysHomeMenuMgr::update() { - s32 conChan; - RPSysCoreController *con; - KPADStatus* kpadStatPtr; - //! test f32 current = RPGrpScreen::GetSizeXMax(); - f32 standard = RPGrpScreen::GetSizeYMax(RPGrpScreen::TV_MODE_STD); - mScaleX = current / standard; - mAdjScaleX = 1.0f; - - if (mIsOpen) { - kpadStatPtr = &mKpadStatus; - conChan = 0; - while (conChan < 4) { - con = RP_GET_INSTANCE(RPSysCoreControllerMgr)->findController(conChan); - if (con && con->isCoreBaseDevice()) { - if (mKpadStatus.wpad_err == WPAD_ERR_COMMUNICATION_ERROR) { - std::memset(kpadStatPtr, 0, sizeof(KPADStatus)); - mKpadStatus.horizon = con->getCoreStatus()->horizon; - } else { - mKpadStatus = *con->getCoreStatus(); + f32 standard = RPGrpScreen::GetSizeXMax(RPGrpScreen::TV_MODE_STD); + + mHBMDataInfo.adjust.x = current / standard; + mHBMDataInfo.adjust.y = 1.0f; + + if (mIsActive) { + for (s32 chan = 0; chan < KPAD_MAX_CONTROLLERS; chan++) { + RPSysCoreController* pController = + RP_GET_INSTANCE(RPSysCoreControllerMgr)->findController(chan); + + if (pController != NULL && pController->isCoreBaseDevice()) { + switch (mKPADStatus[chan].wpad_err) { + case WPAD_ERR_COMMUNICATION_ERROR: { + std::memset(&mKPADStatus[chan], 0, + sizeof(mKPADStatus[chan])); + + mKPADStatus[chan].horizon = + pController->getCoreStatus()->horizon; + break; + } + + default: { + mKPADStatus[chan] = *pController->getCoreStatus(); + break; } - mVec2 = mKpadStatus.pos; + } + + mHBMControllerData.wiiCon[chan].kpad = &mKPADStatus[chan]; + mHBMControllerData.wiiCon[chan].pos = mKPADStatus[chan].pos; + } else { - mHbmControllerData = NULL; - mVec2.x = 10000.0f; - mVec2.y = 10000.0f; + mHBMControllerData.wiiCon[chan].kpad = NULL; + mHBMControllerData.wiiCon[chan].pos.x = 10000.0f; + mHBMControllerData.wiiCon[chan].pos.y = 10000.0f; } - conChan++; - kpadStatPtr++; } } - if (mResLoaded) { - switch (mButtonState) { - /* Commenting out: code right now has severe bug that leads to 0% match - case BUTTON_OPEN: { - mUNK_0x14++; - if (RP_GET_INSTANCE(RPSndSpeakerMgr) - ->isDisconnectAllFinished()) { - mButtonState = BUTTON_CLOSE; - mUNK_0x14 = 0; - HBMInit(); - con->stopMotorAll(); - con->pushDpdCtrlStackAll(TRUE); - } - } - */ - case BUTTON_CLOSE: { - clearMenu(); + + if (mIsInitialized) { + switch (mMenuState) { + case EMenuState_End: { + checkMenuStart(); + break; + } + + case EMenuState_Start: { + mStateTimer++; + + if (!RP_GET_INSTANCE(RPSndSpeakerMgr)->isDisconnectAllFinished()) { + break; } - case BUTTON_RESET: { - mButtonState = BUTTON_NONE; - mIsOpen = FALSE; - mUNK_0x0C = FALSE; - RP_GET_INSTANCE(RPSndAudioMgr)->exitMenu(); - con->popDpdCtrlStackAll(); - con->popKPADParamStackAll(); - if (RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { - RPSysScene* sceneRP = RP_GET_INSTANCE(RPSysSceneMgr) - ->getCurrentSceneRP(); - //! This function is stubbed out in rev 1 - sceneRP->pauseCallBack(FALSE); - } + + mMenuState = EMenuState_Open; + mStateTimer = 0; + + HBMInit(); + + RPSysCoreController::stopMotorAll(); + RPSysCoreController::pushDpdCtrlStackAll(true); + RPSysCoreController::pushKPADParamStackAll(); + + // Avoid firing pauseCallback if it would be untrue + if (!RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { + RP_GET_INSTANCE(RPSysSceneMgr) + ->getCurrentSceneRP() + ->pauseCallBack(true); } - default: { - updateOutside(); + break; + } + + case EMenuState_Open: { + checkMenuEnd(); + break; + } + + case EMenuState_Reset: { + mMenuState = EMenuState_End; + mIsActive = false; + mIsVisible = false; + + RP_GET_INSTANCE(RPSndAudioMgr)->exitMenu(); + + RPSysCoreController::popDpdCtrlStackAll(); + RPSysCoreController::popKPADParamStackAll(); + + // Avoid firing pauseCallback if it would be untrue + if (!RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { + RP_GET_INSTANCE(RPSysSceneMgr) + ->getCurrentSceneRP() + ->pauseCallBack(false); } + break; + } + + default: { + break; } + } + + mpBanIcon->calc(); + spHomeMenuArcMgr->calc(); } - spHomeMenuArcMgr->calc(); } /** - * @brief Starts the drawing process for the home menu. + * @brief Renders the HOME Menu if it is visible */ void RPSysHomeMenuMgr::draw() { - if (mResLoaded && mIsOpen && mUNK_0x0C) { + if (!mIsInitialized) { + return; + } + + if (isActive() && mIsVisible) { HBMDraw(); } } -void RPSysHomeMenuMgr::beginDrawScreen() { - if (mResLoaded) { - if (mFileAccessor->UNK_0x04) { - mFileAccessor->drawScreen(); - } +/** + * @brief Renders the ban icon if it is visible + */ +void RPSysHomeMenuMgr::drawBanIcon() { + if (!mIsInitialized) { + return; + } + + if (mpBanIcon->isDisp()) { + mpBanIcon->draw(); } } diff --git a/src/Pack/RPKernel/RPSysSystem.cpp b/src/Pack/RPKernel/RPSysSystem.cpp index c828c9c5a..88897729a 100644 --- a/src/Pack/RPKernel/RPSysSystem.cpp +++ b/src/Pack/RPKernel/RPSysSystem.cpp @@ -73,10 +73,13 @@ void RPSysSystem::setupLocalSettings() { void RPSysSystem::softResetCallBack() { if (RP_GET_INSTANCE(RPSysDvdStatus)->isErrorOccured()) { RP_GET_INSTANCE(RPSysSceneMgr)->returnToMenu(FALSE); + } else { VIEnableDimming(FALSE); + if (RP_GET_INSTANCE(RPSysSceneMgr)->isNormalState() && - !RP_GET_INSTANCE(RPSysHomeMenuMgr)->startBlackOut()) { + !RP_GET_INSTANCE(RPSysHomeMenuMgr)->softReset()) { + RP_GET_INSTANCE(RPSysSceneMgr)->softReset(FALSE); } } diff --git a/src/Pack/RPSystem/RPSysLoadScene.cpp b/src/Pack/RPSystem/RPSysLoadScene.cpp index 81f1a70ef..09271799f 100644 --- a/src/Pack/RPSystem/RPSysLoadScene.cpp +++ b/src/Pack/RPSystem/RPSysLoadScene.cpp @@ -239,7 +239,7 @@ void RPSysScene::updateNandEndMessage() { } } - if (!RP_GET_INSTANCE(RPSysHomeMenuMgr)->isOpen() && + if (!RP_GET_INSTANCE(RPSysHomeMenuMgr)->isActive() && !RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { RP_GET_INSTANCE(RPSysSaveDataMgr)->update(isSceneDisplay()); diff --git a/src/Pack/RPSystem/RPSysProjectLocal.cpp b/src/Pack/RPSystem/RPSysProjectLocal.cpp index 007aa415f..e6b331a29 100644 --- a/src/Pack/RPSystem/RPSysProjectLocal.cpp +++ b/src/Pack/RPSystem/RPSysProjectLocal.cpp @@ -16,7 +16,7 @@ RPSysProjectLocal::RPSysProjectLocal(EGG::Heap* pHeap) mRegion(ERegion_NTSC_U), mLocale(EArea_USA), mLanguage(EArea_USA), - mIsPal50(false), + mFrameRate(EFrameRate_60Hz), mSoundStorage(EStorage_DVDStream), #endif diff --git a/src/Pack/RPSystem/RPSysScene.cpp b/src/Pack/RPSystem/RPSysScene.cpp index 67cdf6ba9..4199ed1c7 100644 --- a/src/Pack/RPSystem/RPSysScene.cpp +++ b/src/Pack/RPSystem/RPSysScene.cpp @@ -195,7 +195,7 @@ void RPSysScene::calc() { loadUpdate(); if (RP_GET_INSTANCE(RPSysSceneMgr)->isNormalState() && - !RP_GET_INSTANCE(RPSysHomeMenuMgr)->isOpen() && + !RP_GET_INSTANCE(RPSysHomeMenuMgr)->isActive() && !RP_GET_INSTANCE(RPSysPauseMgr)->isPause()) { mpRenderer->PreCalculate();