Skip to content

Commit f2be270

Browse files
1.3.0
1 parent 1666d47 commit f2be270

2 files changed

Lines changed: 101 additions & 50 deletions

File tree

isautils.h

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,21 +57,21 @@ class CWidgetButton;
5757

5858
enum eTypeOfSettings : unsigned char
5959
{
60-
Controller = 0,
61-
Game = 1,
62-
Display = 2,
63-
Audio = 3,
64-
Language = 4,
65-
Mods = 5,
60+
SetType_Controller = 0,
61+
SetType_Game = 1,
62+
SetType_Display = 2,
63+
SetType_Audio = 3,
64+
SetType_Language = 4,
65+
SetType_Mods = 5,
6666

6767
SETTINGS_COUNT
6868
};
6969

7070
enum eTypeOfItem : unsigned char
7171
{
72-
WithItems = 0,
73-
Slider = 1,
74-
Button = 2,
72+
ItemType_WithItems = 0,
73+
ItemType_Slider = 1,
74+
ItemType_Button = 2,
7575

7676
ITEMTYPES_COUNT
7777
};
@@ -178,6 +178,14 @@ class ISAUtils
178178

179179
/* Functions below added in 1.3.0.0 */
180180

181+
/** Creates a custom tabs in settings (like "Mods Settings")
182+
*
183+
* \param name A name of settings tab
184+
* \param textureName A name of the texture from mobile.txt texdb (def: "menu_mainsettings")
185+
* \return An id to use with: AddButton or AddSliderItem or AddClickableItem
186+
*/
187+
virtual eTypeOfSettings AddSettingsTab(const char* name, const char* textureName = "menu_mainsettings") = 0;
188+
181189
/** Get current game time in milliseconds
182190
*
183191
* \return Current milliseconds
@@ -283,7 +291,7 @@ class ISAUtils
283291
/** Enable or disable widget
284292
*
285293
* \param widget A pointer of the widget
286-
* \param enable Enable? (default: true)
294+
* \param enable Enable? (def: true)
287295
*/
288296
virtual void ToggleWidget(CWidgetButton* widget, bool enable = true) = 0;
289297

sautils.cpp

Lines changed: 83 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ MYMODDECL();
1212
extern uintptr_t pGameLib;
1313
extern void* pGameHandle;
1414
void Redirect(uintptr_t addr, uintptr_t to);
15+
int None(...){return 0;}
1516

1617
/* Callbacks */
1718
std::vector<SimpleFn> gCreateWidgetFns;
@@ -22,9 +23,10 @@ std::vector<OnPlayerProcessFn> gPlayerUpdatePostFns;
2223
std::vector<AdditionalSetting*> gMoreSettings;
2324
std::vector<AdditionalTexDB*> gMoreTexDBs;
2425
std::vector<const char*> gMoreIMGs;
26+
std::vector<AdditionalSettingsButton*> gMoreSettingButtons;
2527
int nNextSettingNum = MODS_SETTINGS_STARTING_FROM - 1;
2628
int nCurrentSliderId = 0;
27-
eTypeOfSettings nCurrentItemTab = Mods;
29+
eTypeOfSettings nCurrentItemTab = SetType_Mods;
2830
bool g_bIsGameStartedAlready = false;
2931

3032
/* Patched vars */
@@ -89,12 +91,12 @@ void AddSettingsToScreen(void* screen)
8991
AdditionalSetting* setting = gMoreSettings[i];
9092
if(setting->eType == nCurrentItemTab)
9193
{
92-
if(setting->byteItemType == Button)
94+
if(setting->byteItemType == ItemType_Button)
9395
{
9496
ButtonSettingItem* mob_rtd = new ButtonSettingItem;
9597
mob_rtd->vtable = pGameLib + 0x66281C;
9698
mob_rtd->itemText = setting->szName;
97-
mob_rtd->actionFn = (uintptr_t)(setting->fnOnButtonPressed);
99+
mob_rtd->actionFn = setting->fnOnButtonPressed == NULL ? (uintptr_t)None : (uintptr_t)setting->fnOnButtonPressed;
98100
mob_rtd->flag = 0;
99101
AddSettingsItemFn(screen, (uintptr_t)mob_rtd);
100102
}
@@ -157,7 +159,7 @@ void SettingsScreenClosed()
157159
for(int i = 0; i < size; ++i)
158160
{
159161
AdditionalSetting* setting = gMoreSettings[i];
160-
if(setting->byteItemType != Button && setting->eType == nCurrentItemTab)
162+
if(setting->byteItemType != ItemType_Button && setting->eType == nCurrentItemTab)
161163
{
162164
int nNewVal = sautils->ValueOfSettingsItem(setting->nSettingId);
163165
if(nNewVal != setting->nSavedVal)
@@ -192,17 +194,16 @@ DECL_HOOK(unsigned short*, GxtTextGet, void* self, const char* txt)
192194
}
193195
return ret;
194196
}
195-
int None(...){return 0;}
196197
char szSautilsVer[32];
198+
SettingsScreen* curScr = NULL;
197199
MobileMenu* OnModSettingsOpened()
198200
{
199-
nCurrentItemTab = Mods;
201+
nCurrentItemTab = SetType_Mods;
200202
snprintf(szSautilsVer, sizeof(szSautilsVer), "SAUtils v%s", modinfo->VersionString());
201203
char* menuScreenPointer = new char[0x44];
202-
InitializeMenuPtr((uintptr_t)menuScreenPointer, "Mod Settings", true);
204+
InitializeMenuPtr((uintptr_t)menuScreenPointer, "Mods Settings", true);
203205
*(uintptr_t*)menuScreenPointer = pGameLib + 0x6628D0; // Vtable
204206

205-
206207
ButtonSettingItem* sautilsVer = new ButtonSettingItem;
207208
sautilsVer->vtable = pGameLib + 0x66281C;
208209
sautilsVer->itemText = szSautilsVer;
@@ -219,7 +220,6 @@ MobileMenu* OnModSettingsOpened()
219220
sautilsLine->flag = 0;
220221
AddSettingsItemFn((void*)menuScreenPointer, (uintptr_t)sautilsLine); // Empty line
221222

222-
223223
*(bool*)(menuScreenPointer + 48) = true; // Ready to be shown! Or... the other thingy?
224224
if(gMobileMenu->m_nScreensCount)
225225
{
@@ -229,41 +229,76 @@ MobileMenu* OnModSettingsOpened()
229229
gMobileMenu->m_pTopScreen = (MenuScreen*)menuScreenPointer;
230230
return gMobileMenu;
231231
}
232-
DECL_HOOK(uintptr_t, SettingsScreen, uintptr_t self)
232+
MobileMenu* OnCustomModSettingsOpened()
233233
{
234-
SettingsScreen(self);
234+
nCurrentItemTab = (eTypeOfSettings)curScr->m_nChosenButton;
235+
char* menuScreenPointer = new char[0x44];
236+
InitializeMenuPtr((uintptr_t)menuScreenPointer, gMoreSettingButtons[curScr->m_nChosenButton - 6]->szName, true);
237+
*(uintptr_t*)menuScreenPointer = pGameLib + 0x6628D0; // Vtable
235238

236-
// New "Mods" tab should be there!
237-
RwTexture* tex = GetTextureFromDB("menu_mainsettings");
239+
AddSettingsToScreen((void*)menuScreenPointer); // Custom items
240+
241+
ButtonSettingItem* sautilsLine = new ButtonSettingItem;
242+
sautilsLine->vtable = pGameLib + 0x66281C;
243+
sautilsLine->itemText = "";
244+
sautilsLine->actionFn = (uintptr_t)None;
245+
sautilsLine->flag = 0;
246+
AddSettingsItemFn((void*)menuScreenPointer, (uintptr_t)sautilsLine); // Empty line
247+
248+
*(bool*)(menuScreenPointer + 48) = true; // Ready to be shown! Or... the other thingy?
249+
if(gMobileMenu->m_nScreensCount)
250+
{
251+
(*(void(**)(char*, int))(*(int*)menuScreenPointer + 20))(menuScreenPointer, *(int*)(gMobileMenu->m_pScreens[gMobileMenu->m_nScreensCount - 1]));
252+
}
253+
if(gMobileMenu->m_pTopScreen != NULL) ProcessMenuPending(gMobileMenu);
254+
gMobileMenu->m_pTopScreen = (MenuScreen*)menuScreenPointer;
255+
return gMobileMenu;
256+
}
257+
void AddSettingsButton(SettingsScreen* self, const char* name, const char* textureName, FSButtonCallback callback)
258+
{
259+
RwTexture* tex = GetTextureFromDB(textureName);
238260
++tex->refCount;
239-
int& tabsCount = *(int*)(self + 64);
240-
uintptr_t container; // Maybe a storage for those tabs
241-
if(*(int*)(self + 60) >= tabsCount + 1) // If we have a place for tabs
261+
int& tabsCount = self->m_nButtonsCount;
262+
FlowScreenButton* container;
263+
if(self->m_nAllocatedCount >= tabsCount + 1) // If we have a place for tabs
242264
{
243-
container = *(uintptr_t*)(self + 68);
265+
container = self->m_pButtonsContainer;
244266
}
245267
else // If we dont have a place for tabs, reallocate more
246268
{
247269
int reallocCount = 4 * (tabsCount + 1) / 3u + 3;
248-
void* newContainer = malloc(12 * reallocCount);
249-
void* oldContainer = *(void **)(self + 68);
250-
container = (uintptr_t)newContainer;
270+
FlowScreenButton* newContainer = new FlowScreenButton[reallocCount];
271+
FlowScreenButton* oldContainer = self->m_pButtonsContainer;
272+
container = newContainer;
251273
if (oldContainer)
252274
{
253-
memcpy(newContainer, *(const void **)(self + 68), 12 * tabsCount);
275+
memcpy(newContainer, self->m_pButtonsContainer, sizeof(FlowScreenButton) * tabsCount);
254276
free(oldContainer);
255-
tabsCount = *(int*)(self + 64);
277+
tabsCount = self->m_nButtonsCount;
256278
}
257-
*(int*)(self + 60) = reallocCount;
258-
*(int*)(self + 68) = (int)container;
279+
self->m_nAllocatedCount = reallocCount;
280+
self->m_pButtonsContainer = container;
259281
}
260-
container = container + 12 * tabsCount;
261-
*(RwTexture**)(container + 0) = tex;
262-
*(const char**)(container + 4) = "Mods settings";
263-
*(uintptr_t*)(container + 8) = (uintptr_t)OnModSettingsOpened;
282+
FlowScreenButton* btn = &container[tabsCount];
283+
btn->m_pTexture = tex;
284+
btn->m_szName = name;
285+
btn->m_pOnPressed = callback;
264286
++tabsCount;
287+
}
288+
DECL_HOOK(SettingsScreen*, SettingsScreen_Construct, SettingsScreen* self)
289+
{
290+
curScr = self;
291+
SettingsScreen_Construct(self);
292+
293+
// New "Mods" tab should be there!
294+
AddSettingsButton(self, "Mods settings", "menu_mainsettings", OnModSettingsOpened);
265295
// New "Mods" tab should be there!
266296

297+
// Custom tabs!
298+
int size = gMoreSettingButtons.size();
299+
for(int i = 0; i < size; ++i) AddSettingsButton(self, gMoreSettingButtons[i]->szName, gMoreSettingButtons[i]->szTextureName, OnCustomModSettingsOpened);
300+
// Custom tabs!
301+
267302
return self;
268303
}
269304

@@ -319,25 +354,25 @@ uintptr_t NewScreen_Controls_backto, NewScreen_Game_backto, NewScreen_Display_ba
319354
uintptr_t DrawSlider_backto;
320355
extern "C" void NewScreen_Controls_inject(void* self)
321356
{
322-
nCurrentItemTab = Controller;
357+
nCurrentItemTab = SetType_Controller;
323358
AddSettingsToScreen(self);
324359
AddRestoreDefaultsItem(self);
325360
}
326361
extern "C" void NewScreen_Game_inject(void* self)
327362
{
328-
nCurrentItemTab = Game;
363+
nCurrentItemTab = SetType_Game;
329364
AddSettingsToScreen(self);
330365
AddRestoreDefaultsItem(self);
331366
}
332367
extern "C" void NewScreen_Display_inject(void* self)
333368
{
334-
nCurrentItemTab = Display;
369+
nCurrentItemTab = SetType_Display;
335370
AddSettingsToScreen(self);
336371
AddRestoreDefaultsItem(self);
337372
}
338373
extern "C" void NewScreen_Audio_inject(void* self)
339374
{
340-
nCurrentItemTab = Audio;
375+
nCurrentItemTab = SetType_Audio;
341376
AddSettingsToScreen(self);
342377
AddRestoreDefaultsItem(self, true);
343378
}
@@ -373,7 +408,7 @@ __attribute__((optnone)) __attribute__((naked)) void NewScreen_Audio_stub(void)
373408

374409
DECL_HOOK(void*, NewScreen_Language, void* self)
375410
{
376-
nCurrentItemTab = Language;
411+
nCurrentItemTab = SetType_Language;
377412
NewScreen_Language(self);
378413
AddSettingsToScreen(self);
379414
return self;
@@ -451,7 +486,7 @@ void SAUtils::InitializeSAUtils()
451486
HOOKPLT(SelectScreenOnDestroy, pGameLib + 0x673FD8);
452487
HOOKPLT(SettingSelectionRender, pGameLib + 0x662850);
453488
HOOKPLT(GxtTextGet, pGameLib + 0x66E78C);
454-
HOOKPLT(SettingsScreen, pGameLib + 0x674018);
489+
HOOKPLT(SettingsScreen_Construct, pGameLib + 0x674018);
455490
HOOKPLT(InitialiseRenderWare, pGameLib + 0x66F2D0);
456491
HOOKPLT(InitialiseGame_SecondPass, pGameLib + 0x672178);
457492
HOOKPLT(PlayerProcess, pGameLib + 0x673E84);
@@ -547,7 +582,7 @@ int SAUtils::AddSettingsItem(eTypeOfSettings typeOf, const char* name, int initV
547582
pNew->eType = typeOf;
548583
pNew->szName = name;
549584
pNew->fnOnValueChange = fnOnValueChange;
550-
pNew->byteItemType = isSlider ? Slider : WithItems;
585+
pNew->byteItemType = isSlider ? ItemType_Slider : ItemType_WithItems;
551586
pNew->nInitVal = (int)initVal;
552587
pNew->nSavedVal = (int)initVal;
553588
pNew->nMaxVal = maxVal;
@@ -582,7 +617,7 @@ int SAUtils::AddClickableItem(eTypeOfSettings typeOf, const char* name, int init
582617
pNew->fnOnValueChange = fnOnValueChange;
583618
pNew->fnOnValueDraw = NULL;
584619
pNew->fnOnButtonPressed = NULL;
585-
pNew->byteItemType = WithItems;
620+
pNew->byteItemType = ItemType_WithItems;
586621
pNew->nInitVal = (int)initVal;
587622
pNew->nSavedVal = (int)initVal;
588623
pNew->nMaxVal = maxVal;
@@ -608,7 +643,7 @@ int SAUtils::AddSliderItem(eTypeOfSettings typeOf, const char* name, int initVal
608643
pNew->fnOnValueChange = fnOnValueChange;
609644
pNew->fnOnValueDraw = fnOnValueDraw;
610645
pNew->fnOnButtonPressed = NULL;
611-
pNew->byteItemType = Slider;
646+
pNew->byteItemType = ItemType_Slider;
612647
pNew->nInitVal = (int)initVal;
613648
pNew->nSavedVal = (int)initVal;
614649
pNew->nMaxVal = maxVal;
@@ -626,16 +661,14 @@ int SAUtils::AddSliderItem(eTypeOfSettings typeOf, const char* name, int initVal
626661
// 1.2
627662
void SAUtils::AddButton(eTypeOfSettings typeOf, const char* name, OnButtonPressedFn fnOnButtonPressed)
628663
{
629-
if(fnOnButtonPressed == NULL) return;
630-
631664
AdditionalSetting* pNew = new AdditionalSetting;
632665
pNew->nSettingId = -1;
633666
pNew->eType = typeOf;
634667
pNew->szName = name;
635668
pNew->fnOnValueChange = NULL;
636669
pNew->fnOnValueDraw = NULL;
637670
pNew->fnOnButtonPressed = fnOnButtonPressed;
638-
pNew->byteItemType = Button;
671+
pNew->byteItemType = ItemType_Button;
639672
pNew->nInitVal = 0;
640673
pNew->nSavedVal = 0;
641674
pNew->nMaxVal = 0;
@@ -672,6 +705,16 @@ void SAUtils::AddIMG(const char* imgName)
672705
if(g_bIsGameStartedAlready) AddImageToList(imgName, false);
673706
}
674707

708+
eTypeOfSettings SAUtils::AddSettingsTab(const char* name, const char* textureName)
709+
{
710+
static unsigned char tabId = SETTINGS_COUNT-1;
711+
AdditionalSettingsButton* pNew = new AdditionalSettingsButton;
712+
pNew->szName = name;
713+
pNew->szTextureName = textureName;
714+
gMoreSettingButtons.push_back(pNew);
715+
return (eTypeOfSettings)++tabId;
716+
}
717+
675718
unsigned int SAUtils::GetCurrentMs()
676719
{
677720
return *m_snTimeInMilliseconds;

0 commit comments

Comments
 (0)