forked from Ports/perfect_dark
mpsetupfile (not 100% functional yet): load/save setup file, save new setups/groups, increased mp options/scenario data width
This commit is contained in:
1 parent
2ff8819265
commit
f5d851f7c2
13 files changed
+484
-112
No files matched your search
@@ -25,3 +25,4 @@ tools/mkrom/mkrom
|
|||||||
/.vs
|
/.vs
|
||||||
CppProperties.json
|
CppProperties.json
|
||||||
.idea
|
.idea
|
||||||
|
cmake-build-debug
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _IN_MPSETUPS_H
|
||||||
|
#define _IN_MPSETUPS_H
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
s32 mpsetupLoadFile();
|
||||||
|
void mpsetupLoadSetup(s32 index);
|
||||||
|
s32 mpsetupSaveFile(const char *name, u8 overwrite);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,363 @@
|
|||||||
|
#include "types.h"
|
||||||
|
#include "constants.h"
|
||||||
|
#include "game/menu.h"
|
||||||
|
#include "game/savebuffer.h"
|
||||||
|
#include "game/mplayer/mplayer.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "fs.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
MP Setup File Format
|
||||||
|
# header
|
||||||
|
[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); }
|
||||||
|
#define BUF_WRITEBLOCK(buf, src, size) { \
|
||||||
|
memcpy(buf, src, size); \
|
||||||
|
buf += size; }
|
||||||
|
|
||||||
|
// #### Group List
|
||||||
|
MenuItemHandlerResult mpSelectGroupHandler(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||||
|
|
||||||
|
struct menuitem g_MpSetupGroupsDialogItems[] = {
|
||||||
|
{
|
||||||
|
MENUITEMTYPE_LIST,
|
||||||
|
0,
|
||||||
|
MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
|
||||||
|
0x00000078,
|
||||||
|
0x00000042,
|
||||||
|
mpSelectGroupHandler,
|
||||||
|
},
|
||||||
|
{ MENUITEMTYPE_END },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct menudialogdef g_MpSetupGroupsDialog = {
|
||||||
|
MENUDIALOGTYPE_DEFAULT,
|
||||||
|
(uintptr_t) "Groups",
|
||||||
|
g_MpSetupGroupsDialogItems,
|
||||||
|
NULL,
|
||||||
|
MENUDIALOGFLAG_LITERAL_TEXT | MENUDIALOGFLAG_CLOSEONSELECT,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
MenuItemHandlerResult mpSelectGroupHandler(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);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_MpCurrentGroup = data->list.value;
|
||||||
|
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case MENUOP_GETSELECTEDINDEX:
|
||||||
|
data->list.value = 0xfffff;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// #### 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 },
|
||||||
|
};
|
||||||
|
|
||||||
|
struct menudialogdef g_MpGroupNameMenuDialog = {
|
||||||
|
MENUDIALOGTYPE_DEFAULT,
|
||||||
|
(uintptr_t) "Group Name\n",
|
||||||
|
g_MpGroupNameMenuItems,
|
||||||
|
NULL,
|
||||||
|
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static size_t readStr(char *dst, char *src)
|
||||||
|
{
|
||||||
|
char *start = dst;
|
||||||
|
while (*src) {
|
||||||
|
*dst = *src;
|
||||||
|
dst++;
|
||||||
|
src++;
|
||||||
|
}
|
||||||
|
*dst = '\0';
|
||||||
|
dst++;
|
||||||
|
return dst - start;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mpsetupfileRead(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)
|
||||||
|
{
|
||||||
|
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 FILE *openMpSetupFile(u8 mode) {
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if (fsFileSize(MPSETUP_FILE) < 0) {
|
||||||
|
// setup file doesn't exist: create one
|
||||||
|
f = fsFileOpenWrite(MPSETUP_FILE);
|
||||||
|
fsFileFree(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == 'r') {
|
||||||
|
f = fsFileOpenRead(MPSETUP_FILE);
|
||||||
|
}
|
||||||
|
else if (mode == 'w') {
|
||||||
|
f = fsFileOpenWrite(MPSETUP_FILE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sysLogPrintf(LOG_ERROR, "openMpSetupFile: invalid file mode");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f == NULL) {
|
||||||
|
sysLogPrintf(LOG_NOTE, "Unable to open mp setup file");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void zeroFileBuffer()
|
||||||
|
{
|
||||||
|
memset(filebuffer, 0, sizeof(struct mpsetupfile));
|
||||||
|
}
|
||||||
|
|
||||||
|
s32 mpsetupLoadFile()
|
||||||
|
{
|
||||||
|
FILE *f = openMpSetupFile('r');
|
||||||
|
if (f == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
zeroFileBuffer();
|
||||||
|
|
||||||
|
fseek(f, 0L, SEEK_END);
|
||||||
|
size_t size = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
fread(filebuffer, 1, size, f);
|
||||||
|
|
||||||
|
mpsetupfileRead(&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()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
FILE *f = openMpSetupFile('w');
|
||||||
|
if (f == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(filebuffer, sizeof(struct mpsetupfile), 1, f);
|
||||||
|
fsFileFree(f);
|
||||||
|
|
||||||
|
// reload the file to update in-memory structs
|
||||||
|
mpsetupLoadFile();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mpsetupLoadSetup(s32 index)
|
||||||
|
{
|
||||||
|
struct savebuffer buffer;
|
||||||
|
savebufferClear(&buffer);
|
||||||
|
struct setupblock *block = &g_MpSetupFile.setups[index];
|
||||||
|
memcpy(&buffer.bytes, block->bytes, MPSETUP_BLOCKSIZE);
|
||||||
|
mpsetupfileLoadWad(&buffer);
|
||||||
|
g_MpCurrentSetup = index;
|
||||||
|
g_MpCurrentGroup = getGroupIndex(index);
|
||||||
|
}
|
||||||
@@ -816,12 +816,6 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess)
|
|||||||
g_Menus[g_MpPlayerNum].fm.fileid,
|
g_Menus[g_MpPlayerNum].fm.fileid,
|
||||||
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
||||||
break;
|
break;
|
||||||
case FILEOP_SAVE_MPSETUP:
|
|
||||||
errnum = mpsetupfileSave(device,
|
|
||||||
g_Menus[g_MpPlayerNum].fm.fileid,
|
|
||||||
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
|
||||||
showfilesaved = true;
|
|
||||||
break;
|
|
||||||
case FILEOP_WRITE_GAME:
|
case FILEOP_WRITE_GAME:
|
||||||
case FILEOP_WRITE_MPSETUP:
|
case FILEOP_WRITE_MPSETUP:
|
||||||
case FILEOP_WRITE_MPPLAYER:
|
case FILEOP_WRITE_MPPLAYER:
|
||||||
@@ -845,11 +839,6 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess)
|
|||||||
g_Menus[g_MpPlayerNum].fm.fileid,
|
g_Menus[g_MpPlayerNum].fm.fileid,
|
||||||
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
||||||
break;
|
break;
|
||||||
case FILEOP_LOAD_MPSETUP:
|
|
||||||
errnum = mpsetupfileLoad(device,
|
|
||||||
g_Menus[g_MpPlayerNum].fm.fileid,
|
|
||||||
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
|
||||||
break;
|
|
||||||
case FILEOP_READ_GAME:
|
case FILEOP_READ_GAME:
|
||||||
case FILEOP_READ_MPSETUP:
|
case FILEOP_READ_MPSETUP:
|
||||||
case FILEOP_READ_MPPLAYER:
|
case FILEOP_READ_MPPLAYER:
|
||||||
|
|||||||
@@ -614,6 +614,15 @@ Gfx *menuitemListRender(Gfx *gdl, struct menurendercontext *context)
|
|||||||
height = 0;
|
height = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reuse the label color flag here
|
||||||
|
if (context->item->flags & MENUITEMFLAG_LABEL_CUSTOMCOLOUR) {
|
||||||
|
u32 savedunk04 = sp15c.list.unk04;
|
||||||
|
sp15c.list.unk04 = colour;
|
||||||
|
context->item->handler(MENUOP_GETCOLOUR, context->item, &sp15c);
|
||||||
|
colour = sp15c.list.unk04;
|
||||||
|
sp15c.list.unk04 = savedunk04;
|
||||||
|
}
|
||||||
|
|
||||||
gdl = textRenderProjected(gdl, &x, &y, text2, chars, font, colour, context->width - left + context->x, height, sp128, 0);
|
gdl = textRenderProjected(gdl, &x, &y, text2, chars, font, colour, context->width - left + context->x, height, sp128, 0);
|
||||||
|
|
||||||
// Consider a checkbox
|
// Consider a checkbox
|
||||||
|
|||||||
@@ -28,6 +28,9 @@
|
|||||||
#include "lib/lib_317f0.h"
|
#include "lib/lib_317f0.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "mpsetups.h"
|
||||||
|
|
||||||
// bss
|
// bss
|
||||||
struct chrdata *g_MpAllChrPtrs[MAX_MPCHRS];
|
struct chrdata *g_MpAllChrPtrs[MAX_MPCHRS];
|
||||||
@@ -3924,7 +3927,7 @@ void mpsetupfileLoadWad(struct savebuffer *buffer)
|
|||||||
scenarioInit();
|
scenarioInit();
|
||||||
scenarioReadSave(buffer);
|
scenarioReadSave(buffer);
|
||||||
|
|
||||||
g_MpSetup.options = savebufferReadBits(buffer, 21);
|
g_MpSetup.options = savebufferReadBits(buffer, 32);
|
||||||
g_MpSetup.chrslots &= 0x000f;
|
g_MpSetup.chrslots &= 0x000f;
|
||||||
|
|
||||||
for (i = 0; i < MAX_BOTS; i++) {
|
for (i = 0; i < MAX_BOTS; i++) {
|
||||||
@@ -3984,7 +3987,7 @@ void mpsetupfileSaveWad(struct savebuffer *buffer)
|
|||||||
|
|
||||||
scenarioWriteSave(buffer);
|
scenarioWriteSave(buffer);
|
||||||
|
|
||||||
savebufferOr(buffer, g_MpSetup.options, 21);
|
savebufferOr(buffer, g_MpSetup.options, 32);
|
||||||
|
|
||||||
for (i = 0; i < MAX_BOTS; i++) {
|
for (i = 0; i < MAX_BOTS; i++) {
|
||||||
savebufferOr(buffer, g_BotConfigsArray[i].type, 5);
|
savebufferOr(buffer, g_BotConfigsArray[i].type, 5);
|
||||||
@@ -4039,60 +4042,6 @@ void mpsetupfileGetOverview(char *arg0, char *filename, u16 *numsims, u16 *stage
|
|||||||
*scenarionum = savebufferReadBits(&buffer, 3);
|
*scenarionum = savebufferReadBits(&buffer, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 mpsetupfileSave(s32 device, s32 fileid, u16 deviceserial)
|
|
||||||
{
|
|
||||||
s32 ret;
|
|
||||||
s32 newfileid;
|
|
||||||
struct savebuffer buffer;
|
|
||||||
|
|
||||||
if (device >= 0) {
|
|
||||||
savebufferClear(&buffer);
|
|
||||||
mpsetupfileSaveWad(&buffer);
|
|
||||||
func0f0d54c4(&buffer);
|
|
||||||
|
|
||||||
ret = pakSaveAtGuid(device, fileid, PAKFILETYPE_MPSETUP, buffer.bytes, &newfileid, 0);
|
|
||||||
var80075bd0[1] = true;
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
g_MpSetup.fileguid.fileid = newfileid;
|
|
||||||
g_MpSetup.fileguid.deviceserial = deviceserial;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_FilemgrLastPakError = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
s32 mpsetupfileLoad(s32 device, s32 fileid, u16 deviceserial)
|
|
||||||
{
|
|
||||||
s32 ret;
|
|
||||||
struct savebuffer buffer;
|
|
||||||
|
|
||||||
if (device >= 0) {
|
|
||||||
savebufferClear(&buffer);
|
|
||||||
ret = pakReadBodyAtGuid(device, fileid, buffer.bytes, 0);
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
g_MpSetup.fileguid.fileid = fileid;
|
|
||||||
g_MpSetup.fileguid.deviceserial = deviceserial;
|
|
||||||
|
|
||||||
mpsetupfileLoadWad(&buffer);
|
|
||||||
func0f0d54c4(&buffer);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_FilemgrLastPakError = ret;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void func0f18e558(void)
|
void func0f18e558(void)
|
||||||
{
|
{
|
||||||
s32 i;
|
s32 i;
|
||||||
|
|||||||
@@ -438,7 +438,7 @@ void scenarioWriteSave(struct savebuffer *buffer)
|
|||||||
if (g_MpScenarios[g_MpSetup.scenario].writesavefunc) {
|
if (g_MpScenarios[g_MpSetup.scenario].writesavefunc) {
|
||||||
g_MpScenarios[g_MpSetup.scenario].writesavefunc(buffer);
|
g_MpScenarios[g_MpSetup.scenario].writesavefunc(buffer);
|
||||||
} else {
|
} else {
|
||||||
savebufferOr(buffer, 0, 8);
|
savebufferOr(buffer, 0, 32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -183,12 +183,12 @@ struct menudialogdef g_KohOptionsMenuDialog = {
|
|||||||
|
|
||||||
void kohReadSave(struct savebuffer *buffer)
|
void kohReadSave(struct savebuffer *buffer)
|
||||||
{
|
{
|
||||||
g_Vars.mphilltime = savebufferReadBits(buffer, 8);
|
g_Vars.mphilltime = savebufferReadBits(buffer, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kohWriteSave(struct savebuffer *buffer)
|
void kohWriteSave(struct savebuffer *buffer)
|
||||||
{
|
{
|
||||||
savebufferOr(buffer, g_Vars.mphilltime, 8);
|
savebufferOr(buffer, g_Vars.mphilltime, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kohInit(void)
|
void kohInit(void)
|
||||||
|
|||||||
+66
-41
@@ -23,6 +23,8 @@
|
|||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "gbiex.h"
|
#include "gbiex.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "system.h"
|
||||||
|
#include "mpsetups.h"
|
||||||
|
|
||||||
struct menuitem g_MpCharacterMenuItems[];
|
struct menuitem g_MpCharacterMenuItems[];
|
||||||
struct menudialogdef g_MpAddSimulantMenuDialog;
|
struct menudialogdef g_MpAddSimulantMenuDialog;
|
||||||
@@ -31,6 +33,10 @@ struct menudialogdef g_MpChangeTeamNameMenuDialog;
|
|||||||
struct menudialogdef g_MpEditSimulantMenuDialog;
|
struct menudialogdef g_MpEditSimulantMenuDialog;
|
||||||
struct menudialogdef g_MpSaveSetupNameMenuDialog;
|
struct menudialogdef g_MpSaveSetupNameMenuDialog;
|
||||||
|
|
||||||
|
extern struct menudialogdef g_MpSetupGroupsDialog;
|
||||||
|
extern struct menudialogdef g_FilemgrFileSavedMenuDialog;
|
||||||
|
extern struct menudialogdef g_FilemgrErrorMenuDialog;
|
||||||
|
|
||||||
#ifndef PLATFORM_N64
|
#ifndef PLATFORM_N64
|
||||||
extern s32 g_MpWeaponSetNum;
|
extern s32 g_MpWeaponSetNum;
|
||||||
#endif
|
#endif
|
||||||
@@ -454,6 +460,7 @@ MenuItemHandlerResult menuhandlerMpConfirmSaveChr(s32 operation, struct menuitem
|
|||||||
MenuItemHandlerResult menuhandlerMpSetupName(s32 operation, struct menuitem *item, union handlerdata *data)
|
MenuItemHandlerResult menuhandlerMpSetupName(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||||
{
|
{
|
||||||
char *name = data->keyboard.string;
|
char *name = data->keyboard.string;
|
||||||
|
s32 err;
|
||||||
|
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MENUOP_GETTEXT:
|
case MENUOP_GETTEXT:
|
||||||
@@ -463,7 +470,14 @@ MenuItemHandlerResult menuhandlerMpSetupName(s32 operation, struct menuitem *ite
|
|||||||
strcpy(g_MpSetup.name, name);
|
strcpy(g_MpSetup.name, name);
|
||||||
break;
|
break;
|
||||||
case MENUOP_SET:
|
case MENUOP_SET:
|
||||||
filemgrPushSelectLocationDialog(7, FILETYPE_MPSETUP);
|
err = mpsetupSaveFile(name, false);
|
||||||
|
if (!err) {
|
||||||
|
menuPushDialog(&g_FilemgrFileSavedMenuDialog);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// menuPushDialog(&g_FilemgrErrorMenuDialog);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,7 +488,7 @@ MenuItemHandlerResult menuhandlerMpSaveSetupOverwrite(s32 operation, struct menu
|
|||||||
{
|
{
|
||||||
if (operation == MENUOP_SET) {
|
if (operation == MENUOP_SET) {
|
||||||
menuPopDialog();
|
menuPopDialog();
|
||||||
filemgrSaveOrLoad(&g_MpSetup.fileguid, FILEOP_SAVE_MPSETUP, 0);
|
mpsetupSaveFile(g_MpSetupFile.setups[g_MpCurrentSetup].bytes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -484,7 +498,7 @@ MenuItemHandlerResult menuhandlerMpSaveSetupCopy(s32 operation, struct menuitem
|
|||||||
{
|
{
|
||||||
if (operation == MENUOP_SET) {
|
if (operation == MENUOP_SET) {
|
||||||
menuPopDialog();
|
menuPopDialog();
|
||||||
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
|
menuPushDialog(&g_MpSetupGroupsDialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1112,10 +1126,10 @@ struct menuitem g_MpSaveSetupExistsMenuItems[] = {
|
|||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
MENUITEMTYPE_LABEL,
|
MENUITEMTYPE_SEPARATOR,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
0,
|
0,
|
||||||
MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_SMALLFONT,
|
|
||||||
(uintptr_t)&filemgrMenuTextDeviceName,
|
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
@@ -1123,8 +1137,16 @@ struct menuitem g_MpSaveSetupExistsMenuItems[] = {
|
|||||||
{
|
{
|
||||||
MENUITEMTYPE_LABEL,
|
MENUITEMTYPE_LABEL,
|
||||||
0,
|
0,
|
||||||
MENUITEMFLAG_LESSLEFTPADDING,
|
MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_LITERAL_TEXT,
|
||||||
L_MPMENU_184, // "Do you want to save over your original game file?"
|
(uintptr_t)"Save over your\noriginal setup?\n",
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MENUITEMTYPE_SEPARATOR,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
0,
|
0,
|
||||||
NULL,
|
NULL,
|
||||||
},
|
},
|
||||||
@@ -2232,17 +2254,15 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
|
|||||||
switch (operation) {
|
switch (operation) {
|
||||||
case MENUOP_GETOPTIONCOUNT:
|
case MENUOP_GETOPTIONCOUNT:
|
||||||
data->list.value = mpGetNumUnlockedPresets();
|
data->list.value = mpGetNumUnlockedPresets();
|
||||||
|
data->list.value += g_MpSetupFile.numsetups;
|
||||||
if (g_FileLists[1] != NULL) {
|
|
||||||
data->list.value += g_FileLists[1]->numfiles;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MENUOP_GETOPTIONTEXT:
|
case MENUOP_GETOPTIONTEXT:
|
||||||
if (data->list.value < mpGetNumUnlockedPresets()) {
|
if (data->list.value < mpGetNumUnlockedPresets()) {
|
||||||
return (uintptr_t)mpGetPresetNameBySlot(data->list.value);
|
return (uintptr_t)mpGetPresetNameBySlot(data->list.value);
|
||||||
}
|
}
|
||||||
if (g_FileLists[1] != NULL) {
|
if (g_MpSetupFile.numsetups > 0) {
|
||||||
func0f0d564c(g_FileLists[1]->files[data->list.value - mpGetNumUnlockedPresets()].name, g_StringPointer, false);
|
struct setupblock *block = &g_MpSetupFile.setups[data->list.value - mpGetNumUnlockedPresets()];
|
||||||
|
func0f0d564c(block->bytes, g_StringPointer, false);
|
||||||
return (uintptr_t)g_StringPointer;
|
return (uintptr_t)g_StringPointer;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2251,14 +2271,10 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
|
|||||||
|
|
||||||
if (data->list.value < mpGetNumUnlockedPresets()) {
|
if (data->list.value < mpGetNumUnlockedPresets()) {
|
||||||
mp0f18dec4(data->list.value);
|
mp0f18dec4(data->list.value);
|
||||||
} else if (g_FileLists[1] != NULL) {
|
g_MpCurrentSetup = -1;
|
||||||
struct filelistfile *file = &g_FileLists[1]->files[data->list.value - mpGetNumUnlockedPresets()];
|
}
|
||||||
struct fileguid guid;
|
else {
|
||||||
|
mpsetupLoadSetup(data->list.value - mpGetNumUnlockedPresets());
|
||||||
guid.fileid = file->fileid;
|
|
||||||
guid.deviceserial = file->deviceserial;
|
|
||||||
|
|
||||||
filemgrSaveOrLoad(&guid, FILEOP_LOAD_MPSETUP, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item->param == 1) {
|
if (item->param == 1) {
|
||||||
@@ -2273,19 +2289,14 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
|
|||||||
data->list.value = 0xfffff;
|
data->list.value = 0xfffff;
|
||||||
break;
|
break;
|
||||||
case MENUOP_GETOPTGROUPCOUNT:
|
case MENUOP_GETOPTGROUPCOUNT:
|
||||||
data->list.value = 1;
|
data->list.value = g_MpSetupFile.numgroups + 1;
|
||||||
|
|
||||||
if (g_FileLists[1] != NULL) {
|
|
||||||
data->list.value += g_FileLists[1]->numdevices;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MENUOP_GETOPTGROUPTEXT:
|
case MENUOP_GETOPTGROUPTEXT:
|
||||||
if (data->list.value == 0) {
|
if (data->list.value == 0) {
|
||||||
return (uintptr_t)langGet(L_MPMENU_141); // "Presets"
|
return (uintptr_t)langGet(L_MPMENU_141); // "Presets"
|
||||||
}
|
}
|
||||||
if (g_FileLists[1] != NULL) {
|
|
||||||
return (uintptr_t)filemgrGetDeviceNameOrStartIndex(1, operation, data->list.value - 1);
|
return (uintptr_t)&g_MpSetupFile.groups[data->list.value - 1].name;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case MENUOP_GETGROUPSTARTINDEX:
|
case MENUOP_GETGROUPSTARTINDEX:
|
||||||
if (data->list.value == 0) {
|
if (data->list.value == 0) {
|
||||||
@@ -2293,16 +2304,14 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
|
|||||||
} else {
|
} else {
|
||||||
data->list.groupstartindex = mpGetNumUnlockedPresets();
|
data->list.groupstartindex = mpGetNumUnlockedPresets();
|
||||||
|
|
||||||
if (g_FileLists[1] != NULL) {
|
if (g_MpSetupFile.numgroups > 0) {
|
||||||
data->list.groupstartindex += filemgrGetDeviceNameOrStartIndex(1, operation, data->list.value - 1);
|
data->list.groupstartindex += g_MpSetupFile.groups[data->list.value - 1].offset_index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MENUOP_LISTITEMFOCUS:
|
case MENUOP_LISTITEMFOCUS:
|
||||||
if (data->list.value < mpGetNumUnlockedPresets()) {
|
if (data->list.value < mpGetNumUnlockedPresets()) {
|
||||||
g_Menus[g_MpPlayerNum].mpsetup.slotindex = 0xffff;
|
g_Menus[g_MpPlayerNum].mpsetup.slotindex = 0xffff;
|
||||||
} else {
|
|
||||||
g_Menus[g_MpPlayerNum].mpsetup.slotindex = data->list.value - mpGetNumUnlockedPresets();
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2630,6 +2639,22 @@ struct menuitem g_MpLoadSettingsMenuItems[] = {
|
|||||||
0,
|
0,
|
||||||
NULL,
|
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 },
|
{ MENUITEMTYPE_END },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -5013,13 +5038,10 @@ MenuItemHandlerResult menuhandler0017ef30(s32 operation, struct menuitem *item,
|
|||||||
MenuItemHandlerResult menuhandlerMpSaveSettings(s32 operation, struct menuitem *item, union handlerdata *data)
|
MenuItemHandlerResult menuhandlerMpSaveSettings(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||||
{
|
{
|
||||||
if (operation == MENUOP_SET) {
|
if (operation == MENUOP_SET) {
|
||||||
if (g_MpSetup.fileguid.fileid == 0) {
|
if (g_MpCurrentSetup < 0) {
|
||||||
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
|
menuPushDialog(&g_MpSetupGroupsDialog);
|
||||||
} else {
|
}
|
||||||
#if VERSION >= VERSION_NTSC_1_0
|
else {
|
||||||
filemgrSetDevice1BySerial(g_MpSetup.fileguid.deviceserial);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
menuPushDialog(&g_MpSaveSetupExistsMenuDialog);
|
menuPushDialog(&g_MpSaveSetupExistsMenuDialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5362,6 +5384,9 @@ MenuDialogHandlerResult menudialogCombatSimulator(s32 operation, struct menudial
|
|||||||
g_Vars.waitingtojoin[1] = false;
|
g_Vars.waitingtojoin[1] = false;
|
||||||
g_Vars.waitingtojoin[2] = false;
|
g_Vars.waitingtojoin[2] = false;
|
||||||
g_Vars.waitingtojoin[3] = false;
|
g_Vars.waitingtojoin[3] = false;
|
||||||
|
|
||||||
|
// load the setup file when entering the Combat Simulator
|
||||||
|
mpsetupLoadFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_Menus[g_MpPlayerNum].curdialog
|
if (g_Menus[g_MpPlayerNum].curdialog
|
||||||
|
|||||||
@@ -4754,6 +4754,11 @@ enum weaponnum {
|
|||||||
|
|
||||||
#define EXTRA_SLEEP_TIME 1000LL // 100us
|
#define EXTRA_SLEEP_TIME 1000LL // 100us
|
||||||
|
|
||||||
|
#define MPSETUP_MAXSETUPS 100
|
||||||
|
#define MPSETUP_MAXGROUPS 100
|
||||||
|
#define MPSETUP_MAXGROUPNAME 33
|
||||||
|
#define MPSETUP_BLOCKSIZE 64
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -562,6 +562,10 @@ extern s32 g_FileAutoSelect;
|
|||||||
extern u8 g_MpWeaponSetRandomFilters[NUM_MPWEAPONS];
|
extern u8 g_MpWeaponSetRandomFilters[NUM_MPWEAPONS];
|
||||||
extern s32 g_MpWeaponRandomFilterNum;
|
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_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3]
|
||||||
#define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)
|
#define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,6 @@ void mpsetupfileLoadWad(struct savebuffer *buffer);
|
|||||||
void mpsetupfileSaveWad(struct savebuffer *buffer);
|
void mpsetupfileSaveWad(struct savebuffer *buffer);
|
||||||
void mpsetupfileGetOverview(char *arg0, char *filename, u16 *numsims, u16 *stagenum, u16 *scenarionum);
|
void mpsetupfileGetOverview(char *arg0, char *filename, u16 *numsims, u16 *stagenum, u16 *scenarionum);
|
||||||
s32 mpsetupfileSave(s32 device, s32 filenum, u16 deviceserial);
|
s32 mpsetupfileSave(s32 device, s32 filenum, u16 deviceserial);
|
||||||
s32 mpsetupfileLoad(s32 device, s32 filenum, u16 deviceserial);
|
|
||||||
void func0f18e558(void);
|
void func0f18e558(void);
|
||||||
struct modeldef *func0f18e57c(s32 index, s32 *headnum);
|
struct modeldef *func0f18e57c(s32 index, s32 *headnum);
|
||||||
|
|
||||||
|
|||||||
@@ -6156,6 +6156,24 @@ struct extplayerconfig {
|
|||||||
s32 usereloads;
|
s32 usereloads;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
Reference in new issue
Block a user