diff --git a/port/include/config.h b/port/include/config.h index 154745454..d1dc940f5 100644 --- a/port/include/config.h +++ b/port/include/config.h @@ -5,10 +5,41 @@ #define CONFIG_FNAME "pd.ini" #define CONFIG_PATH "$S/" CONFIG_FNAME + +#define CONFIG_MAX_SECNAME 128 +#define CONFIG_MAX_KEYNAME 256 +#define CONFIG_MAX_SETTINGS 256 * 8 + +typedef enum { + CFG_NONE, + CFG_S32, + CFG_F32, + CFG_U32, + CFG_STR, + CFG_U8 +} configtype; + +struct configentry { + char key[CONFIG_MAX_KEYNAME + 1]; + s32 seclen; + configtype type; + void *ptr; + union { + struct { f32 min_f32, max_f32; }; + struct { s32 min_s32, max_s32; }; + struct { u32 min_u32, max_u32; }; + struct { u8 min_u8, max_u8; }; + u32 max_str; + }; +}; + +extern struct configentry settings[CONFIG_MAX_SETTINGS]; + void configInit(void); // loads config from file (path extensions such as ! apply) s32 configLoad(const char *fname); +s32 configLoadKey(const char *fname, char *key); // saves config to file (path extensions such as ! apply) s32 configSave(const char *fname); @@ -19,3 +50,14 @@ void configRegisterInt(const char *key, s32 *var, s32 min, s32 max); void configRegisterUInt(const char* key, u32* var, u32 min, u32 max); void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max); void configRegisterString(const char *key, char *var, u32 maxstr); + +// player save stuff +struct configentry *configFindPlayerEntry(s32 player, const char *key); +struct configentry *configFindOrAddPlayerEntry(s32 player, const char *key); +void configSetPlayerEntry(s32 player, const char *key, const char *val); +s32 getPlayerConfigSlug(s32 playernum, char *out, char* key); +void configRegisterU8Int(const char *key, u8 *var, u32 min, u32 max); + +struct configentry *configFindEntryByPtr(void *ptr); + +s32 getConfigIndexFromDB(u16 deviceserial, s32 fileid); diff --git a/port/src/config.c b/port/src/config.c index 6be6f0d9f..bc7b1c661 100644 --- a/port/src/config.c +++ b/port/src/config.c @@ -7,32 +7,10 @@ #include "config.h" #include "system.h" #include "utils.h" +#include "types.h" +#include "bss.h" -#define CONFIG_MAX_SECNAME 128 -#define CONFIG_MAX_KEYNAME 256 -#define CONFIG_MAX_SETTINGS 256 - -typedef enum { - CFG_NONE, - CFG_S32, - CFG_F32, - CFG_U32, - CFG_STR -} configtype; - -struct configentry { - char key[CONFIG_MAX_KEYNAME + 1]; - s32 seclen; - configtype type; - void *ptr; - union { - struct { f32 min_f32, max_f32; }; - struct { s32 min_s32, max_s32; }; - struct { u32 min_u32, max_u32; }; - u32 max_str; - }; -} settings[CONFIG_MAX_SETTINGS]; - +struct configentry settings[CONFIG_MAX_SETTINGS]; static s32 numSettings = 0; static inline s32 configClampInt(s32 val, s32 min, s32 max) @@ -69,6 +47,7 @@ static inline struct configentry *configAddEntry(const char *key) cfg->seclen = delim ? (delim - cfg->key) : 0; return cfg; } + printf("configAddEntry: too many settings: %s\n", key); return NULL; } @@ -118,6 +97,17 @@ void configRegisterUInt(const char* key, u32* var, u32 min, u32 max) } } +void configRegisterU8Int(const char* key, u8* var, u32 min, u32 max) +{ + struct configentry* cfg = configFindOrAddEntry(key); + if (cfg) { + cfg->type = CFG_U8; + cfg->ptr = var; + cfg->min_u32 = min; + cfg->max_u32 = max; + } +} + void configRegisterFloat(const char *key, f32 *var, f32 min, f32 max) { struct configentry *cfg = configFindOrAddEntry(key); @@ -139,14 +129,14 @@ void configRegisterString(const char *key, char *var, u32 maxstr) } } -static void configSetFromString(const char *key, const char *val) -{ - struct configentry *cfg = configFindEntry(key); - if (!cfg) return; - +void configSet(struct configentry *cfg, const char *val) { s32 tmp_s32; f32 tmp_f32; u32 tmp_u32; + u8 tmp_u8; + if (!cfg->ptr) { + return; + } switch (cfg->type) { case CFG_S32: tmp_s32 = strtol(val, NULL, 0); @@ -169,6 +159,13 @@ static void configSetFromString(const char *key, const char *val) } *(u32*)cfg->ptr = tmp_u32; break; + case CFG_U8: + tmp_u8 = strtoul(val, NULL, 0); + if (cfg->min_u8 < cfg->max_u8) { + tmp_u8 = configClampUInt(tmp_u8, cfg->min_u8, cfg->max_u8); + } + *(u8*)cfg->ptr = tmp_u8; + break; case CFG_STR: strncpy(cfg->ptr, val, cfg->max_str ? cfg->max_str - 1 : 4096); break; @@ -177,8 +174,21 @@ static void configSetFromString(const char *key, const char *val) } } +static inline void configSetFromString(const char *key, const char *val) +{ + struct configentry *cfg = configFindOrAddEntry(key); + if (!cfg) { + return; + } + + configSet(cfg, val); +} + static void configSaveEntry(struct configentry *cfg, FILE *f) { + if (!cfg->ptr) { + return; + } switch (cfg->type) { case CFG_S32: if (cfg->min_s32 < cfg->max_s32) { @@ -198,6 +208,12 @@ static void configSaveEntry(struct configentry *cfg, FILE *f) } fprintf(f, "%s=%u\n", cfg->key + cfg->seclen + 1, *(u32 *)cfg->ptr); break; + case CFG_U8: + if (cfg->min_u8 < cfg->max_u8) { + *(u8*)cfg->ptr = configClampUInt(*(u8*)cfg->ptr, cfg->min_u8, cfg->max_u8); + } + fprintf(f, "%s=%u\n", cfg->key + cfg->seclen + 1, *(u8 *)cfg->ptr); + break; case CFG_STR: fprintf(f, "%s=%s\n", cfg->key + cfg->seclen + 1, (char *)cfg->ptr); break; @@ -206,6 +222,16 @@ static void configSaveEntry(struct configentry *cfg, FILE *f) } } +struct configentry *configFindEntryByPtr(void *ptr) +{ + for (s32 i = 0; i < numSettings; ++i) { + if (settings[i].ptr == ptr) { + return &settings[i]; + } + } + return NULL; +} + s32 configSave(const char *fname) { FILE *f = fsFileOpenWrite(fname); @@ -232,7 +258,23 @@ s32 configSave(const char *fname) return 1; } -s32 configLoad(const char *fname) +static inline s32 configLoadFileIdFromSection(const char *sec, u16 *deviceserial, s32 *fileid) +{ + u32 tmp_deviceserial = 0; + s32 tmp_fileid = 0; + + // Ensure sscanf matches both fields + if (sscanf(sec, "MpPlayer.%x-%x", &tmp_deviceserial, &tmp_fileid) == 2) { + *deviceserial = tmp_deviceserial; + *fileid = tmp_fileid; + return 1; + } + + // If sscanf did not match both fields, return 0 + return 0; +} + +s32 configLoadKey(const char *fname, char *key) { FILE *f = fsFileOpenRead(fname); if (!f) { @@ -259,6 +301,13 @@ s32 configLoad(const char *fname) continue; } strncpy(curSec, token, CONFIG_MAX_SECNAME); + // detect if curSec has a fileguid in it + u16 deviceserial = 0; + s32 fileid = 0; + s32 configindex = -1; + if (!key && configLoadFileIdFromSection(curSec, &deviceserial, &fileid)) { + g_GuidsToProcess[g_NumGuidsToProcess++] = (struct fileguid) { fileid, deviceserial }; + } // eat ] line = strParseToken(line, token, NULL); if (token[0] != ']' || token[1] != '\0') { @@ -278,13 +327,20 @@ s32 configLoad(const char *fname) if (line[0] == '"') { line = strUnquote(line); } - configSetFromString(keyBuf, line); + if (!key || (key && strcmp(keyBuf, key) == 0)) { + configSetFromString(keyBuf, line); + } } } fsFileFree(f); return 1; + +} +s32 configLoad(const char *fname) +{ + return configLoadKey(fname, 0); } void configInit(void) @@ -293,3 +349,26 @@ void configInit(void) configLoad(CONFIG_PATH); } } + +s32 getPlayerConfigSlug(s32 playernum, char *out, char *key) +{ + struct fileguid *guid = &(g_PlayerConfigsArray[playernum].fileguid); + if (guid && key) { + sprintf(out, "MpPlayer.%x-%x.%s\0", guid->deviceserial, guid->fileid, key); + return 1; + } else if (guid) { + sprintf(out, "MpPlayer.%x-%x\0", guid->deviceserial, guid->fileid); + return 1; + } + return 0; +} + +s32 getConfigIndexFromDB(u16 deviceserial, s32 fileid) { + s32 retval = -1; + for (s32 i = 0; i < numSettings; ++i) { + if (strncmp(settings[i].key, "MpPlayer.", 9) != 0) { + continue; + } + } + return retval; +} diff --git a/src/game/challenge.c b/src/game/challenge.c index ca809ca99..b5a39e2c8 100644 --- a/src/game/challenge.c +++ b/src/game/challenge.c @@ -244,7 +244,7 @@ void challengePerformSanityChecks(void) // Reset player handicaps for (i = 0; i < MAX_PLAYERS; i++) { if (g_MpSetup.chrslots & (1 << i)) { - g_PlayerConfigsArray[i].handicap = 0x80; + *g_PlayerConfigsArray[i].handicap = 0x80; numplayers++; } } diff --git a/src/game/chraction.c b/src/game/chraction.c index 1ea0b8b72..988f5e1cc 100644 --- a/src/game/chraction.c +++ b/src/game/chraction.c @@ -4549,9 +4549,9 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse if (g_Vars.normmplayerisrunning) { #if VERSION >= VERSION_PAL_FINAL // Fixing a @bug? - damage = damage * mpHandicapToDamageScale(g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].handicap); + damage = damage * mpHandicapToDamageScale(*g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].handicap); #else - damage /= mpHandicapToDamageScale(g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].handicap); + damage /= mpHandicapToDamageScale(*g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].handicap); #endif } @@ -4756,7 +4756,7 @@ void chrDamage(struct chrdata *chr, f32 damage, struct coord *vector, struct gse setCurrentPlayerNum(playermgrGetPlayerNumByProp(vprop)); if (g_Vars.normmplayerisrunning) { - damage /= mpHandicapToDamageScale(g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].handicap); + damage /= mpHandicapToDamageScale(*g_PlayerConfigsArray[g_Vars.currentplayerstats->mpindex].handicap); } if (g_Vars.currentplayer->isdead == false && !g_PlayerInvincible) { diff --git a/src/game/filemgr.c b/src/game/filemgr.c index e82d7af15..d95bf7c42 100644 --- a/src/game/filemgr.c +++ b/src/game/filemgr.c @@ -871,10 +871,12 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess) filemgrHandleSuccess(); } + // Success dialog: Cool! if (showfilesaved && errnum == 0) { menuPushDialog(&g_FilemgrFileSavedMenuDialog); } } else { + // file load if (errnum == 0) { filemgrHandleSuccess(); } diff --git a/src/game/lv.c b/src/game/lv.c index 22f3993a8..da904a89f 100644 --- a/src/game/lv.c +++ b/src/game/lv.c @@ -2443,6 +2443,8 @@ void lvStop(void) #if VERSION >= VERSION_NTSC_1_0 menuStop(); #endif + updateGuids(); + mpExtendedProfileRegisterBlank(); } void lvCheckPauseStateChanged(void) diff --git a/src/game/menutick.c b/src/game/menutick.c index 5a795da9d..ad0521c29 100644 --- a/src/game/menutick.c +++ b/src/game/menutick.c @@ -360,7 +360,7 @@ void menuTick(void) } if (canjoin && (buttons & START_BUTTON)) { - g_PlayerConfigsArray[i].handicap = 128; + // g_PlayerConfigsArray[i].handicap = 128; if (g_Vars.mpsetupmenu == MPSETUPMENU_GENERAL) { // Joining from a general area such as the Combat diff --git a/src/game/mplayer/mplayer.c b/src/game/mplayer/mplayer.c index 4d72e22a7..10f8f75e5 100644 --- a/src/game/mplayer/mplayer.c +++ b/src/game/mplayer/mplayer.c @@ -28,6 +28,8 @@ #include "lib/lib_317f0.h" #include "data.h" #include "types.h" +#include "config.h" +#include "input.h" // bss struct chrdata *g_MpAllChrPtrs[MAX_MPCHRS]; @@ -44,6 +46,8 @@ u32 var800acc1c; struct mplockinfo g_MpLockInfo; struct modeldef *var800acc28[18]; +s32 g_NumProfiles = 0; + // Forward declaractions struct mpweaponset g_MpWeaponSets[12]; s32 g_MpWeaponSetNum; @@ -132,13 +136,174 @@ struct mpweapon g_MpWeapons[NUM_MPWEAPONS] = { .crosshairhealth = CROSSHAIR_HEALTH_OFF, \ } -struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { +struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS] = { PLAYER_EXT_CFG_DEFAULT, PLAYER_EXT_CFG_DEFAULT, PLAYER_EXT_CFG_DEFAULT, PLAYER_EXT_CFG_DEFAULT, }; + +#define PLAYER_EXT_PROFILE_DEFAULT { \ + .fileguid = 0, \ + .handicap = 0x80, \ +}; + +struct extplayerprofile g_ExtendedProfiles[CONFIG_MAX_PROFILES]; + +struct extprofileproperty { + configtype type; + char *name; + union{ + struct { + u8 initialvalue_u8; + s8 min_u8; + s8 max_u8; + }; + struct { + s32 min_s32; + s32 initialvalue_s32; + s32 max_s32; + }; + struct { + u32 max_u32; + u32 min_u32; + u32 initialvalue_u32; + }; + struct { + f32 max_f32; + f32 min_f32; + f32 initialvalue_f32; + }; + struct { + char initialvalue_str[128]; + u32 max_str; + }; + }; + void (*initfunc)(s32, s32); +}; + +static void mpExtendedProfileInitHandicap(s32 profileindex, s32 playernum) +{ + g_PlayerConfigsArray[playernum].handicap = &g_ExtendedProfiles[profileindex].handicap; +} + +struct extprofileproperty g_ExtendedProfileProperties[] = { + { CFG_U8, "Handicap", 0x80, 0, 255, &mpExtendedProfileInitHandicap}, +}; // these must be in the same order as the extendedprofile struct, ignoring the fileguid + +static inline s32 getExtendedProfileIndexFromFileGuid(const struct fileguid* fileguid) +{ + s32 i; + + for (i = 0; i < g_NumProfiles; i++) { + if (g_ExtendedProfiles[i].fileguid.fileid == fileguid->fileid &&\ + g_ExtendedProfiles[i].fileguid.deviceserial == fileguid->deviceserial) { + return i; + } + } + + return -1; +} + +static inline s32 mpExtendedProfileAdd(struct fileguid *fileguid) +{ + s32 index = getExtendedProfileIndexFromFileGuid(fileguid); + + if (index < 0) { + index = g_NumProfiles; + + if (g_NumProfiles < CONFIG_MAX_PROFILES) { + g_NumProfiles++; + } + + g_ExtendedProfiles[index] = (struct extplayerprofile)PLAYER_EXT_PROFILE_DEFAULT; + g_ExtendedProfiles[index].fileguid.deviceserial = fileguid->deviceserial; + g_ExtendedProfiles[index].fileguid.fileid = fileguid->fileid; + } + + return index; +} + +static inline s32 mpPlayerGetIndexFromFileGuid(struct fileguid *fileguid) +{ + s32 i; + + for (i = 0; i < MAX_PLAYERS; i++) { + if (g_PlayerConfigsArray[i].fileguid.fileid == fileguid->fileid &&\ + g_PlayerConfigsArray[i].fileguid.deviceserial == fileguid->deviceserial) { + return i; + } + } + + return -1; +} + +static inline s32 mpExtendedProfileRegister(struct fileguid *fileguid, s32 arg0) +{ + s32 i; + + char *playerslug = 0; + char playerbuf[128]; + + if (arg0 & 1) { + sprintf(playerbuf, "MpPlayer.%x-%x", fileguid->deviceserial, fileguid->fileid); + playerslug = playerbuf; + } + + s32 configindex = mpExtendedProfileAdd(fileguid); + + s32 playernum = mpPlayerGetIndexFromFileGuid(fileguid); + + for (i = 0; i < ARRAYCOUNT(g_ExtendedProfileProperties); i++) { + char key[128]; + sprintf(key, "%s.%s", playerslug, g_ExtendedProfileProperties[i].name); + + switch (g_ExtendedProfileProperties[i].type) { + case CFG_U8: + if (playerslug) { + g_ExtendedProfiles[configindex].ptr[i+1] = (extplayerprop)g_ExtendedProfileProperties[i].initialvalue_u8; + configRegisterU8Int(key, (u8*)&g_ExtendedProfiles[configindex].ptr[i+1].u8, g_ExtendedProfileProperties[i].min_u8, g_ExtendedProfileProperties[i].max_u8); + } + if (g_ExtendedProfileProperties[i].initfunc) g_ExtendedProfileProperties[i].initfunc(configindex, playernum); + break; + case CFG_S32: + if (playerslug) { + g_ExtendedProfiles[configindex].ptr[i+1] = (extplayerprop)g_ExtendedProfileProperties[i].initialvalue_s32; + configRegisterInt(key, (s32*)&g_ExtendedProfiles[configindex].ptr[i+1].s32, g_ExtendedProfileProperties[i].min_s32, g_ExtendedProfileProperties[i].max_s32); + } + if (g_ExtendedProfileProperties[i].initfunc) g_ExtendedProfileProperties[i].initfunc(configindex, playernum); + break; + case CFG_U32: + if (playerslug) { + g_ExtendedProfiles[configindex].ptr[i+1] = (extplayerprop)g_ExtendedProfileProperties[i].initialvalue_u32; + configRegisterUInt(key, (u32*)&g_ExtendedProfiles[configindex].ptr[i+1].u32, g_ExtendedProfileProperties[i].min_u32, g_ExtendedProfileProperties[i].max_u32); + } + if (g_ExtendedProfileProperties[i].initfunc) g_ExtendedProfileProperties[i].initfunc(configindex, playernum); + break; + case CFG_F32: + if (playerslug) { + g_ExtendedProfiles[configindex].ptr[i+1] = (extplayerprop)g_ExtendedProfileProperties[i].initialvalue_f32; + configRegisterFloat(key, (f32*)&g_ExtendedProfiles[configindex].ptr[i+1].f32, g_ExtendedProfileProperties[i].min_f32, g_ExtendedProfileProperties[i].max_f32); + } + if (g_ExtendedProfileProperties[i].initfunc) g_ExtendedProfileProperties[i].initfunc(configindex, playernum); + break; + case CFG_STR: + if (playerslug) { + g_ExtendedProfiles[configindex].ptr[i+1] = (extplayerprop)g_ExtendedProfileProperties[i].initialvalue_str; + configRegisterString(key, (char*)g_ExtendedProfiles[configindex].ptr[i+1].string, sizeof(g_ExtendedProfiles[configindex].ptr[i])); + } + if (g_ExtendedProfileProperties[i].initfunc) g_ExtendedProfileProperties[i].initfunc(configindex, playernum); + break; + } + if (playerslug) configLoadKey(CONFIG_PATH, key); + } + + return configindex; +} + + + #endif /** @@ -223,6 +388,8 @@ void mpStartMatch(void) g_Vars.perfectbuddynum = 1; } + + void mpReset(void) { s32 i; @@ -416,6 +583,30 @@ void func0f187fec(void) g_MpSetup.teamscorelimit = 19; } +static inline void processGuids() +{ + for (s32 i = 0; i < g_NumGuidsToProcess; i++) { + printf("Processing guid %x\n", g_GuidsToProcess[i].fileid); + mpExtendedProfileRegister(&g_GuidsToProcess[i], 1); + } + g_NumGuidsToProcess = 0; +} + +void mpExtendedProfileRegisterBlank(void) +{ + struct fileguid fileguid = {0, 0}; + mpExtendedProfileRegister(&fileguid, 1); +} +void updateNewGuids(s32 arg0) +{ + processGuids(); +} + +void updateGuids(void) +{ + processGuids(); +} + void mpPlayerSetDefaults(s32 playernum, bool autonames) { s32 i; @@ -446,7 +637,7 @@ void mpPlayerSetDefaults(s32 playernum, bool autonames) | OPTION_ALWAYSSHOWTARGET | OPTION_SHOWZOOMRANGE; - g_PlayerConfigsArray[playernum].handicap = 128; + updateNewGuids(autonames); switch (playernum) { case 0: @@ -3616,6 +3807,29 @@ void mpplayerfileGetOverview(char *arg0, char *name, u32 *playtime) *playtime = savebufferReadBits(&buffer, 28); } +// save: this should be called immediately after updating the file guid / device serial +// load: this should be called immediately after loading the wad +static inline void updateExtendedMpProfileOnFileOperation(s32 playernum) +{ + s32 configindex = getExtendedProfileIndexFromFileGuid(&g_PlayerConfigsArray[playernum].fileguid); + + if (configindex > 0) { + // old config is still saved to its own index, if any + // we just need to calculate the index of the config in the global array + // for the player we just loaded + g_PlayerConfigsArray[playernum].configindex = configindex; + configindex = mpExtendedProfileRegister(&g_PlayerConfigsArray[playernum].fileguid, 0); + g_PlayerConfigsArray[playernum].configindex = configindex; + + } else { + // register new entry + // need table with cfgtype, slugname, defaultvalue for every extended profile property + // so the appriate init function can be called and config file setup + configindex = mpExtendedProfileRegister(&g_PlayerConfigsArray[playernum].fileguid, 1); + g_PlayerConfigsArray[playernum].configindex = configindex; + } +} + s32 mpplayerfileSave(s32 playernum, s32 device, s32 fileid, u16 deviceserial) { s32 ret; @@ -3634,6 +3848,7 @@ s32 mpplayerfileSave(s32 playernum, s32 device, s32 fileid, u16 deviceserial) if (ret == 0) { g_PlayerConfigsArray[playernum].fileguid.fileid = newfileid; g_PlayerConfigsArray[playernum].fileguid.deviceserial = deviceserial; + updateExtendedMpProfileOnFileOperation(playernum); return 0; } @@ -3649,6 +3864,10 @@ s32 mpplayerfileLoad(s32 playernum, s32 device, s32 fileid, u16 deviceserial) s32 ret; struct savebuffer buffer; + // iterate through g_GuidsToProcess and check if the fileid is already loaded + // the counter is g_NumGuidsToProcess + processGuids(); + if (device >= 0) { savebufferClear(&buffer); @@ -3661,7 +3880,8 @@ s32 mpplayerfileLoad(s32 playernum, s32 device, s32 fileid, u16 deviceserial) mpplayerfileLoadWad(playernum, &buffer, 1); func0f0d54c4(&buffer); - g_PlayerConfigsArray[playernum].handicap = 0x80; + updateExtendedMpProfileOnFileOperation(playernum); + return 0; } diff --git a/src/game/mplayer/setup.c b/src/game/mplayer/setup.c index 380c1b283..d7ab04cba 100644 --- a/src/game/mplayer/setup.c +++ b/src/game/mplayer/setup.c @@ -2341,13 +2341,13 @@ MenuItemHandlerResult menuhandlerMpHandicapPlayer(s32 operation, struct menuitem } break; case MENUOP_GETSLIDER: - data->slider.value = g_PlayerConfigsArray[item->param].handicap; + data->slider.value = *g_PlayerConfigsArray[item->param].handicap; break; case MENUOP_SET: - g_PlayerConfigsArray[item->param].handicap = (u16)data->slider.value; + *g_PlayerConfigsArray[item->param].handicap = (u16)data->slider.value; break; case MENUOP_GETSLIDERLABEL: - sprintf(data->slider.label, "%s%s%.00f%%\n", "", "", mpHandicapToDamageScale(g_PlayerConfigsArray[item->param].handicap) * 100); + sprintf(data->slider.label, "%s%s%.00f%%\n", "", "", mpHandicapToDamageScale(*g_PlayerConfigsArray[item->param].handicap) * 100); break; } @@ -2369,7 +2369,7 @@ MenuItemHandlerResult menuhandlerMpRestoreHandicapDefaults(s32 operation, struct s32 i; for (i = 0; i < MAX_PLAYERS; i++) { - g_PlayerConfigsArray[i].handicap = 0x80; + if (g_PlayerConfigsArray[i].handicap) *g_PlayerConfigsArray[i].handicap = 0x80; } } diff --git a/src/include/bss.h b/src/include/bss.h index 5382431b1..52e2bf34a 100644 --- a/src/include/bss.h +++ b/src/include/bss.h @@ -295,6 +295,8 @@ extern s32 g_JpnMaxCacheItems; extern s32 var8009d370jf; #ifndef PLATFORM_N64 extern bool g_ValidGbcRomFound; +extern struct fileguid g_GuidsToProcess[CONFIG_MAX_PROFILES]; +extern u32 g_NumGuidsToProcess; #endif #endif diff --git a/src/include/constants.h b/src/include/constants.h index 777fbed56..206b6208c 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -1696,7 +1696,7 @@ #ifndef PLATFORM_N64 #define MENUITEMTYPE_COLORBOX 0x1b -#endif +#endif #define MENUMODELFLAG_HASSCALE 0x01 #define MENUMODELFLAG_HASPOSITION 0x02 @@ -4753,6 +4753,9 @@ enum weaponnum { #define EXTRA_SLEEP_TIME 1000LL // 100us +// if controller pak-like support was added and everyone had 4 profiles, this is twice the max +#define CONFIG_MAX_PROFILES ((MAX_PLAYERS * 4) * 2) + #endif #endif diff --git a/src/include/data.h b/src/include/data.h index 24c106292..090d3ab3f 100644 --- a/src/include/data.h +++ b/src/include/data.h @@ -532,6 +532,8 @@ extern struct menudialogdef g_HangarListMenuDialog; #ifndef PLATFORM_N64 extern struct extplayerconfig g_PlayerExtCfg[MAX_PLAYERS]; +extern struct extplayerprofile g_PlayerProfiles[CONFIG_MAX_PROFILES]; +extern s32 g_NumProfiles; extern struct weathercfg g_WeatherConfig[WEATHERCFG_MAX_STAGES]; extern const struct weathercfg g_DefaultWeatherConfig; diff --git a/src/include/game/mplayer/mplayer.h b/src/include/game/mplayer/mplayer.h index b2ab42f95..f877ee3ed 100644 --- a/src/include/game/mplayer/mplayer.h +++ b/src/include/game/mplayer/mplayer.h @@ -122,5 +122,8 @@ s32 mpsetupfileSave(s32 device, s32 filenum, u16 deviceserial); s32 mpsetupfileLoad(s32 device, s32 filenum, u16 deviceserial); void func0f18e558(void); struct modeldef *func0f18e57c(s32 index, s32 *headnum); +void updateNewGuids(s32 arg0); +void updateGuids(void); +void mpExtendedProfileRegisterBlank(void); #endif diff --git a/src/include/types.h b/src/include/types.h index 79f553fc9..b06be1f45 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -4,6 +4,7 @@ #include #include "n_libaudio.h" #include "constants.h" +#include "config.h" #include "lang.h" #include "pads.h" #include "tiles.h" @@ -4049,7 +4050,8 @@ struct mpplayerconfig { /*0x95*/ u8 title; /*0x96*/ u8 newtitle; /*0x97*/ u8 gunfuncs[6]; - /*0x9d*/ u8 handicap; + /*0x9d*/ u8* handicap; + s32 configindex; }; struct mpbotconfig { @@ -6154,6 +6156,26 @@ struct extplayerconfig { s32 crosshairhealth; }; +typedef union { + struct fileguid fileguid; + u8 u8; + s32 s32; + f32 f32; + u32 u32; + char *string; +} extplayerprop; + +struct extplayerprofile { + union { + struct { + struct fileguid fileguid; + u8 handicap; + }; + extplayerprop ptr[2]; + }; +}; + + #endif #endif diff --git a/src/lib/varsinit.c b/src/lib/varsinit.c index c64418044..f225d53bb 100644 --- a/src/lib/varsinit.c +++ b/src/lib/varsinit.c @@ -10,6 +10,9 @@ u32 var8009e6b0[4]; struct g_vars g_Vars; +struct fileguid g_GuidsToProcess[CONFIG_MAX_PROFILES] = {}; +u32 g_NumGuidsToProcess = 0; + void varsInit(void) { g_Vars.diffframe60f = 1;