@@ -12,6 +12,7 @@ MYMODDECL();
1212extern uintptr_t pGameLib;
1313extern void * pGameHandle;
1414void Redirect (uintptr_t addr, uintptr_t to);
15+ int None (...){return 0 ;}
1516
1617/* Callbacks */
1718std::vector<SimpleFn> gCreateWidgetFns ;
@@ -22,9 +23,10 @@ std::vector<OnPlayerProcessFn> gPlayerUpdatePostFns;
2223std::vector<AdditionalSetting*> gMoreSettings ;
2324std::vector<AdditionalTexDB*> gMoreTexDBs ;
2425std::vector<const char *> gMoreIMGs ;
26+ std::vector<AdditionalSettingsButton*> gMoreSettingButtons ;
2527int nNextSettingNum = MODS_SETTINGS_STARTING_FROM - 1 ;
2628int nCurrentSliderId = 0 ;
27- eTypeOfSettings nCurrentItemTab = Mods ;
29+ eTypeOfSettings nCurrentItemTab = SetType_Mods ;
2830bool 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 ;}
196197char szSautilsVer[32 ];
198+ SettingsScreen* curScr = NULL ;
197199MobileMenu* 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
319354uintptr_t DrawSlider_backto;
320355extern " C" void NewScreen_Controls_inject (void * self)
321356{
322- nCurrentItemTab = Controller ;
357+ nCurrentItemTab = SetType_Controller ;
323358 AddSettingsToScreen (self);
324359 AddRestoreDefaultsItem (self);
325360}
326361extern " C" void NewScreen_Game_inject (void * self)
327362{
328- nCurrentItemTab = Game ;
363+ nCurrentItemTab = SetType_Game ;
329364 AddSettingsToScreen (self);
330365 AddRestoreDefaultsItem (self);
331366}
332367extern " C" void NewScreen_Display_inject (void * self)
333368{
334- nCurrentItemTab = Display ;
369+ nCurrentItemTab = SetType_Display ;
335370 AddSettingsToScreen (self);
336371 AddRestoreDefaultsItem (self);
337372}
338373extern " 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
374409DECL_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
627662void 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+
675718unsigned int SAUtils::GetCurrentMs ()
676719{
677720 return *m_snTimeInMilliseconds;
0 commit comments