sm64ex-coop/data/dynos_opt_vanilla.cpp

160 lines
5.5 KiB
C++

#include "dynos.cpp.h"
static DynosOption *sPrevOpt = NULL;
static DynosOption *sOptionsMenu = NULL;
//
// Vanilla actions
//
typedef void (*VanillaActionFunction)(struct Option *, s32);
typedef struct VanillaAction {
String mFuncName;
VanillaActionFunction mAction;
} VanillaAction;
STATIC_STORAGE(Array<VanillaAction *>, VanillaActions);
#define sVanillaActions __VanillaActions()
static VanillaActionFunction DynOS_Opt_GetVanillaAction(const String& aFuncName) {
for (auto &_DynosAction : sVanillaActions) {
if (_DynosAction->mFuncName == aFuncName) {
return _DynosAction->mAction;
}
}
return NULL;
}
static void DynOS_Opt_AddVanillaAction(const String& aFuncName, void (*aFuncPtr)(struct Option *, s32)) {
for (auto &_DynosAction : sVanillaActions) {
if (_DynosAction->mFuncName == aFuncName) {
return;
}
}
VanillaAction *_DynosAction = New<VanillaAction>();
_DynosAction->mFuncName = aFuncName;
_DynosAction->mAction = aFuncPtr;
sVanillaActions.Add(_DynosAction);
}
static bool DynOS_Opt_CallVanillaAction(const char *aOptName) {
VanillaActionFunction _Func = DynOS_Opt_GetVanillaAction(aOptName);
if (_Func) {
_Func(NULL, 0);
return true;
}
return false;
}
//
// Convert classic options menu into DynOS menu
//
static DynosOption *DynOS_Opt_ConvertOption(const u8 *aLabel, const u8 *aTitle) {
static u32 sOptIdx = 0;
DynosOption *_Opt = New<DynosOption>();
_Opt->mName = String("vanilla_opt_%08X", sOptIdx++);
_Opt->mConfigName = "";
_Opt->mLabel = { "", aLabel };
_Opt->mTitle = { "", aTitle };
_Opt->mDynos = false;
if (sPrevOpt == NULL) { // The very first option
_Opt->mPrev = NULL;
_Opt->mNext = NULL;
_Opt->mParent = NULL;
sOptionsMenu = _Opt;
} else {
if (sPrevOpt->mType == DOPT_SUBMENU && sPrevOpt->mSubMenu.mEmpty) { // First option of a sub-menu
_Opt->mPrev = NULL;
_Opt->mNext = NULL;
_Opt->mParent = sPrevOpt;
sPrevOpt->mSubMenu.mChild = _Opt;
sPrevOpt->mSubMenu.mEmpty = false;
} else {
_Opt->mPrev = sPrevOpt;
_Opt->mNext = NULL;
_Opt->mParent = sPrevOpt->mParent;
sPrevOpt->mNext = _Opt;
}
}
sPrevOpt = _Opt;
return _Opt;
}
static void DynOS_Opt_EndSubMenu() {
if (sPrevOpt) {
if (sPrevOpt->mType == DOPT_SUBMENU && sPrevOpt->mSubMenu.mEmpty) { // ENDMENU command following a SUBMENU command
sPrevOpt->mSubMenu.mEmpty = false;
} else {
sPrevOpt = sPrevOpt->mParent;
}
}
}
static void DynOS_Opt_ConvertSubMenu(const u8 *aLabel, const u8 *aTitle) {
DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aTitle);
_Opt->mType = DOPT_SUBMENU;
_Opt->mSubMenu.mChild = NULL;
_Opt->mSubMenu.mEmpty = true;
}
static void DynOS_Opt_ConvertToggle(const u8 *aLabel, bool *pValue) {
DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel);
_Opt->mType = DOPT_TOGGLE;
_Opt->mToggle.mTog = (bool *) pValue;
}
static void DynOS_Opt_ConvertScroll(const u8 *aLabel, s32 aMin, s32 aMax, s32 aStep, u32 *pValue) {
DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel);
_Opt->mType = DOPT_SCROLL;
_Opt->mScroll.mMin = aMin;
_Opt->mScroll.mMax = aMax;
_Opt->mScroll.mStep = aStep;
_Opt->mScroll.mValue = (s32 *) pValue;
}
static void DynOS_Opt_ConvertChoice(const u8 *aLabel, const u8 **aChoices, s32 aCount, u32 *pValue) {
DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel);
_Opt->mType = DOPT_CHOICE;
_Opt->mChoice.mIndex = (s32 *) pValue;
for (s32 i = 0; i != aCount; ++i) {
_Opt->mChoice.mChoices.Add({ "", aChoices[i] });
}
}
static void DynOS_Opt_ConvertButton(const u8 *aLabel, VanillaActionFunction aAction) {
DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel);
_Opt->mType = DOPT_BUTTON;
_Opt->mButton.mFuncName = "DynOS_Opt_CallVanillaAction";
DynOS_Opt_AddVanillaAction(_Opt->mName, aAction);
}
static void DynOS_Opt_ConvertBind(const u8 *aLabel, u32 *pBinds) {
DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel);
_Opt->mType = DOPT_BIND;
_Opt->mBind.mMask = 0;
_Opt->mBind.mBinds = pBinds;
_Opt->mBind.mIndex = 0;
}
#ifndef COOP
extern "C" {
extern void dynos_opt_convert_vanilla_main_menu();
void dynos_opt_end_submenu() { return DynOS_Opt_EndSubMenu(); }
void dynos_opt_convert_submenu(const u8 *label, const u8 *title) { return DynOS_Opt_ConvertSubMenu(label, title); }
void dynos_opt_convert_toggle(const u8 *label, bool *bval) { return DynOS_Opt_ConvertToggle(label, bval); }
void dynos_opt_convert_scroll(const u8 *label, s32 min, s32 max, s32 step, u32 *uval) { return DynOS_Opt_ConvertScroll(label, min, max, step, uval); }
void dynos_opt_convert_choice(const u8 *label, const u8 **choices, s32 numChoices, u32 *uval) { return DynOS_Opt_ConvertChoice(label, choices, numChoices, uval); }
void dynos_opt_convert_button(const u8 *label, void *action) { return DynOS_Opt_ConvertButton(label, (VanillaActionFunction) action); }
void dynos_opt_convert_bind(const u8 *label, u32 *uval) { return DynOS_Opt_ConvertBind(label, uval); }
}
#endif
void DynOS_Opt_InitVanilla(DynosOption *&aOptionsMenu) {
sPrevOpt = NULL;
#ifndef COOP
dynos_opt_convert_vanilla_main_menu();
#endif
DynOS_Opt_AddAction("DynOS_Opt_CallVanillaAction", DynOS_Opt_CallVanillaAction, true);
aOptionsMenu = sOptionsMenu;
}