mpsetupfile: scrapped groups, manage settings: rename/delete

This commit is contained in:
Raf committed 2025-03-25 01:05:57 +08:00
1 parent f5d851f7c2
commit ad9ed9ff3b
5 files changed
+257 -220

No files matched your search

+2 -2
View File
@@ -4,7 +4,7 @@
#include "types.h"
s32 mpsetupLoadFile();
void mpsetupLoadSetup(s32 index);
s32 mpsetupSaveFile(const char *name, u8 overwrite);
void mpsetupLoadSetup(s32 slotindex);
s32 mpsetupSaveSetup(s32 slotindex);
#endif
+238 -176
View File
@@ -1,11 +1,13 @@
#include "types.h"
#include "constants.h"
#include "bss.h"
#include "game/menu.h"
#include "game/savebuffer.h"
#include "game/mplayer/mplayer.h"
#include <string.h>
#include "fs.h"
#include "system.h"
#include "mpsetups.h"
/*
MP Setup File Format
@@ -13,28 +15,19 @@ MP Setup File Format
[version{1}]
[defaultsetup{1}]
[numsetups{1}]
[numgroups{1}]
# setups
[setup_1{64}]
...
[setup_n{64}]
# groups
[offset_index_1{1}]
[name_1{1-32}]
...
[offset_index_n{1}]
[name_n{1-32}]
*/
extern struct menudialogdef g_MpSaveSetupNameMenuDialog;
struct menudialogdef g_MpGroupNameMenuDialog;
#define MPSETUP_FILE "mpsetups.bin"
u8 filebuffer[sizeof(struct mpsetupfile)];
struct mpsetupfile g_MpSetupFile;
s16 g_MpCurrentSetup = -1;
s16 g_MpCurrentGroup = -1;
#define BUF_READ(dst, buf, type) { dst = *(type*)((buf)); buf += sizeof(type); }
#define BUF_WRITE(src, buf, type) { *((type*)(buf)) = src; buf += sizeof(type); }
@@ -42,62 +35,139 @@ s16 g_MpCurrentGroup = -1;
memcpy(buf, src, size); \
buf += size; }
// #### Group List
MenuItemHandlerResult mpSelectGroupHandler(s32 operation, struct menuitem *item, union handlerdata *data);
// #### Rename setup dialogue
MenuItemHandlerResult menuhandlerRenameSetup(s32 operation, struct menuitem *item, union handlerdata *data)
{
char *name = data->keyboard.string;
s32 slotindex = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
struct setupblock *setup = &g_MpSetupFile.setups[slotindex];
s32 err;
struct menuitem g_MpSetupGroupsDialogItems[] = {
switch (operation) {
case MENUOP_GETTEXT:
// strcpy(name, g_MpSetup.name);
strcpy(name, setup->bytes);
break;
case MENUOP_SETTEXT:
strcpy(g_MpSetup.name, name);
break;
case MENUOP_SET:
strcpy(setup->bytes, name);
err = mpsetupSaveSetup(slotindex);
if (!err) {
menuPopDialog();
}
else {
// TODO
// menuPushDialog(&g_FilemgrFileSavedMenuDialog);
}
break;
}
return 0;
}
struct menuitem g_RenameSetupItems[] = {
#if VERSION != VERSION_JPN_FINAL
{
MENUITEMTYPE_LIST,
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
0x00000078,
0x00000042,
mpSelectGroupHandler,
MENUITEMFLAG_LESSLEFTPADDING,
L_MPMENU_189, // "Enter a name for your game setup file:"
0,
NULL,
},
#endif
{
MENUITEMTYPE_KEYBOARD,
0,
0,
0,
0,
menuhandlerRenameSetup,
},
{ MENUITEMTYPE_END },
};
struct menudialogdef g_MpSetupGroupsDialog = {
struct menudialogdef g_RenameSetupDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t) "Groups",
g_MpSetupGroupsDialogItems,
(uintptr_t)"Setup Name:\n",
g_RenameSetupItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_CLOSEONSELECT,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
MenuItemHandlerResult mpSelectGroupHandler(s32 operation, struct menuitem *item, union handlerdata *data)
// #### Delete setup dialog
static s32 deleteSetup();
MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETCOLOUR: {
u8 disabled = data->list.value == g_MpSetupFile.numgroups && g_MpSetupFile.numsetups == 0;
u32 colour = data->list.unk04;
data->list.unk04 = disabled ? 0xff333300 | (colour & 0xff) : colour;
}
case MENUOP_GETOPTIONCOUNT:
data->list.value = g_MpSetupFile.numgroups + 1;
break;
case MENUOP_GETOPTIONTEXT:
if (data->list.value == g_MpSetupFile.numgroups) {
return (uintptr_t) "[New Group]\n";
}
return (uintptr_t) g_MpSetupFile.groups[data->list.value].name;
case MENUOP_SET:
{
u8 newgroupdisabled = data->list.value == g_MpSetupFile.numgroups && g_MpSetupFile.numsetups == 0;
if (newgroupdisabled) {
return 0;
}
menuPopDialog();
if (data->list.value == g_MpSetupFile.numgroups) {
menuPushDialog(&g_MpGroupNameMenuDialog);
if (operation == MENUOP_SET) {
s32 err = deleteSetup();
if (!err) {
menuPopDialog();
menuPopDialog();
}
else {
g_MpCurrentGroup = data->list.value;
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
// TODO
}
}
return 0;
}
struct menuitem g_DeleteSetupItems[] = {
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
(uintptr_t)"Delete Setup?\n",
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_385, // "No"
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CENTRE,
L_OPTIONS_386, // "Yes"
0,
menuhandlerDeleteSetup,
},
{ MENUITEMTYPE_END },
};
struct menudialogdef g_DeleteSetupDialog = {
MENUDIALOGTYPE_DANGER,
(uintptr_t)"Delete Setup\n",
g_DeleteSetupItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
// #### Manage settings dialog
struct menudialogdef g_ManageSetupDialog;
MenuItemHandlerResult mpSelectSettingHandler(s32 operation, struct menuitem *item, union handlerdata *data)
{
switch (operation) {
case MENUOP_GETOPTIONCOUNT:
data->list.value = g_MpSetupFile.numsetups;
break;
case MENUOP_GETOPTIONTEXT:
return (uintptr_t) g_MpSetupFile.setups[data->list.value].bytes;
case MENUOP_SET:
{
g_Menus[g_MpPlayerNum].mpsetup.slotindex = data->list.value;
menuPushDialog(&g_ManageSetupDialog);
}
case MENUOP_GETSELECTEDINDEX:
data->list.value = 0xfffff;
break;
@@ -106,68 +176,93 @@ MenuItemHandlerResult mpSelectGroupHandler(s32 operation, struct menuitem *item,
return 0;
}
static void createGroup(char *name)
{
g_MpCurrentGroup = g_MpSetupFile.numgroups++;
struct setupgroup *group = &g_MpSetupFile.groups[g_MpCurrentGroup];
strcpy(group->name, name);
group->offset_index = g_MpSetupFile.numsetups;
}
struct menuitem g_MpManageSettingsListItems[] = {
{
MENUITEMTYPE_LIST,
0,
0,
0x00000078,
0x00000042,
mpSelectSettingHandler,
},
{ MENUITEMTYPE_END },
// #### Group name dialog
MenuItemHandlerResult menuhandlerMpSetupGroupName(s32 operation, struct menuitem *item, union handlerdata *data)
{
char *name = data->keyboard.string;
struct setupgroup *group = &g_MpSetupFile.groups[g_MpSetupFile.numgroups];
};
switch (operation) {
case MENUOP_GETTEXT:
strcpy(name, group->name);
break;
case MENUOP_SETTEXT:
strcpy(group->name, name);
break;
case MENUOP_SET:
createGroup(name);
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
break;
struct menudialogdef g_MpManageSettingsDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t) "Manage Settings\n",
g_MpManageSettingsListItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
struct menudialogdef g_RenameSetupDialog;
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
menuPushDialog(&g_RenameSetupDialog);
}
return 0;
}
struct menuitem g_MpGroupNameMenuItems[] = {
#if VERSION != VERSION_JPN_FINAL
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t) "Enter the group name:\n",
0,
NULL,
},
#endif
{
MENUITEMTYPE_KEYBOARD,
0,
0,
0,
0,
menuhandlerMpSetupGroupName,
},
{ MENUITEMTYPE_END },
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data)
{
if (operation == MENUOP_SET) {
menuPushDialog(&g_DeleteSetupDialog);
}
return 0;
}
struct menuitem g_ManageSetupItems[] = {
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Rename\n",
0,
menuhandlerSetupRename,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_LITERAL_TEXT,
(uintptr_t)"Delete\n",
0,
menuhandlerSetupDelete,
},
{
MENUITEMTYPE_SEPARATOR,
0,
0,
0,
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
L_OPTIONS_213, // "Back"
0,
NULL,
},
{ MENUITEMTYPE_END },
};
struct menudialogdef g_MpGroupNameMenuDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t) "Group Name\n",
g_MpGroupNameMenuItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
struct menudialogdef g_ManageSetupDialog = {
MENUDIALOGTYPE_DEFAULT,
(uintptr_t)"Manage Setup",
g_ManageSetupItems,
NULL,
MENUDIALOGFLAG_LITERAL_TEXT,
NULL,
};
// -----------------------
static size_t readStr(char *dst, char *src)
{
char *start = dst;
@@ -181,50 +276,49 @@ static size_t readStr(char *dst, char *src)
return dst - start;
}
static void mpsetupfileRead(struct mpsetupfile *setupfile, u8 *buffer)
static void mpsetupDeserialize(struct mpsetupfile *setupfile, u8 *buffer)
{
BUF_READ(setupfile->version, buffer, u8);
BUF_READ(setupfile->defaultsetup, buffer, u8);
BUF_READ(setupfile->numsetups, buffer, u8);
BUF_READ(setupfile->numgroups, buffer, u8);
for (int i = 0; i < setupfile->numsetups; ++i) {
memcpy(setupfile->setups[i].bytes, buffer, MPSETUP_BLOCKSIZE);
buffer += MPSETUP_BLOCKSIZE;
}
for (int i = 0; i < setupfile->numgroups; ++i) {
struct setupgroup *group = &setupfile->groups[i];
BUF_READ(group->offset_index, buffer, u8);
buffer += readStr(group->name, buffer);
}
}
void mpsetupfileWrite(u8 *buffer, struct mpsetupfile *setupfile, struct savebuffer *setup, u8 setupidx, u8 overwrite)
void mpsetupSerialize(u8 *buffer, struct mpsetupfile *setupfile)
{
BUF_WRITE(setupfile->version, buffer, u8);
BUF_WRITE(setupfile->defaultsetup, buffer, u8);
BUF_WRITE(setupfile->numsetups, buffer, u8);
BUF_WRITE(setupfile->numgroups, buffer, u8);
for (int i = 0; i < setupfile->numsetups; ++i) {
if (i == setupidx) {
BUF_WRITEBLOCK(buffer, setup->bytes, MPSETUP_BLOCKSIZE);
if (!overwrite) {
BUF_WRITEBLOCK(buffer, setupfile->setups[i].bytes, MPSETUP_BLOCKSIZE)
}
continue;
}
BUF_WRITEBLOCK(buffer, setupfile->setups[i].bytes, MPSETUP_BLOCKSIZE)
}
}
for (int i = 0; i < setupfile->numgroups; ++i) {
struct setupgroup *group = &setupfile->groups[i];
BUF_WRITE(group->offset_index, buffer, u8);
buffer += readStr(buffer, group->name);
static s32 mpsetupSaveFile();
static s32 deleteSetup()
{
s32 slotindex = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
for (int i = slotindex; i < g_MpSetupFile.numsetups - 1; ++i) {
u8* dst = g_MpSetupFile.setups[i].bytes;
u8* src = g_MpSetupFile.setups[i+1].bytes;
memcpy(dst, src, MPSETUP_BLOCKSIZE);
}
if (g_MpCurrentSetup > slotindex) {
g_MpCurrentSetup--;
}
else if (g_MpCurrentSetup == slotindex) {
g_MpCurrentSetup = -1;
}
g_MpSetupFile.numsetups--;
return mpsetupSaveFile();
}
static FILE *openMpSetupFile(u8 mode) {
@@ -248,7 +342,7 @@ static FILE *openMpSetupFile(u8 mode) {
}
if (f == NULL) {
sysLogPrintf(LOG_NOTE, "Unable to open mp setup file");
sysLogPrintf(LOG_ERROR, "Unable to open mp setup file");
return NULL;
}
@@ -275,68 +369,21 @@ s32 mpsetupLoadFile()
fread(filebuffer, 1, size, f);
mpsetupfileRead(&g_MpSetupFile, filebuffer);
mpsetupDeserialize(&g_MpSetupFile, filebuffer);
if (g_MpSetupFile.defaultsetup != 0) {
g_MpCurrentSetup = g_MpSetupFile.defaultsetup;
}
// setup a default group if there is none
if (g_MpSetupFile.numgroups == 0) {
g_MpSetupFile.numgroups++;
strcpy(g_MpSetupFile.groups[0].name, "Default\n");
g_MpSetupFile.groups[0].offset_index = 0;
g_MpCurrentSetup = -1;
}
fsFileFree(f);
return 0;
}
static s32 getNewSetupIndex()
static s32 mpsetupSaveFile()
{
if (g_MpSetupFile.numsetups == 0) {
return 0;
}
if (g_MpCurrentGroup == g_MpSetupFile.numgroups - 1)
return g_MpSetupFile.numsetups;
return g_MpSetupFile.groups[g_MpCurrentGroup + 1].offset_index;
}
static s32 getGroupIndex(s32 setupIndex)
{
s32 index = 0;
struct setupgroup *groups = g_MpSetupFile.groups;
for (int i = 0; i < g_MpSetupFile.numgroups; ++i) {
if (setupIndex >= groups[i].offset_index) {
index = groups[i].offset_index;
}
}
return index;
}
s32 mpsetupSaveFile(const char *name, u8 overwrite)
{
struct savebuffer setup;
if (!overwrite) {
g_MpCurrentSetup = getNewSetupIndex();
g_MpSetupFile.numsetups++;
for (int i = g_MpCurrentGroup + 1; i < g_MpSetupFile.numgroups; ++i) {
g_MpSetupFile.groups[i].offset_index++;
}
}
savebufferClear(&setup);
mpsetupfileSaveWad(&setup);
zeroFileBuffer();
mpsetupfileWrite(filebuffer, &g_MpSetupFile, &setup, g_MpCurrentSetup, overwrite);
mpsetupSerialize(filebuffer, &g_MpSetupFile);
FILE *f = openMpSetupFile('w');
if (f == NULL) {
@@ -347,8 +394,24 @@ s32 mpsetupSaveFile(const char *name, u8 overwrite)
fsFileFree(f);
// reload the file to update in-memory structs
mpsetupLoadFile();
return 0;
return mpsetupLoadFile();
}
s32 mpsetupSaveSetup(s32 slotindex)
{
struct savebuffer setup;
// request to add a new setup
if (slotindex == g_MpSetupFile.numsetups) {
g_MpCurrentSetup = g_MpSetupFile.numsetups++;
}
savebufferClear(&setup);
mpsetupfileSaveWad(&setup);
memcpy(g_MpSetupFile.setups[slotindex].bytes, &setup.bytes, MPSETUP_BLOCKSIZE);
return mpsetupSaveFile();
}
void mpsetupLoadSetup(s32 index)
@@ -359,5 +422,4 @@ void mpsetupLoadSetup(s32 index)
memcpy(&buffer.bytes, block->bytes, MPSETUP_BLOCKSIZE);
mpsetupfileLoadWad(&buffer);
g_MpCurrentSetup = index;
g_MpCurrentGroup = getGroupIndex(index);
}
+17 -34
View File
@@ -33,7 +33,7 @@ struct menudialogdef g_MpChangeTeamNameMenuDialog;
struct menudialogdef g_MpEditSimulantMenuDialog;
struct menudialogdef g_MpSaveSetupNameMenuDialog;
extern struct menudialogdef g_MpSetupGroupsDialog;
extern struct menudialogdef g_MpManageSettingsDialog;
extern struct menudialogdef g_FilemgrFileSavedMenuDialog;
extern struct menudialogdef g_FilemgrErrorMenuDialog;
@@ -470,7 +470,7 @@ MenuItemHandlerResult menuhandlerMpSetupName(s32 operation, struct menuitem *ite
strcpy(g_MpSetup.name, name);
break;
case MENUOP_SET:
err = mpsetupSaveFile(name, false);
err = mpsetupSaveSetup(g_MpSetupFile.numsetups);
if (!err) {
menuPushDialog(&g_FilemgrFileSavedMenuDialog);
}
@@ -488,7 +488,8 @@ MenuItemHandlerResult menuhandlerMpSaveSetupOverwrite(s32 operation, struct menu
{
if (operation == MENUOP_SET) {
menuPopDialog();
mpsetupSaveFile(g_MpSetupFile.setups[g_MpCurrentSetup].bytes, true);
mpsetupSaveSetup(g_MpCurrentSetup);
menuPushDialog(&g_FilemgrFileSavedMenuDialog);
}
return 0;
@@ -498,7 +499,7 @@ MenuItemHandlerResult menuhandlerMpSaveSetupCopy(s32 operation, struct menuitem
{
if (operation == MENUOP_SET) {
menuPopDialog();
menuPushDialog(&g_MpSetupGroupsDialog);
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
}
return 0;
@@ -2289,25 +2290,15 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
data->list.value = 0xfffff;
break;
case MENUOP_GETOPTGROUPCOUNT:
data->list.value = g_MpSetupFile.numgroups + 1;
data->list.value = 2;
break;
case MENUOP_GETOPTGROUPTEXT:
if (data->list.value == 0) {
return (uintptr_t)langGet(L_MPMENU_141); // "Presets"
}
return (uintptr_t)&g_MpSetupFile.groups[data->list.value - 1].name;
break;
return (uintptr_t)"Custom";
case MENUOP_GETGROUPSTARTINDEX:
if (data->list.value == 0) {
data->list.groupstartindex = 0;
} else {
data->list.groupstartindex = mpGetNumUnlockedPresets();
if (g_MpSetupFile.numgroups > 0) {
data->list.groupstartindex += g_MpSetupFile.groups[data->list.value - 1].offset_index;
}
}
data->list.groupstartindex = data->list.value == 0 ? 0 : mpGetNumUnlockedPresets();
break;
case MENUOP_LISTITEMFOCUS:
if (data->list.value < mpGetNumUnlockedPresets()) {
@@ -2639,22 +2630,6 @@ struct menuitem g_MpLoadSettingsMenuItems[] = {
0,
NULL,
},
{
MENUITEMTYPE_SEPARATOR,
0,
MENUITEMFLAG_00000002,
0,
0,
NULL,
},
{
MENUITEMTYPE_LABEL,
0,
MENUITEMFLAG_00000002 | MENUITEMFLAG_SELECTABLE_CENTRE,
L_MPMENU_414, // "Press the B Button to go back."
0,
NULL,
},
{ MENUITEMTYPE_END },
};
@@ -5039,7 +5014,7 @@ MenuItemHandlerResult menuhandlerMpSaveSettings(s32 operation, struct menuitem *
{
if (operation == MENUOP_SET) {
if (g_MpCurrentSetup < 0) {
menuPushDialog(&g_MpSetupGroupsDialog);
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
}
else {
menuPushDialog(&g_MpSaveSetupExistsMenuDialog);
@@ -5779,6 +5754,14 @@ struct menuitem g_MpAdvancedSetupMenuItems[] = {
0,
NULL,
},
{
MENUITEMTYPE_SELECTABLE,
0,
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_OPENSDIALOG | MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LOCKABLEMAJOR,
(uintptr_t)"Manage Settings\n",
0,
(void *)&g_MpManageSettingsDialog,
},
{
MENUITEMTYPE_SELECTABLE,
0,
-1
View File
@@ -564,7 +564,6 @@ extern s32 g_MpWeaponRandomFilterNum;
extern struct mpsetupfile g_MpSetupFile;
extern s16 g_MpCurrentSetup;
extern s16 g_MpCurrentGroup;
#define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3]
#define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)
-7
View File
@@ -6160,18 +6160,11 @@ struct setupblock {
u8 bytes[MPSETUP_BLOCKSIZE];
};
struct setupgroup {
char name[MPSETUP_MAXGROUPNAME];
u8 offset_index;
};
struct mpsetupfile {
u8 version;
u8 defaultsetup;
u8 numsetups;
u8 numgroups;
struct setupblock setups[MPSETUP_MAXSETUPS];
struct setupgroup groups[MPSETUP_MAXGROUPS];
};
#endif