mirror of
https://github.com/CraftyBoss/SuperMarioOdysseyOnline.git
synced 2024-11-21 18:55:16 +00:00
fix: crashes related to Keyboard in FreezeTagConfigMenu
In some kingdoms (e.g. in Sand, but not in Cascade) it always/sometimes crashed the game when closing the keyboard. I assume that's because the Keyboard was on the SceneHeap which it shouldn't. At least moving it to the game mode heap fixed it. But then there was a memory leak that the game mode heap growed everytime the scene was reloaded. That was because of some never freed memory in the Keyboard class. I tried to implement destructors for `StageSceneStateServerConfig` and `FreezeTagConfigMenu` but that also crashed. So I added new `clean()` methods instead.
This commit is contained in:
parent
7fa8c659e1
commit
be50d034f8
8 changed files with 42 additions and 17 deletions
|
@ -9,6 +9,7 @@ typedef void (*KeyboardSetup)(nn::swkbd::KeyboardConfig&);
|
||||||
class Keyboard {
|
class Keyboard {
|
||||||
public:
|
public:
|
||||||
Keyboard(ulong strSize);
|
Keyboard(ulong strSize);
|
||||||
|
~Keyboard();
|
||||||
void keyboardThread();
|
void keyboardThread();
|
||||||
|
|
||||||
void openKeyboard(const char* initialText, KeyboardSetup setup);
|
void openKeyboard(const char* initialText, KeyboardSetup setup);
|
||||||
|
|
|
@ -41,6 +41,7 @@ class StageSceneStateServerConfig : public al::HostStateBase<al::Scene>, public
|
||||||
virtual void appear(void) override;
|
virtual void appear(void) override;
|
||||||
virtual void kill(void) override;
|
virtual void kill(void) override;
|
||||||
|
|
||||||
|
void clean();
|
||||||
void exeMainMenu();
|
void exeMainMenu();
|
||||||
void exeOpenKeyboardIP();
|
void exeOpenKeyboardIP();
|
||||||
void exeOpenKeyboardPort();
|
void exeOpenKeyboardPort();
|
||||||
|
|
|
@ -9,6 +9,8 @@ class FreezeTagConfigMenu : public GameModeConfigMenu {
|
||||||
public:
|
public:
|
||||||
FreezeTagConfigMenu();
|
FreezeTagConfigMenu();
|
||||||
|
|
||||||
|
void clean() override;
|
||||||
|
|
||||||
const sead::WFixedSafeString<0x200>* getStringData() override;
|
const sead::WFixedSafeString<0x200>* getStringData() override;
|
||||||
GameModeConfigMenu::UpdateAction updateMenu(int selectIndex) override;
|
GameModeConfigMenu::UpdateAction updateMenu(int selectIndex) override;
|
||||||
|
|
||||||
|
@ -17,6 +19,5 @@ class FreezeTagConfigMenu : public GameModeConfigMenu {
|
||||||
private:
|
private:
|
||||||
static constexpr int mItemCount = 8;
|
static constexpr int mItemCount = 8;
|
||||||
sead::SafeArray<sead::WFixedSafeString<0x200>, mItemCount>* mItems = nullptr;
|
sead::SafeArray<sead::WFixedSafeString<0x200>, mItemCount>* mItems = nullptr;
|
||||||
Keyboard* mScoreKeyboard;
|
Keyboard* mKeyboard;
|
||||||
Keyboard* mRoundKeyboard;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,8 @@ public:
|
||||||
|
|
||||||
GameModeConfigMenu() = default;
|
GameModeConfigMenu() = default;
|
||||||
|
|
||||||
|
virtual void clean() {}
|
||||||
|
|
||||||
virtual UpdateAction updateMenu(int selectIndex) { return UpdateAction::NOOP; }
|
virtual UpdateAction updateMenu(int selectIndex) { return UpdateAction::NOOP; }
|
||||||
|
|
||||||
virtual const sead::WFixedSafeString<0x200>* getStringData() { return nullptr; }
|
virtual const sead::WFixedSafeString<0x200>* getStringData() { return nullptr; }
|
||||||
|
|
|
@ -20,7 +20,13 @@ Keyboard::Keyboard(ulong strSize) : mResultString(strSize) {
|
||||||
|
|
||||||
mCustomizeDicSize = 0x400;
|
mCustomizeDicSize = 0x400;
|
||||||
mCustomizeDicBuf = (char*)malloc(mCustomizeDicSize);
|
mCustomizeDicBuf = (char*)malloc(mCustomizeDicSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Keyboard::~Keyboard() {
|
||||||
|
delete mThread;
|
||||||
|
free(mWorkBuf);
|
||||||
|
free(mTextCheckBuf);
|
||||||
|
free(mCustomizeDicBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Keyboard::keyboardThread() {
|
void Keyboard::keyboardThread() {
|
||||||
|
@ -48,7 +54,6 @@ void Keyboard::keyboardThread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Keyboard::openKeyboard(const char* initialText, KeyboardSetup setupFunc) {
|
void Keyboard::openKeyboard(const char* initialText, KeyboardSetup setupFunc) {
|
||||||
|
|
||||||
mInitialText = initialText;
|
mInitialText = initialText;
|
||||||
mSetupFunc = setupFunc;
|
mSetupFunc = setupFunc;
|
||||||
|
|
||||||
|
|
|
@ -119,6 +119,7 @@ void initStateHook(
|
||||||
) {
|
) {
|
||||||
thisPtr->mStateOption = new StageSceneStateOption(stateName, host, initInfo, footer, data, unkBool);
|
thisPtr->mStateOption = new StageSceneStateOption(stateName, host, initInfo, footer, data, unkBool);
|
||||||
|
|
||||||
|
if (sceneStateServerConfig) { sceneStateServerConfig->clean(); }
|
||||||
sceneStateServerConfig = new StageSceneStateServerConfig("ServerConfig", host, initInfo, footer, data, unkBool);
|
sceneStateServerConfig = new StageSceneStateServerConfig("ServerConfig", host, initInfo, footer, data, unkBool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include "server/freeze-tag/FreezeTagConfigMenu.hpp"
|
#include "server/freeze-tag/FreezeTagConfigMenu.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "sead/basis/seadNew.h"
|
||||||
|
#include "sead/heap/seadHeap.h"
|
||||||
|
#include "server/gamemode/GameModeManager.hpp"
|
||||||
#include "nn/util.h"
|
#include "nn/util.h"
|
||||||
|
|
||||||
FreezeTagConfigMenu::FreezeTagConfigMenu() : GameModeConfigMenu() {
|
FreezeTagConfigMenu::FreezeTagConfigMenu() : GameModeConfigMenu() {
|
||||||
|
@ -14,13 +18,12 @@ FreezeTagConfigMenu::FreezeTagConfigMenu() : GameModeConfigMenu() {
|
||||||
mItems->mBuffer[6].copy(u"Cappy Collision (ON) ");
|
mItems->mBuffer[6].copy(u"Cappy Collision (ON) ");
|
||||||
mItems->mBuffer[7].copy(u"Cappy Bounce (OFF) ");
|
mItems->mBuffer[7].copy(u"Cappy Bounce (OFF) ");
|
||||||
|
|
||||||
mScoreKeyboard = new Keyboard(6);
|
sead::Heap* heap = GameModeManager::instance()->getHeap();
|
||||||
mScoreKeyboard->setHeaderText(u"Set your Freeze Tag score");
|
mKeyboard = new (heap) Keyboard(6);
|
||||||
mScoreKeyboard->setSubText(u"");
|
}
|
||||||
|
|
||||||
mRoundKeyboard = new Keyboard(3);
|
void FreezeTagConfigMenu::clean() {
|
||||||
mRoundKeyboard->setHeaderText(u"Set length of rounds you start in minutes");
|
delete mKeyboard;
|
||||||
mRoundKeyboard->setSubText(u"This will be automatically sent to other players (2-60 minutes)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const sead::WFixedSafeString<0x200>* FreezeTagConfigMenu::getStringData() {
|
const sead::WFixedSafeString<0x200>* FreezeTagConfigMenu::getStringData() {
|
||||||
|
@ -92,7 +95,9 @@ GameModeConfigMenu::UpdateAction FreezeTagConfigMenu::updateMenu(int selectIndex
|
||||||
char buf[5];
|
char buf[5];
|
||||||
nn::util::SNPrintf(buf, 5, "%u", oldScore);
|
nn::util::SNPrintf(buf, 5, "%u", oldScore);
|
||||||
|
|
||||||
mScoreKeyboard->openKeyboard(
|
mKeyboard->setHeaderText(u"Set your Freeze Tag score");
|
||||||
|
mKeyboard->setSubText(u"");
|
||||||
|
mKeyboard->openKeyboard(
|
||||||
buf,
|
buf,
|
||||||
[](nn::swkbd::KeyboardConfig& config) {
|
[](nn::swkbd::KeyboardConfig& config) {
|
||||||
config.keyboardMode = nn::swkbd::KeyboardMode::ModeNumeric;
|
config.keyboardMode = nn::swkbd::KeyboardMode::ModeNumeric;
|
||||||
|
@ -103,12 +108,12 @@ GameModeConfigMenu::UpdateAction FreezeTagConfigMenu::updateMenu(int selectIndex
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
while (!mScoreKeyboard->isThreadDone()) {
|
while (!mKeyboard->isThreadDone()) {
|
||||||
nn::os::YieldThread(); // allow other threads to run
|
nn::os::YieldThread(); // allow other threads to run
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mScoreKeyboard->isKeyboardCancelled()) {
|
if (!mKeyboard->isKeyboardCancelled()) {
|
||||||
newScore = ::atoi(mScoreKeyboard->getResult());
|
newScore = std::atoi(mKeyboard->getResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newScore != uint16_t(-1)) {
|
if (newScore != uint16_t(-1)) {
|
||||||
|
@ -128,7 +133,9 @@ GameModeConfigMenu::UpdateAction FreezeTagConfigMenu::updateMenu(int selectIndex
|
||||||
char buf[3];
|
char buf[3];
|
||||||
nn::util::SNPrintf(buf, 3, "%u", oldTime);
|
nn::util::SNPrintf(buf, 3, "%u", oldTime);
|
||||||
|
|
||||||
mRoundKeyboard->openKeyboard(
|
mKeyboard->setHeaderText(u"Set length of rounds you start in minutes");
|
||||||
|
mKeyboard->setSubText(u"This will be automatically sent to other players (2-60 minutes)");
|
||||||
|
mKeyboard->openKeyboard(
|
||||||
buf,
|
buf,
|
||||||
[](nn::swkbd::KeyboardConfig& config) {
|
[](nn::swkbd::KeyboardConfig& config) {
|
||||||
config.keyboardMode = nn::swkbd::KeyboardMode::ModeNumeric;
|
config.keyboardMode = nn::swkbd::KeyboardMode::ModeNumeric;
|
||||||
|
@ -139,17 +146,18 @@ GameModeConfigMenu::UpdateAction FreezeTagConfigMenu::updateMenu(int selectIndex
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
while (!mRoundKeyboard->isThreadDone()) {
|
while (!mKeyboard->isThreadDone()) {
|
||||||
nn::os::YieldThread(); // allow other threads to run
|
nn::os::YieldThread(); // allow other threads to run
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mRoundKeyboard->isKeyboardCancelled()) {
|
if (!mKeyboard->isKeyboardCancelled()) {
|
||||||
newTime = ::atoi(mRoundKeyboard->getResult());
|
newTime = std::atoi(mKeyboard->getResult());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newTime != uint8_t(-1)) {
|
if (newTime != uint8_t(-1)) {
|
||||||
FreezeTagInfo::mRoundLength = al::clamp(newTime, u8(2), u8(60));
|
FreezeTagInfo::mRoundLength = al::clamp(newTime, u8(2), u8(60));
|
||||||
}
|
}
|
||||||
|
|
||||||
return UpdateAction::NOOP;
|
return UpdateAction::NOOP;
|
||||||
}
|
}
|
||||||
case 4: {
|
case 4: {
|
||||||
|
|
|
@ -139,6 +139,12 @@ al::MessageSystem* StageSceneStateServerConfig::getMessageSystem(void) const {
|
||||||
return mMsgSystem;
|
return mMsgSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void StageSceneStateServerConfig::clean() {
|
||||||
|
for (int mode = 0; mode < GameModeFactory::getModeCount() - 1; mode++) {
|
||||||
|
mGamemodeConfigMenus[mode].mMenu->clean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StageSceneStateServerConfig::exeMainMenu() {
|
void StageSceneStateServerConfig::exeMainMenu() {
|
||||||
if (al::isFirstStep(this)) {
|
if (al::isFirstStep(this)) {
|
||||||
activateInput();
|
activateInput();
|
||||||
|
|
Loading…
Reference in a new issue