mirror of
https://github.com/perfect-dark-pc-port/perfect_dark.git
synced 2026-10-23 15:52:41 +02:00
Merge branch 'port' into port-no-doors
This commit is contained in:
commit
54b62c044f
39 files changed
+1487
-395
No files matched your search
@@ -25,3 +25,4 @@ tools/mkrom/mkrom
|
||||
/.vs
|
||||
CppProperties.json
|
||||
.idea
|
||||
cmake-build-debug
|
||||
@@ -22,5 +22,6 @@ FILE *fsFileOpenRead(const char *name);
|
||||
void fsFileFree(FILE *f);
|
||||
|
||||
const char *fsGetModDir(void);
|
||||
s32 fsCreateDir(const char *path);
|
||||
|
||||
#endif
|
||||
@@ -40,6 +40,7 @@ enum virtkey {
|
||||
VK_DELETE = 76,
|
||||
VK_LCTRL = 224,
|
||||
VK_LSHIFT = 225,
|
||||
VK_LALT = 226,
|
||||
VK_RCTRL = 228,
|
||||
VK_RSHIFT = 229,
|
||||
|
||||
@@ -56,6 +57,8 @@ enum virtkey {
|
||||
/* same order as SDL gamecontroller buttons plus two buttons for triggers */
|
||||
VK_JOY_BEGIN,
|
||||
VK_JOY1_BEGIN = VK_JOY_BEGIN,
|
||||
VK_JOY1_LSHOULDER = VK_JOY1_BEGIN + 9,
|
||||
VK_JOY1_RSHOULDER = VK_JOY1_BEGIN + 10,
|
||||
VK_JOY1_LTRIG = VK_JOY1_BEGIN + 30,
|
||||
VK_JOY1_RTRIG = VK_JOY1_BEGIN + 31,
|
||||
VK_JOY2_BEGIN = VK_JOY1_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef _IN_MPSETUPS_H
|
||||
#define _IN_MPSETUPS_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
s32 mpsetupLoadCurrentFile(void);
|
||||
s32 mpsetupSaveCurrentFile(void);
|
||||
void mpsetupLoadSetup(s32 slotindex);
|
||||
s32 mpsetupSaveSetup(s32 slotindex, u8 savefile);
|
||||
void mpsetupCopyAllFromPak(void);
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,9 @@
|
||||
#include "platform.h"
|
||||
#include "utils.h"
|
||||
#include "fs.h"
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include <direct.h>
|
||||
#endif
|
||||
|
||||
#define DEFAULT_BASEDIR_NAME "data"
|
||||
|
||||
@@ -280,3 +283,12 @@ void fsFileFree(FILE *f)
|
||||
{
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
s32 fsCreateDir(const char *path)
|
||||
{
|
||||
#ifdef PLATFORM_WIN32
|
||||
return _mkdir(fsFullPath(path));
|
||||
#else
|
||||
return mkdir(fsFullPath(path), 0777);
|
||||
#endif
|
||||
}
|
||||
+20
-24
@@ -88,8 +88,8 @@ static s32 mouseLockMode = MLOCK_AUTO;
|
||||
static u64 mouseCursorTime = 0;
|
||||
static s32 mouseShowCursor = 1;
|
||||
|
||||
static f32 mouseSensX = 1.5f;
|
||||
static f32 mouseSensY = 1.5f;
|
||||
static f32 mouseSensX = 2.5f;
|
||||
static f32 mouseSensY = 2.5f;
|
||||
|
||||
static s32 lastKey = 0;
|
||||
static char lastChar = 0;
|
||||
@@ -1239,32 +1239,28 @@ void inputMouseGetRawDelta(s32 *dx, s32 *dy)
|
||||
if (dy) *dy = mouseDY;
|
||||
}
|
||||
|
||||
void inputMouseGetScaledDelta(f32 *dx, f32 *dy)
|
||||
void inputMouseGetScaledDelta(f32* dx, f32* dy)
|
||||
{
|
||||
f32 mdx, mdy;
|
||||
if (mouseLocked) {
|
||||
mdx = mouseSensX * (f32)mouseDX / 100.0f;
|
||||
mdy = mouseSensY * (f32)mouseDY / 100.0f;
|
||||
} else {
|
||||
mdx = 0.f;
|
||||
mdy = 0.f;
|
||||
}
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
f32 mdx = 0.f, mdy = 0.f;
|
||||
|
||||
if (mouseLocked) {
|
||||
mdx = mouseSensX * ((f32)mouseDX / 3.5f) * 0.022f;
|
||||
mdy = mouseSensY * ((f32)mouseDY / 3.5f) * 0.022f;
|
||||
}
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
}
|
||||
|
||||
void inputMouseGetAbsScaledDelta(f32 *dx, f32 *dy)
|
||||
void inputMouseGetAbsScaledDelta(f32* dx, f32* dy)
|
||||
{
|
||||
f32 mdx, mdy;
|
||||
if (mouseLocked) {
|
||||
mdx = fabsf(mouseSensX) * (f32)mouseDX / 100.0f;
|
||||
mdy = fabsf(mouseSensY) * (f32)mouseDY / 100.0f;
|
||||
} else {
|
||||
mdx = 0.f;
|
||||
mdy = 0.f;
|
||||
}
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
f32 mdx = 0.f, mdy = 0.f;
|
||||
|
||||
if (mouseLocked) {
|
||||
mdx = fabsf(mouseSensX) * ((f32)mouseDX / 3.5f) * 0.022f;
|
||||
mdy = fabsf(mouseSensY) * ((f32)mouseDY / 3.5f) * 0.022f;
|
||||
}
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
}
|
||||
|
||||
void inputMouseGetSpeed(f32 *x, f32 *y)
|
||||
|
||||
@@ -0,0 +1,896 @@
|
||||
#include "types.h"
|
||||
#include "constants.h"
|
||||
#include "bss.h"
|
||||
#include "game/pak.h"
|
||||
#include "game/filelist.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
|
||||
# header
|
||||
[version{1}]
|
||||
[defaultsetup{1}]
|
||||
[numsetups{1}]
|
||||
# setups
|
||||
[setup_1{80}]
|
||||
...
|
||||
[setup_n{80}]
|
||||
*/
|
||||
|
||||
#define MPSETUP_VERSION 1
|
||||
|
||||
#define MPSETUP_EXPORTDIR "$S/exported/"
|
||||
#define MPSETUP_FILENAME "mpsetups"
|
||||
#define MPSETUP_FILENAME_EXP "mpsetups-ext"
|
||||
|
||||
#define MPSETUP_OP_DEFAULT 0
|
||||
#define MPSETUP_OP_IMPORT 1
|
||||
#define MPSETUP_OP_EXPORT 2
|
||||
|
||||
#define MPSETUP_IMPORT_OVERWRITE 0
|
||||
#define MPSETUP_IMPORT_ADD 1
|
||||
|
||||
#define MPSETUP_IMPORT_CONFLICT 0x1313
|
||||
|
||||
extern struct menudialogdef g_MpSaveSetupNameMenuDialog;
|
||||
|
||||
s16 g_MpCurrentSetup = -1;
|
||||
struct mpsetupfile g_MpSetupFile;
|
||||
|
||||
static struct mpsetupfile g_ImportMpSetupFile;
|
||||
static u64 g_MpImportExportFilter[2];
|
||||
|
||||
static char g_StatusText[128];
|
||||
static char g_TitleImportExportDialog[20];
|
||||
static char g_LabelSetDefault[20] = "Set Default\n";
|
||||
|
||||
/* extended mpsetup menu definitions */
|
||||
|
||||
static MenuItemHandlerResult menuhandlerRenameSetup(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerImportOrExportSettings(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerImportAction(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerOpenImportExportDialog(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSelectSetupHandler(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
static MenuItemHandlerResult menuhandlerSetupSetDefault(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
|
||||
static struct menuitem g_StatusOkMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)g_StatusText,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
L_OPTIONS_347, // "OK"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_StatusOkDialog = {
|
||||
MENUDIALOGTYPE_SUCCESS,
|
||||
L_OPTIONS_345, // "Cool!"
|
||||
g_StatusOkMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_DISABLEBANNER,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_StatusErrorMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)g_StatusText,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG | MENUITEMFLAG_SELECTABLE_CENTRE,
|
||||
L_OPTIONS_347, // "OK"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
/* public */
|
||||
struct menudialogdef g_StatusErrorDialog = {
|
||||
MENUDIALOGTYPE_DANGER,
|
||||
L_OPTIONS_277, // "Failed"
|
||||
g_StatusErrorMenuItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_DISABLEBANNER,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_RenameSetupItems[] = {
|
||||
#if VERSION != VERSION_JPN_FINAL
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)"Enter the setup name:\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
MENUITEMTYPE_KEYBOARD,
|
||||
18,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
menuhandlerRenameSetup,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_RenameSetupDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Setup Name:\n",
|
||||
g_RenameSetupItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static 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 },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_DeleteSetupDialog = {
|
||||
MENUDIALOGTYPE_DANGER,
|
||||
(uintptr_t)"Delete Setup\n",
|
||||
g_DeleteSetupItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_ImportExportItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LIST,
|
||||
0,
|
||||
MENUITEMFLAG_LOCKABLEMINOR | MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
|
||||
140,
|
||||
0x0000004d,
|
||||
menuhandlerImportOrExportSettings,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ImportExportDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t) g_TitleImportExportDialog,
|
||||
g_ImportExportItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_ManageImportExportItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_OP_IMPORT,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Import Settings\n",
|
||||
0,
|
||||
menuhandlerOpenImportExportDialog,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_OP_EXPORT,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Export Settings\n",
|
||||
0,
|
||||
menuhandlerOpenImportExportDialog,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ManageImportExportDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t) "Import/Export\n",
|
||||
g_ManageImportExportItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_MpManageSettingsListItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LIST,
|
||||
0,
|
||||
MENUITEMFLAG_LABEL_CUSTOMCOLOUR,
|
||||
160,
|
||||
0x00000042,
|
||||
menuhandlerSelectSetupHandler,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
|
||||
};
|
||||
|
||||
/* public */
|
||||
struct menudialogdef g_ManageSettingsDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t) "Manage Settings\n",
|
||||
g_MpManageSettingsListItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
&g_ManageImportExportDialog,
|
||||
};
|
||||
|
||||
static 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_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)g_LabelSetDefault,
|
||||
0,
|
||||
menuhandlerSetupSetDefault,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
L_OPTIONS_213, // "Back"
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ManageSetupDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Manage Setup",
|
||||
g_ManageSetupItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct menuitem g_ImportOverrideItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t) "How to resolve setups\nwith the same name?\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_IMPORT_ADD,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
(uintptr_t) "Add\n",
|
||||
0,
|
||||
menuhandlerImportAction,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
MPSETUP_IMPORT_OVERWRITE,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_SELECTABLE_CLOSESDIALOG,
|
||||
(uintptr_t) "Overwrite\n",
|
||||
0,
|
||||
menuhandlerImportAction,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
static struct menudialogdef g_ImportOverrideDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
(uintptr_t)"Name Conflicts\n",
|
||||
g_ImportOverrideItems,
|
||||
NULL,
|
||||
MENUDIALOGFLAG_LITERAL_TEXT,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* common utils */
|
||||
|
||||
static s32 mpsetupDeserialize(FILE *f, struct mpsetupfile *setupfile)
|
||||
{
|
||||
s32 rx = 0;
|
||||
|
||||
rx += fread(&setupfile->version, sizeof(setupfile->version), 1, f);
|
||||
rx += fread(&setupfile->defaultsetup, sizeof(setupfile->defaultsetup), 1, f);
|
||||
rx += fread(&setupfile->numsetups, sizeof(setupfile->numsetups), 1, f);
|
||||
|
||||
for (int i = 0; i < setupfile->numsetups; ++i) {
|
||||
rx += fread(setupfile->setups[i].bytes, sizeof(setupfile->setups[i].bytes), 1, f);
|
||||
}
|
||||
|
||||
return rx;
|
||||
}
|
||||
|
||||
static s32 mpsetupSerialize(FILE *f, struct mpsetupfile *setupfile)
|
||||
{
|
||||
s32 wx = 0;
|
||||
|
||||
wx += fwrite(&setupfile->version, sizeof(setupfile->version), 1, f);
|
||||
wx += fwrite(&setupfile->defaultsetup, sizeof(setupfile->defaultsetup), 1, f);
|
||||
wx += fwrite(&setupfile->numsetups, sizeof(setupfile->numsetups), 1, f);
|
||||
|
||||
for (int i = 0; i < setupfile->numsetups; ++i) {
|
||||
wx += fwrite(setupfile->setups[i].bytes, sizeof(setupfile->setups[i].bytes), 1, f);
|
||||
}
|
||||
|
||||
return wx;
|
||||
}
|
||||
|
||||
static FILE *mpsetupOpenFile(bool write, u8 op) {
|
||||
const char *filename = fsFullPath("$S/" MPSETUP_FILENAME ".bin");
|
||||
|
||||
if (op == MPSETUP_OP_EXPORT) {
|
||||
// create export directory if it doesn't exist
|
||||
if (fsFileSize(MPSETUP_EXPORTDIR) < 0) {
|
||||
if (fsCreateDir(MPSETUP_EXPORTDIR) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
filename = fsFullPath(MPSETUP_EXPORTDIR MPSETUP_FILENAME_EXP ".bin");
|
||||
} else if (op == MPSETUP_OP_IMPORT) {
|
||||
// same name as export but different folder
|
||||
filename = fsFullPath("$S/" MPSETUP_FILENAME_EXP ".bin");
|
||||
}
|
||||
|
||||
FILE *f;
|
||||
|
||||
if (fsFileSize(filename) < 0) {
|
||||
// setup file doesn't exist: create one
|
||||
f = fsFileOpenWrite(filename);
|
||||
fsFileFree(f);
|
||||
}
|
||||
|
||||
if (write) {
|
||||
f = fsFileOpenWrite(filename);
|
||||
} else {
|
||||
f = fsFileOpenRead(filename);
|
||||
}
|
||||
|
||||
if (f == NULL) {
|
||||
sysLogPrintf(LOG_ERROR, "Unable to open mp setup file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static s32 mpsetupSaveFile(u8 op, struct mpsetupfile *setupfile)
|
||||
{
|
||||
FILE *f = mpsetupOpenFile(true, op);
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s32 nwritten = mpsetupSerialize(f, setupfile);
|
||||
if (nwritten < 1) {
|
||||
fsFileFree(f);
|
||||
sysLogPrintf(LOG_ERROR, "Unable to write the MP setup file");
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "Unable to write the setup file\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fsFileFree(f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 mpsetupLoadFile(struct mpsetupfile *setupfile, u8 op)
|
||||
{
|
||||
FILE *f = mpsetupOpenFile(false, op);
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mpsetupDeserialize(f, setupfile);
|
||||
|
||||
if (op == MPSETUP_OP_DEFAULT && setupfile->defaultsetup > 0) {
|
||||
mpsetupLoadSetup(setupfile->defaultsetup - 1);
|
||||
}
|
||||
|
||||
fsFileFree(f);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 mpsetupImportFile(u8 op, u8 skipOverlap)
|
||||
{
|
||||
if (!skipOverlap) {
|
||||
// check for names overlap
|
||||
u8 overlap = false;
|
||||
for (int i = 0; i < g_ImportMpSetupFile.numsetups; ++i) {
|
||||
for (int j = 0; j < g_MpSetupFile.numsetups; ++j) {
|
||||
if (strcmp(g_ImportMpSetupFile.setups[i].bytes, g_MpSetupFile.setups[j].bytes) == 0) {
|
||||
overlap = true;
|
||||
return MPSETUP_IMPORT_CONFLICT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_ImportMpSetupFile.numsetups; ++i) {
|
||||
s16 overlapIdx = -1;
|
||||
for (int j = g_MpSetupFile.numsetups-1; j >= 0; --j) {
|
||||
if (strcmp(g_ImportMpSetupFile.setups[i].bytes, g_MpSetupFile.setups[j].bytes) == 0) {
|
||||
overlapIdx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s16 importIdx = overlapIdx;
|
||||
if (overlapIdx < 0 || op == MPSETUP_IMPORT_ADD) {
|
||||
if (g_MpSetupFile.numsetups == MPSETUP_MAXSETUPS) {
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "Number of setups exceeds %d\n", MPSETUP_MAXSETUPS);
|
||||
return -1;
|
||||
}
|
||||
importIdx = g_MpSetupFile.numsetups++;
|
||||
}
|
||||
|
||||
memcpy(g_MpSetupFile.setups[importIdx].bytes, g_ImportMpSetupFile.setups[i].bytes, MPSETUP_BLOCKSIZE);
|
||||
}
|
||||
|
||||
return mpsetupSaveCurrentFile();
|
||||
}
|
||||
|
||||
static s32 mpsetupExportFile(void)
|
||||
{
|
||||
struct mpsetupfile expMpSetupFile;
|
||||
expMpSetupFile.numsetups = 0;
|
||||
expMpSetupFile.defaultsetup = 0;
|
||||
expMpSetupFile.version = MPSETUP_VERSION;
|
||||
|
||||
u8 maxsetups = MPSETUP_MAXSETUPS;
|
||||
maxsetups = MIN(maxsetups, g_MpSetupFile.numsetups);
|
||||
for (int i = 0; i < maxsetups; ++i) {
|
||||
u8 bank = i < 64 ? 0 : 1;
|
||||
u8 bit = i - bank * 64;
|
||||
if (g_MpImportExportFilter[bank] & (1 << bit)) {
|
||||
u8 n = expMpSetupFile.numsetups;
|
||||
expMpSetupFile.numsetups++;
|
||||
char *name = g_MpSetupFile.setups[i].bytes;
|
||||
memcpy(expMpSetupFile.setups[n].bytes, g_MpSetupFile.setups[i].bytes, MPSETUP_BLOCKSIZE);
|
||||
expMpSetupFile.numsetups = n + 1;
|
||||
}
|
||||
}
|
||||
|
||||
s32 err = mpsetupSaveFile(MPSETUP_OP_EXPORT, &expMpSetupFile);
|
||||
if (err) {
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "Unable to write\nsetup file\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static s32 mpsetupDelete(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
if (g_MpSetupFile.defaultsetup > slotindex + 1) {
|
||||
g_MpSetupFile.defaultsetup--;
|
||||
}
|
||||
else if (g_MpSetupFile.defaultsetup == slotindex + 1) {
|
||||
g_MpSetupFile.defaultsetup = 0;
|
||||
}
|
||||
|
||||
g_MpSetupFile.numsetups--;
|
||||
return mpsetupSaveCurrentFile();
|
||||
}
|
||||
|
||||
/* menu handlers */
|
||||
|
||||
// Rename setup dialog
|
||||
static 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;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETTEXT:
|
||||
strcpy(name, setup->bytes);
|
||||
break;
|
||||
case MENUOP_SETTEXT:
|
||||
strcpy(g_MpSetup.name, name);
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
strcpy(setup->bytes, name);
|
||||
err = mpsetupSaveSetup(slotindex, true);
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
} else {
|
||||
// TODO
|
||||
// menuPushDialog(&g_FilemgrFileSavedMenuDialog);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Delete setup dialog
|
||||
static MenuItemHandlerResult menuhandlerDeleteSetup(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
s32 err = mpsetupDelete();
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
menuPopDialog();
|
||||
} else {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Import (or Export) settings dialog
|
||||
static MenuItemHandlerResult menuhandlerImportOrExportSettings(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
static const char *labels[] = {
|
||||
"Select All",
|
||||
"Select None",
|
||||
"Import",
|
||||
"Export",
|
||||
};
|
||||
|
||||
s32 op = g_Menus[g_MpPlayerNum].mpsetup.unke24;
|
||||
|
||||
struct mpsetupfile *setupfile = op == MPSETUP_OP_IMPORT ? &g_ImportMpSetupFile : &g_MpSetupFile;
|
||||
|
||||
u8 numsetups = setupfile->numsetups;
|
||||
u8 numitems = numsetups + 3;
|
||||
u8 bank = data->list.value < 64 ? 0 : 1;
|
||||
u8 bit = data->list.value - bank * 64;
|
||||
u8 hasselection = (g_MpImportExportFilter[0] | g_MpImportExportFilter[1]) != 0;
|
||||
u8 ofs;
|
||||
s32 err;
|
||||
u32 colour;
|
||||
s32 index;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETCOLOUR:
|
||||
colour = data->list.unk04;
|
||||
if (data->list.value == numitems - 1) {
|
||||
data->list.unk04 = hasselection ? colour : (colour & 0xffffff00) | 0x66;
|
||||
}
|
||||
break;
|
||||
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->list.value = numitems;
|
||||
break;
|
||||
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
if (data->list.value < numsetups) {
|
||||
return (uintptr_t) setupfile->setups[data->list.value].bytes;
|
||||
} else {
|
||||
// creates an offset to select the "Export" or "Import" label for the last item
|
||||
ofs = (data->list.value == numitems - 1) ? op - 1 : 0;
|
||||
return (intptr_t)labels[data->list.value - numsetups + ofs];
|
||||
}
|
||||
|
||||
case MENUOP_SET:
|
||||
if (data->list.value < setupfile->numsetups) {
|
||||
g_MpImportExportFilter[bank] ^= (1 << bit);
|
||||
} else {
|
||||
index = data->list.value - setupfile->numsetups;
|
||||
|
||||
switch (index) {
|
||||
// Select All
|
||||
case 0:
|
||||
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = -1;
|
||||
break;
|
||||
// Select None
|
||||
case 1:
|
||||
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = 0;
|
||||
break;
|
||||
// Export (or Import)
|
||||
case 2:
|
||||
if (hasselection) {
|
||||
err = op == MPSETUP_OP_IMPORT ? mpsetupImportFile(0, false) : mpsetupExportFile();
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
if (op == MPSETUP_OP_IMPORT) {
|
||||
// back to the 'Manage Settings' screen
|
||||
menuPopDialog();
|
||||
menuPushDialog(&g_ManageSettingsDialog);
|
||||
} else {
|
||||
snprintf(g_StatusText, sizeof(g_StatusText), "File %s.bin\nwritten to the folder 'exported'\n", MPSETUP_FILENAME_EXP);
|
||||
menuPushDialog(&g_StatusOkDialog);
|
||||
}
|
||||
} else {
|
||||
if (err == MPSETUP_IMPORT_CONFLICT) {
|
||||
menuPopDialog();
|
||||
menuPushDialog(&g_ImportOverrideDialog);
|
||||
} else {
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->list.value = 0x000fffff;
|
||||
break;
|
||||
|
||||
case MENUOP_GETLISTITEMCHECKBOX:
|
||||
if (data->list.value < numsetups) {
|
||||
data->list.unk04 = (g_MpImportExportFilter[bank] & (1 << bit));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Import: overwrite dialog
|
||||
static MenuItemHandlerResult menuhandlerImportAction(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
s32 err = mpsetupImportFile(item->param, true);
|
||||
if (!err) {
|
||||
menuPopDialog();
|
||||
menuPushDialog(&g_ManageSettingsDialog);
|
||||
} else {
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Manage Import/Export settings dialog
|
||||
static MenuItemHandlerResult menuhandlerOpenImportExportDialog(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
switch (operation) {
|
||||
case MENUOP_SET:
|
||||
if (item->param == MPSETUP_OP_IMPORT) {
|
||||
strcpy(g_TitleImportExportDialog, "Import Settings\n");
|
||||
if (fsFileSize("$S/" MPSETUP_FILENAME_EXP ".bin") < 0) {
|
||||
snprintf(
|
||||
g_StatusText, sizeof(g_StatusText),
|
||||
"No import file found.\n"
|
||||
"Place the file %s.bin\n"
|
||||
"Next to your %s.bin file\n",
|
||||
MPSETUP_FILENAME_EXP, MPSETUP_FILENAME
|
||||
);
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
return 0;
|
||||
}
|
||||
|
||||
mpsetupLoadFile(&g_ImportMpSetupFile, MPSETUP_OP_IMPORT);
|
||||
} else {
|
||||
strcpy(g_TitleImportExportDialog, "Export Settings\n");
|
||||
}
|
||||
g_Menus[g_MpPlayerNum].mpsetup.unke24 = item->param;
|
||||
g_MpImportExportFilter[0] = g_MpImportExportFilter[1] = -1;
|
||||
menuPushDialog(&g_ImportExportDialog);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Manage settings dialog
|
||||
static MenuItemHandlerResult menuhandlerSelectSetupHandler(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
u32 colour;
|
||||
switch (operation) {
|
||||
case MENUOP_GETCOLOUR:
|
||||
colour = data->list.unk04;
|
||||
if (data->list.value + 1 == g_MpSetupFile.defaultsetup) {
|
||||
data->list.unk04 = (colour & 0xffff0000) | 0xff;
|
||||
}
|
||||
break;
|
||||
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;
|
||||
if (data->list.value == g_MpSetupFile.defaultsetup - 1) {
|
||||
strcpy(g_LabelSetDefault, "Clear Default\n");
|
||||
} else {
|
||||
strcpy(g_LabelSetDefault, "Set Default\n");
|
||||
}
|
||||
menuPushDialog(&g_ManageSetupDialog);
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
data->list.value = 0xfffff;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerSetupRename(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
menuPushDialog(&g_RenameSetupDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerSetupDelete(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
menuPushDialog(&g_DeleteSetupDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static MenuItemHandlerResult menuhandlerSetupSetDefault(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
s32 selected = g_Menus[g_MpPlayerNum].mpsetup.slotindex;
|
||||
// clicked on "clear default"
|
||||
if (selected == g_MpSetupFile.defaultsetup - 1) {
|
||||
g_MpSetupFile.defaultsetup = -1;
|
||||
strcpy(g_LabelSetDefault, "Set Default\n");
|
||||
} else {
|
||||
g_MpSetupFile.defaultsetup = selected + 1;
|
||||
strcpy(g_LabelSetDefault, "Clear Default\n");
|
||||
}
|
||||
|
||||
mpsetupSaveCurrentFile();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* public functions */
|
||||
|
||||
s32 mpsetupLoadCurrentFile(void)
|
||||
{
|
||||
return mpsetupLoadFile(&g_MpSetupFile, MPSETUP_OP_DEFAULT);
|
||||
}
|
||||
|
||||
s32 mpsetupSaveCurrentFile(void)
|
||||
{
|
||||
g_MpSetupFile.version = MPSETUP_VERSION;
|
||||
return mpsetupSaveFile(MPSETUP_OP_DEFAULT, &g_MpSetupFile);
|
||||
}
|
||||
|
||||
s32 mpsetupSaveSetup(s32 slotindex, u8 savefile)
|
||||
{
|
||||
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 savefile ? mpsetupSaveCurrentFile() : 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_MpSetupFile.version);
|
||||
g_MpCurrentSetup = index;
|
||||
}
|
||||
|
||||
void mpsetupCopyAllFromPak(void)
|
||||
{
|
||||
if (fsFileSize("$S/" MPSETUP_FILENAME ".bin") > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
filelistCreate(1, FILETYPE_MPSETUP);
|
||||
filelistsTick();
|
||||
|
||||
for (int i = 0; i < g_FileLists[1]->numfiles; ++i) {
|
||||
struct savebuffer buffer;
|
||||
savebufferClear(&buffer);
|
||||
struct filelistfile *file = &g_FileLists[1]->files[i];
|
||||
s32 device = pakFindBySerial(file->deviceserial);
|
||||
s32 err = pakReadBodyAtGuid(device, file->fileid, buffer.bytes, 0);
|
||||
|
||||
if (err != 0) {
|
||||
sysLogPrintf(LOG_ERROR, "Unable to read pak. device %d fileid %d deviceserial %d err %d",
|
||||
device, file->fileid, file->deviceserial, err);
|
||||
continue;
|
||||
}
|
||||
|
||||
mpsetupfileLoadWad(&buffer, 0);
|
||||
|
||||
// save the file when writing the last setup
|
||||
u8 savefile = i == g_FileLists[1]->numfiles - 1;
|
||||
mpsetupSaveSetup(g_MpSetupFile.numsetups, savefile);
|
||||
}
|
||||
|
||||
// to reset the mp setup
|
||||
mpInit(false);
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "game/menu.h"
|
||||
#include "game/gamefile.h"
|
||||
#include "game/player.h"
|
||||
#include "lib/joy.h"
|
||||
#include "video.h"
|
||||
#include "input.h"
|
||||
#include "config.h"
|
||||
@@ -597,8 +598,10 @@ static MenuItemHandlerResult menuhandlerController(s32 operation, struct menuite
|
||||
if (data->dropdown.value == 0) {
|
||||
// unassign controller
|
||||
inputAssignController(g_ExtMenuPlayer, -1);
|
||||
joyReset();
|
||||
} else if (data->dropdown.value <= numCtrls) {
|
||||
inputAssignController(g_ExtMenuPlayer, ctrls[data->dropdown.value - 1]);
|
||||
joyReset();
|
||||
}
|
||||
break;
|
||||
case MENUOP_GETSELECTEDINDEX:
|
||||
|
||||
+1
-1
@@ -259,7 +259,7 @@ void mainInit(void)
|
||||
frametimeInit();
|
||||
profileInit();
|
||||
smokesInit();
|
||||
mpInit();
|
||||
mpInit(true);
|
||||
pheadInit();
|
||||
paksInit();
|
||||
pheadInit2();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
#include "game/game_0b2150.h"
|
||||
#include "game/tex.h"
|
||||
#include "game/sky.h"
|
||||
#include "game/game_13c510.h"
|
||||
#include "game/artifact.h"
|
||||
#include "game/bg.h"
|
||||
#include "game/stagetable.h"
|
||||
#include "game/room.h"
|
||||
@@ -23,6 +23,70 @@
|
||||
#include "game/prop.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Artifacts are points of interest in the z-buffer.
|
||||
*
|
||||
* They correspond to:
|
||||
* - Individual circles in the lens flare effect from the sun.
|
||||
* - Individual corners of each light fixture's box.
|
||||
*
|
||||
* The game needs to do line of sight checks to these points. The collision
|
||||
* system would normally be used for line of sight checks, but it only works
|
||||
* with basic geometric volumes and also doesn't take into account the player's
|
||||
* gun. Instead, the checks are done by reading from the previous frame's
|
||||
* z-buffer.
|
||||
*
|
||||
* Typically, the z-buffer would be read by the scheduler after a graphics frame
|
||||
* is rendered, but this only works if the z-buffer is a complete image.
|
||||
* PD draws the scene, then clears the z-buffer before drawing the player's gun,
|
||||
* so the z-buffer at the end only contains the player's gun. To work around
|
||||
* this, the GPU is given commands to read the z-buffer as a texture and copy
|
||||
* depth values to a safe place before clearing it. Then once the frame is
|
||||
* rendered, the scheduler compares the saved depths with the current z-buffer
|
||||
* and updates the artifact, applying the minimum of the two depths.
|
||||
*
|
||||
* The scheduler maintains 3 arrays of artifacts, each referenced by indexes
|
||||
* which rotate between them.
|
||||
* - Artifacts are written by the main thread using the write index.
|
||||
* The write and front indexes are then incremented.
|
||||
* - The same artifacts are updated by the scheduler using the pending index.
|
||||
* The pending index is then updated.
|
||||
* - The artifacts are then rendered on a later frame using the front index.
|
||||
*
|
||||
* In each artifacts array, the first several slots are reserved for the sun
|
||||
* flare artifacts. The quantity depends on the number of suns in the stage
|
||||
* (Skedar Ruins has 3) and there are 8 artifacts per sun. The remaining slots
|
||||
* are used for light fixture corners. The array is big enough to handle at
|
||||
* least 90 lights on screen at a time.
|
||||
*
|
||||
* The initial state of the indexes are write=0, front=1, pending=0.
|
||||
* These are set in sched_reset_artifacts.
|
||||
*
|
||||
* The detailed workflow is:
|
||||
* - CPU: Light artifacts are determined and added to write artifacts (0) array
|
||||
* - CPU: Constructs the gdl in this order:
|
||||
* - Render scene
|
||||
* - Copy relevant parts of z-buffer to write depths (0) array
|
||||
* - Clear z-buffer and render gun
|
||||
* - Render artifacts by reading from front artifacts (1) array
|
||||
* - CPU: increments write (0 -> 1) and front (1 -> 2) indexes
|
||||
* - GPU: Executes above task. g_ArtifactDepths0 now contains depths, and is
|
||||
* pointed to by pending.
|
||||
* - Scheduler: Reads the z-buffer, which at this point only contains the gun
|
||||
* depth information, and updates the artifact with the minimum of the two
|
||||
* - Scheduler: Increments pending (0 -> 1)
|
||||
*
|
||||
* It appears that the front index should be initialised to 2 instead, so that
|
||||
* it's one frame behind the others rather than two frames behind.
|
||||
*
|
||||
* There's no doubt this went through several iterations before landing on this
|
||||
* implementation. It's likely that this was implemented using a single and full
|
||||
* z-buffer and it worked well until they decided to clear the z-buffer before
|
||||
* rendering the gun. There is evidence in zbuf.c that they allocated a second
|
||||
* z-buffer and swapped it. But when memory got too tight they had to change it
|
||||
* to this texture read method.
|
||||
*/
|
||||
|
||||
u8 *var800a41a0;
|
||||
u32 var800a41a4;
|
||||
u32 var800a41a8;
|
||||
@@ -44,11 +108,25 @@ void artifactsTick(void)
|
||||
schedIncrementFrontArtifacts();
|
||||
}
|
||||
|
||||
u16 func0f13c574(f32 arg0)
|
||||
u16 floatToN64Depth(f32 arg0)
|
||||
{
|
||||
/**
|
||||
* Method to convert a 32 bit floating point depth value to the
|
||||
* unsigned 16 bit integer format used by the zbuffer on the N64.
|
||||
* The argument arg0 represents z normalized to [0, 1] * 32704.0f.
|
||||
*
|
||||
* It works by converting the depth value to a large, unsigned 32 bit
|
||||
* integer before scaling back down to an unsigned 16 bit integer.
|
||||
* The scaling is done using bit shift operations on the most & least
|
||||
* significant bytes of the resulting 16 bit integer, likely because
|
||||
* bit shift operations are faster than division. The segmentation of
|
||||
* this calculation at values 0x3f800, 0x3f000, etc. is probably
|
||||
* intended to reduce z-fighting by adding more differentiation for
|
||||
* distant z values.
|
||||
*/
|
||||
u32 value = arg0 * 8.0f;
|
||||
u32 left;
|
||||
u32 right = value;
|
||||
u32 left; // forms the most significant byte of the final u16
|
||||
u32 right = value; // forms the least significant byte of the final u16
|
||||
|
||||
if (value > 0x3f800) {
|
||||
right = value & 0x7ff;
|
||||
@@ -87,7 +165,7 @@ u16 func0f13c574(f32 arg0)
|
||||
return left << 13 | (right << 2);
|
||||
}
|
||||
|
||||
s32 func0f13c710(f32 arg0)
|
||||
s32 artifactsFloatToInt(f32 arg0)
|
||||
{
|
||||
if (arg0 > 0.0f) {
|
||||
if (arg0 > 2147483520.0f) {
|
||||
@@ -232,8 +310,8 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
|
||||
|
||||
if (spdc[3] > 0.0001f) {
|
||||
f20 = 1.0f / spdc[3];
|
||||
x = func0f13c710(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
|
||||
y = func0f13c710(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
|
||||
x = artifactsFloatToInt(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
|
||||
y = artifactsFloatToInt(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
|
||||
f0 = (spdc[2] * f20 * 511.0f + 511.0f) * 32.0f;
|
||||
|
||||
if (f0 < 32576.0f) {
|
||||
@@ -335,8 +413,8 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
|
||||
f20 = -9999.0f;
|
||||
}
|
||||
|
||||
xi = func0f13c710(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
|
||||
yi = func0f13c710(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
|
||||
xi = artifactsFloatToInt(viewleft + (1.0f + spdc[0] * f20) * (viewwidth * 0.5f));
|
||||
yi = artifactsFloatToInt(viewtop + (1.0f - spdc[1] * f20) * (viewheight * 0.5f));
|
||||
f0 = (spdc[2] * f20 * 511.0f + 511.0f) * 32.0f;
|
||||
|
||||
if (g_ZbufPtr1
|
||||
@@ -357,14 +435,20 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
|
||||
|
||||
if (index < MAX_ARTIFACTS) {
|
||||
#ifndef PLATFORM_N64
|
||||
artifact->unk02 = artifactTestLos(&spec, &g_BgRooms[roomnum].pos, xi, yi);
|
||||
artifact->visiblelos = artifactTestLos(&spec, &g_BgRooms[roomnum].pos, xi, yi);
|
||||
#endif
|
||||
artifact->unk04 = func0f13c574(f0) >> 2;
|
||||
artifact->unk08 = &g_ZbufPtr1[viGetWidth() * yi + xi];
|
||||
/**
|
||||
* the original game performs artifact depth comparison
|
||||
* using the N64 depth values divided by 4. This is
|
||||
* accomplished by bit shifting the N64 depth value
|
||||
* to the right using >> 2
|
||||
*/
|
||||
artifact->expecteddepth = floatToN64Depth(f0) >> 2;
|
||||
artifact->zbufptr = &g_ZbufPtr1[viGetWidth() * yi + xi];
|
||||
artifact->light = &roomlights[i];
|
||||
artifact->type = ARTIFACTTYPE_GLARE;
|
||||
artifact->unk0c.u16_2 = xi;
|
||||
artifact->unk0c.u16_1 = yi;
|
||||
artifact->screenx = xi;
|
||||
artifact->screeny = yi;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -375,7 +459,7 @@ void artifactsCalculateGlaresForRoom(s32 roomnum)
|
||||
}
|
||||
}
|
||||
|
||||
u8 func0f13d3c4(u8 arg0, u8 arg1)
|
||||
u8 artifactsClamp(u8 arg0, u8 arg1)
|
||||
{
|
||||
if (arg1 >= arg0 + 7) {
|
||||
return arg0 + 7;
|
||||
@@ -423,18 +507,18 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
|
||||
u16 min;
|
||||
u16 max;
|
||||
f32 lightop_cur_frac;
|
||||
s32 t2;
|
||||
s32 numgood;
|
||||
struct light *light;
|
||||
u8 *s3;
|
||||
s32 k;
|
||||
s32 count;
|
||||
u16 t4;
|
||||
u16 actualdepth;
|
||||
f32 add;
|
||||
s32 l;
|
||||
f32 brightness;
|
||||
s32 avg;
|
||||
s32 tolerance;
|
||||
f32 f0;
|
||||
s32 v1;
|
||||
s32 difference;
|
||||
s32 r;
|
||||
s32 g;
|
||||
s32 b;
|
||||
@@ -460,6 +544,12 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
|
||||
struct light *light2 = artifacts[i].light;
|
||||
count = 0;
|
||||
|
||||
/**
|
||||
* light arifacts are created from several, closely spaced
|
||||
* textures that give the appearance of a dynamic light glare
|
||||
* as the character moves. Loop to count all the sub-artifacts
|
||||
* in this light.
|
||||
*/
|
||||
for (j = i; j < MAX_ARTIFACTS && artifacts[j].type == ARTIFACTTYPE_GLARE && artifacts[j].light == light2; j++) {
|
||||
count++;
|
||||
}
|
||||
@@ -470,51 +560,65 @@ Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum)
|
||||
if (roomnum == light->roomnum) {
|
||||
lightindex = ((uintptr_t)light - (uintptr_t)g_BgLightsFileData) / sizeof(struct light);
|
||||
s3 = &var800a41a0[lightindex * 3];
|
||||
t2 = 0;
|
||||
numgood = 0;
|
||||
min = 0xffff;
|
||||
max = 0;
|
||||
|
||||
/**
|
||||
* loop to determine the min & max depth of
|
||||
* the sub-artifacts composing this room light.
|
||||
*/
|
||||
for (k = i; k < i + count; k++) {
|
||||
if (artifacts[k].unk04 > max) {
|
||||
max = artifacts[k].unk04;
|
||||
if (artifacts[k].expecteddepth > max) {
|
||||
max = artifacts[k].expecteddepth;
|
||||
}
|
||||
|
||||
if (artifacts[k].unk04 < min) {
|
||||
min = artifacts[k].unk04;
|
||||
if (artifacts[k].expecteddepth < min) {
|
||||
min = artifacts[k].expecteddepth;
|
||||
}
|
||||
}
|
||||
|
||||
avg = (max - min) >> 1;
|
||||
/**
|
||||
* Define a depth tolerance from the min & max
|
||||
* depths of sub-artifacts for a given light.
|
||||
* This will be used to determine which light
|
||||
* artifacts are visible when comparing depth
|
||||
* values of lights to other items rendered
|
||||
* on screen. Without this, the lights would
|
||||
* constantly flicker due to z-fighting caused
|
||||
* by the low precision of the N64 depth.
|
||||
*/
|
||||
tolerance = (max - min) >> 1;
|
||||
|
||||
if (avg < 25) {
|
||||
avg = 25;
|
||||
if (tolerance < 25) {
|
||||
tolerance = 25;
|
||||
}
|
||||
|
||||
for (k = i; k < i + count; k++) {
|
||||
#ifdef PLATFORM_N64
|
||||
u16 tmp;
|
||||
t4 = (artifacts[k].unk02 & 0xfffc) >> 2;
|
||||
tmp = artifacts[k].unk04;
|
||||
u16 expecteddepth;
|
||||
actualdepth = (artifacts[k].actualdepth & 0xfffc) >> 2;
|
||||
expecteddepth = artifacts[k].expecteddepth;
|
||||
|
||||
if (tmp < t4) {
|
||||
v1 = t4 - tmp;
|
||||
if (expecteddepth < actualdepth) {
|
||||
difference = actualdepth - expecteddepth;
|
||||
} else {
|
||||
v1 = tmp - t4;
|
||||
difference = expecteddepth - actualdepth;
|
||||
}
|
||||
|
||||
if (avg >= v1) {
|
||||
t2++;
|
||||
if (difference <= tolerance) {
|
||||
numgood++;
|
||||
}
|
||||
#else
|
||||
t2 += artifacts[k].unk02;
|
||||
numgood += artifacts[k].visiblelos;
|
||||
#endif
|
||||
|
||||
artifacts[k].type = ARTIFACTTYPE_FREE;
|
||||
}
|
||||
|
||||
s3[0] = func0f13d3c4(s3[0], t2 * 2);
|
||||
s3[0] = artifactsClamp(s3[0], numgood * 2);
|
||||
|
||||
if (t2 > 0) {
|
||||
if (numgood > 0) {
|
||||
brightness = viGetFovY() * 0.017453292f;
|
||||
add = cosf(brightness) / sinf(brightness) * 14.6f;
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
#include "game/sky.h"
|
||||
#include "game/stars.h"
|
||||
#include "game/dyntex.h"
|
||||
#include "game/game_13c510.h"
|
||||
#include "game/artifact.h"
|
||||
#include "game/game_1531a0.h"
|
||||
#include "game/gfxmemory.h"
|
||||
#include "game/gfxreplace.h"
|
||||
|
||||
+4
-4
@@ -8477,7 +8477,7 @@ glabel var7f1aca90
|
||||
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
|
||||
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
|
||||
.L0f0a71ec:
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufDrawArtifactsOffscreen
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufSaveArtifactDepths
|
||||
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
|
||||
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
|
||||
/* f0a71f8: 0c002ca0 */ jal viPrepareZbuf
|
||||
@@ -9318,7 +9318,7 @@ glabel var7f1aca90
|
||||
/* f0a71e4: 100002d5 */ b .L0f0a7d3c
|
||||
/* f0a71e8: 8fbf0034 */ lw $ra,0x34($sp)
|
||||
.L0f0a71ec:
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufDrawArtifactsOffscreen
|
||||
/* f0a71ec: 0fc5d9ad */ jal zbufSaveArtifactDepths
|
||||
/* f0a71f0: 8fa4014c */ lw $a0,0x14c($sp)
|
||||
/* f0a71f4: afa2014c */ sw $v0,0x14c($sp)
|
||||
/* f0a71f8: 0c002ca0 */ jal viPrepareZbuf
|
||||
@@ -10159,7 +10159,7 @@ glabel var7f1aca90
|
||||
/* f0a4f30: 100002cd */ beqz $zero,.NB0f0a5a68
|
||||
/* f0a4f34: 8fbf0034 */ lw $ra,0x34($sp)
|
||||
.NB0f0a4f38:
|
||||
/* f0a4f38: 0fc5c4d5 */ jal zbufDrawArtifactsOffscreen
|
||||
/* f0a4f38: 0fc5c4d5 */ jal zbufSaveArtifactDepths
|
||||
/* f0a4f3c: 8fa40144 */ lw $a0,0x144($sp)
|
||||
/* f0a4f40: afa20144 */ sw $v0,0x144($sp)
|
||||
/* f0a4f44: 0c002d00 */ jal viPrepareZbuf
|
||||
@@ -10957,7 +10957,7 @@ void bgunRender(Gfx **gdlptr)
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_N64 // TODO
|
||||
gdl = zbufDrawArtifactsOffscreen(gdl);
|
||||
gdl = zbufSaveArtifactDepths(gdl);
|
||||
#endif
|
||||
gdl = viPrepareZbuf(gdl);
|
||||
gdl = vi0000b1d0(gdl);
|
||||
|
||||
+1
-5
@@ -138,8 +138,6 @@ void bossfileLoad(void)
|
||||
g_BossFile.usingmultipletunes = savebufferReadBits(&buffer, 1);
|
||||
g_AltTitleUnlocked = savebufferReadBits(&buffer, 1);
|
||||
g_AltTitleEnabled = savebufferReadBits(&buffer, 1);
|
||||
|
||||
func0f0d54c4(&buffer);
|
||||
}
|
||||
|
||||
if (failed) {
|
||||
@@ -168,7 +166,7 @@ void bossfileSave(void)
|
||||
savebufferOr(&buffer, g_Vars.language, 4);
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_BossFile.teamnames); i++) {
|
||||
func0f0d55a4(&buffer, g_BossFile.teamnames[i]);
|
||||
savebufferWriteString(&buffer, g_BossFile.teamnames[i]);
|
||||
}
|
||||
|
||||
if (g_BossFile.tracknum == -1) {
|
||||
@@ -185,8 +183,6 @@ void bossfileSave(void)
|
||||
savebufferOr(&buffer, g_AltTitleUnlocked, 1);
|
||||
savebufferOr(&buffer, g_AltTitleEnabled, 1);
|
||||
|
||||
func0f0d54c4(&buffer);
|
||||
|
||||
fileid = bossfileFindFileId();
|
||||
|
||||
if (fileid == 0) {
|
||||
|
||||
@@ -400,6 +400,8 @@ struct mpconfigfull *challengeLoadConfig(s32 confignum, u8 *buffer, s32 len)
|
||||
extern struct mpstrings EXT_SEG _mpstringsSSegmentRomEnd;
|
||||
extern struct mpstrings EXT_SEG _mpstringsISegmentRomEnd;
|
||||
|
||||
extern struct mpconfig g_MpConfigs[];
|
||||
|
||||
BTYPE banks[][2] = {
|
||||
{ (BTYPE)REF_SEG _mpstringsESegmentRomStart, (BTYPE)REF_SEG _mpstringsESegmentRomEnd },
|
||||
{ (BTYPE)REF_SEG _mpstringsJSegmentRomStart, (BTYPE)REF_SEG _mpstringsJSegmentRomEnd },
|
||||
@@ -421,6 +423,7 @@ struct mpconfigfull *challengeLoadConfig(s32 confignum, u8 *buffer, s32 len)
|
||||
bank = banks[language_id][0];
|
||||
loadedstrings = dmaExecWithAutoAlign(buffer2, bank + confignum * sizeof(struct mpstrings), sizeof(struct mpstrings));
|
||||
|
||||
mpconfig->config = g_MpConfigs[confignum];
|
||||
mpconfig->strings = *loadedstrings;
|
||||
|
||||
return mpconfig;
|
||||
|
||||
+1
-33
@@ -499,11 +499,6 @@ char *filemgrMenuTextFileType(struct menuitem *item)
|
||||
case FILEOP_LOAD_GAME:
|
||||
case FILEOP_READ_GAME:
|
||||
return langGet(names[0]);
|
||||
case FILEOP_SAVE_MPSETUP:
|
||||
case FILEOP_WRITE_MPSETUP:
|
||||
case FILEOP_LOAD_MPSETUP:
|
||||
case FILEOP_READ_MPSETUP:
|
||||
return langGet(names[1]);
|
||||
case FILEOP_SAVE_MPPLAYER:
|
||||
case FILEOP_WRITE_MPPLAYER:
|
||||
case FILEOP_LOAD_MPPLAYER:
|
||||
@@ -816,12 +811,6 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess)
|
||||
g_Menus[g_MpPlayerNum].fm.fileid,
|
||||
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
||||
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_MPSETUP:
|
||||
case FILEOP_WRITE_MPPLAYER:
|
||||
@@ -845,11 +834,6 @@ bool filemgrAttemptOperation(s32 device, bool closeonsuccess)
|
||||
g_Menus[g_MpPlayerNum].fm.fileid,
|
||||
g_Menus[g_MpPlayerNum].fm.deviceserial);
|
||||
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_MPSETUP:
|
||||
case FILEOP_READ_MPPLAYER:
|
||||
@@ -2780,7 +2764,7 @@ MenuDialogHandlerResult filemgrMainMenuDialog(s32 operation, struct menudialogde
|
||||
g_Menus[g_MpPlayerNum].fm.filetypeplusone = 0;
|
||||
|
||||
filelistCreate(0, FILETYPE_GAME);
|
||||
mpInit();
|
||||
mpInit(true);
|
||||
|
||||
// Set MP player names to "Player 1" through 4 if blank
|
||||
for (i = 0; i < MAX_PLAYERS; i++) {
|
||||
@@ -3307,14 +3291,6 @@ struct menuitem g_FilemgrOperationsMenuItems[] = {
|
||||
0,
|
||||
filemgrOpenCopyFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
FILETYPE_MPSETUP,
|
||||
0,
|
||||
L_OPTIONS_104, // "Combat Simulator Settings File"
|
||||
0,
|
||||
filemgrOpenCopyFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
FILETYPE_MPPLAYER,
|
||||
@@ -3347,14 +3323,6 @@ struct menuitem g_FilemgrOperationsMenuItems[] = {
|
||||
0,
|
||||
filemgrOpenDeleteFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
FILETYPE_MPSETUP,
|
||||
0,
|
||||
L_OPTIONS_104, // "Combat Simulator Settings File"
|
||||
0,
|
||||
filemgrOpenDeleteFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
FILETYPE_MPPLAYER,
|
||||
|
||||
@@ -133,14 +133,6 @@ struct menuitem g_GameFiles4MbMenuItems[] = {
|
||||
0,
|
||||
filemgrOpenCopyFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
1,
|
||||
0,
|
||||
L_OPTIONS_104, // "Combat Simulator Settings File"
|
||||
0,
|
||||
filemgrOpenCopyFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
2,
|
||||
@@ -173,14 +165,6 @@ struct menuitem g_GameFiles4MbMenuItems[] = {
|
||||
0,
|
||||
filemgrOpenDeleteFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
1,
|
||||
0,
|
||||
L_OPTIONS_104, // "Combat Simulator Settings File"
|
||||
0,
|
||||
filemgrOpenDeleteFileMenuHandler,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
2,
|
||||
|
||||
+1
-5
@@ -395,8 +395,6 @@ s32 gamefileLoad(s32 device)
|
||||
frSetWeaponFound(WEAPON_REMOTEMINE);
|
||||
}
|
||||
#endif
|
||||
|
||||
func0f0d54c4(&buffer);
|
||||
gamefileApplyOptions(&g_GameFile);
|
||||
|
||||
return 0;
|
||||
@@ -499,7 +497,7 @@ s32 gamefileSave(s32 device, s32 fileid, u16 deviceserial)
|
||||
|
||||
if (device >= 0) {
|
||||
savebufferClear(&buffer);
|
||||
func0f0d55a4(&buffer, g_GameFile.name);
|
||||
savebufferWriteString(&buffer, g_GameFile.name);
|
||||
|
||||
savebufferOr(&buffer, g_GameFile.thumbnail, 5);
|
||||
savebufferOr(&buffer, g_GameFile.totaltime, 32);
|
||||
@@ -556,8 +554,6 @@ s32 gamefileSave(s32 device, s32 fileid, u16 deviceserial)
|
||||
savebufferOr(&buffer, g_GameFile.weaponsfound[i], 8);
|
||||
}
|
||||
|
||||
func0f0d54c4(&buffer);
|
||||
|
||||
ret = pakSaveAtGuid(device, fileid, PAKFILETYPE_GAME, buffer.bytes, &newfileid, 0);
|
||||
g_FilemgrLastPakError = ret;
|
||||
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@
|
||||
#include "game/portal.h"
|
||||
#include "game/fmb.h"
|
||||
#include "game/sky.h"
|
||||
#include "game/game_13c510.h"
|
||||
#include "game/artifact.h"
|
||||
#include "game/game_1531a0.h"
|
||||
#include "game/zbuf.h"
|
||||
#include "game/challenge.h"
|
||||
|
||||
+33
-6
@@ -147,6 +147,33 @@ s32 g_MouseDimmedMode = false;
|
||||
s32 g_MouseEndDeferredSlider = false;
|
||||
#endif
|
||||
|
||||
s32 menuAlt1Pressed(s32 playerNum)
|
||||
{
|
||||
const s32 rshoulderKey = VK_JOY1_RSHOULDER + playerNum * INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
|
||||
if (playerNum == 0) {
|
||||
return inputKeyJustPressed(VK_LCTRL) || inputKeyJustPressed(rshoulderKey);
|
||||
}
|
||||
|
||||
return inputKeyJustPressed(rshoulderKey);
|
||||
}
|
||||
|
||||
s32 menuAlt2Pressed(s32 playerNum)
|
||||
{
|
||||
const s32 lshoulderKey = VK_JOY1_LSHOULDER + playerNum * INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
|
||||
if (playerNum == 0) {
|
||||
return inputKeyJustPressed(VK_LALT) || inputKeyJustPressed(lshoulderKey);
|
||||
}
|
||||
|
||||
return inputKeyJustPressed(lshoulderKey);
|
||||
}
|
||||
|
||||
s32 menuAltAnyPressed(s32 playerNum)
|
||||
{
|
||||
return menuAlt1Pressed(playerNum) || menuAlt2Pressed(playerNum);
|
||||
}
|
||||
|
||||
void menuPlaySound(s32 menusound)
|
||||
{
|
||||
s32 sound = -1;
|
||||
@@ -3581,8 +3608,8 @@ void func0f0f820c(struct menudialogdef *dialogdef, s32 root)
|
||||
|
||||
g_MpPlayerNum = prevplayernum;
|
||||
|
||||
g_MenuData.unk008 = root;
|
||||
g_MenuData.unk00c = dialogdef;
|
||||
g_MenuData.prevmenuroot = root;
|
||||
g_MenuData.prevmenudialog = dialogdef;
|
||||
}
|
||||
|
||||
void menuSetBackground(s32 bg)
|
||||
@@ -3656,7 +3683,7 @@ void menuPushRootDialog(struct menudialogdef *dialogdef, s32 root)
|
||||
g_Menus[g_MpPlayerNum].unk820 = 1;
|
||||
|
||||
g_MenuData.root = root;
|
||||
g_MenuData.unk008 = -1;
|
||||
g_MenuData.prevmenuroot = -1;
|
||||
g_MenuData.unk5d5_02 = false;
|
||||
|
||||
if (root == MENUROOT_MAINMENU
|
||||
@@ -3978,13 +4005,13 @@ void menuReset(void)
|
||||
}
|
||||
|
||||
g_MenuData.unk668 = -1;
|
||||
g_MenuData.unk00c = 0;
|
||||
g_MenuData.unk008 = -1;
|
||||
g_MenuData.prevmenudialog = 0;
|
||||
g_MenuData.prevmenuroot = -1;
|
||||
g_MenuData.count = 0;
|
||||
g_MenuData.root = 0;
|
||||
g_MenuData.unk010 = 0;
|
||||
g_MenuData.bg = 0;
|
||||
g_MenuData.unk5d5_06 = false;
|
||||
g_MenuData.isdialogopen = false;
|
||||
g_MenuData.nextbg = 255;
|
||||
g_MenuData.bannernum = -1;
|
||||
|
||||
|
||||
+13
-3
@@ -614,6 +614,15 @@ Gfx *menuitemListRender(Gfx *gdl, struct menurendercontext *context)
|
||||
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);
|
||||
|
||||
// Consider a checkbox
|
||||
@@ -1520,6 +1529,7 @@ bool menuitemKeyboardTick(struct menuitem *item, struct menuinputs *inputs, u32
|
||||
inputs->start = false;
|
||||
}
|
||||
|
||||
u8 maxlen = item->param == 0 ? 10 : item->param;
|
||||
#ifndef PLATFORM_N64
|
||||
if (g_MenuKeyboardPlayer == g_MpPlayerNum) {
|
||||
// match caps state to keyboard shift/caps if typing with keyboard
|
||||
@@ -1531,7 +1541,7 @@ bool menuitemKeyboardTick(struct menuitem *item, struct menuinputs *inputs, u32
|
||||
// handle text input
|
||||
s32 prevpos = strlen(kb->string);
|
||||
s32 pos = prevpos;
|
||||
s32 result = inputTextHandler(kb->string, sizeof(kb->string), &pos, true);
|
||||
s32 result = inputTextHandler(kb->string, maxlen-1, &pos, true);
|
||||
if (result == -1) {
|
||||
// cancel
|
||||
kb->row = 5;
|
||||
@@ -1608,7 +1618,7 @@ bool menuitemKeyboardTick(struct menuitem *item, struct menuinputs *inputs, u32
|
||||
s32 textwidth;
|
||||
s32 textheight;
|
||||
|
||||
if (kb->string[9] == '\0') {
|
||||
if (kb->string[maxlen-1] == '\0') {
|
||||
// String is not full
|
||||
i = 0;
|
||||
|
||||
@@ -1644,7 +1654,7 @@ bool menuitemKeyboardTick(struct menuitem *item, struct menuinputs *inputs, u32
|
||||
// Handle deleting
|
||||
if (delete && kb->string[0] != '\0') {
|
||||
s32 deleted = false;
|
||||
s32 i = 10;
|
||||
s32 i = maxlen;
|
||||
|
||||
menuPlaySound(MENUSOUND_FOCUS);
|
||||
|
||||
|
||||
+25
-26
@@ -59,7 +59,7 @@ void menuTick(void)
|
||||
s32 i;
|
||||
s32 j;
|
||||
s32 k;
|
||||
s32 sp344;
|
||||
s32 isdialogopen;
|
||||
s32 sp340 = true;
|
||||
s32 anyopen = false;
|
||||
|
||||
@@ -285,7 +285,7 @@ void menuTick(void)
|
||||
var8006294c = 1;
|
||||
|
||||
if (g_MenuData.root == MENUROOT_MPSETUP || g_MenuData.root == MENUROOT_4MBMAINMENU) {
|
||||
if (g_MenuData.unk008 == -1) {
|
||||
if (g_MenuData.prevmenuroot == -1) {
|
||||
g_MpSetup.chrslots &= 0xfff0;
|
||||
}
|
||||
|
||||
@@ -295,7 +295,7 @@ void menuTick(void)
|
||||
if (g_Menus[i].curdialog) {
|
||||
g_Menus[i].playernum = g_MpNumJoined++;
|
||||
|
||||
if (g_MenuData.unk008 == -1) {
|
||||
if (g_MenuData.prevmenuroot == -1) {
|
||||
g_MpSetup.chrslots |= (1 << i);
|
||||
}
|
||||
}
|
||||
@@ -473,7 +473,6 @@ void menuTick(void)
|
||||
(g_MenuData.root == MENUROOT_MPSETUP || g_MenuData.root == MENUROOT_4MBMAINMENU)) {
|
||||
var80062948 = 1;
|
||||
filelistCreate(0, FILETYPE_MPPLAYER);
|
||||
filelistCreate(1, FILETYPE_MPSETUP);
|
||||
}
|
||||
|
||||
if (var80062944) {
|
||||
@@ -486,31 +485,31 @@ void menuTick(void)
|
||||
}
|
||||
|
||||
g_MpPlayerNum = 0;
|
||||
sp344 = false;
|
||||
isdialogopen = false;
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_Menus); i++) {
|
||||
if (g_Menus[i].curdialog) {
|
||||
sp344 = true;
|
||||
isdialogopen = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((g_MenuData.unk5d5_06 || g_MenuData.unk008 != -1) && sp344 == false) {
|
||||
if ((g_MenuData.isdialogopen || g_MenuData.prevmenuroot != -1) && isdialogopen == false) {
|
||||
if ((g_MenuData.root == MENUROOT_MPSETUP || g_MenuData.root == MENUROOT_4MBMAINMENU)
|
||||
&& g_MenuData.unk008 == -1) {
|
||||
&& g_MenuData.prevmenuroot == -1) {
|
||||
if (g_Vars.mpsetupmenu == MPSETUPMENU_GENERAL) {
|
||||
g_MenuData.unk008 = MENUROOT_MAINMENU;
|
||||
g_MenuData.unk00c = IS4MB() ? &g_CiMenuViaPauseMenuDialog : &g_CiMenuViaPcMenuDialog;
|
||||
g_MenuData.prevmenuroot = MENUROOT_MAINMENU;
|
||||
g_MenuData.prevmenudialog = IS4MB() ? &g_CiMenuViaPauseMenuDialog : &g_CiMenuViaPcMenuDialog;
|
||||
} else if (IS4MB()) {
|
||||
g_MenuData.unk008 = MENUROOT_4MBMAINMENU;
|
||||
g_MenuData.unk00c = &g_MainMenu4MbMenuDialog;
|
||||
g_MenuData.prevmenuroot = MENUROOT_4MBMAINMENU;
|
||||
g_MenuData.prevmenudialog = &g_MainMenu4MbMenuDialog;
|
||||
} else {
|
||||
g_MenuData.unk008 = MENUROOT_MPSETUP;
|
||||
g_MenuData.unk00c = &g_CombatSimulatorMenuDialog;
|
||||
g_MenuData.prevmenuroot = MENUROOT_MPSETUP;
|
||||
g_MenuData.prevmenudialog = &g_CombatSimulatorMenuDialog;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_MenuData.unk008 != -1) {
|
||||
if (g_MenuData.unk008 == -5) {
|
||||
if (g_MenuData.prevmenuroot != -1) {
|
||||
if (g_MenuData.prevmenuroot == -5) {
|
||||
// Match is beginning
|
||||
mpStartMatch();
|
||||
menuStop();
|
||||
@@ -519,7 +518,7 @@ void menuTick(void)
|
||||
bossfileSave();
|
||||
g_Vars.modifiedfiles &= ~MODFILE_MPSETUP;
|
||||
}
|
||||
} else if (g_MenuData.unk008 == -6) {
|
||||
} else if (g_MenuData.prevmenuroot == -6) {
|
||||
// Match is ending
|
||||
s32 playernum = 0;
|
||||
|
||||
@@ -542,17 +541,17 @@ void menuTick(void)
|
||||
setCurrentPlayerNum(playernum);
|
||||
endscreenPushCoop();
|
||||
setCurrentPlayerNum(prevplayernum);
|
||||
sp344 = true;
|
||||
isdialogopen = true;
|
||||
}
|
||||
} else if (g_Vars.antiplayernum >= 0) {
|
||||
s32 prevplayernum = g_Vars.currentplayernum;
|
||||
setCurrentPlayerNum(playernum);
|
||||
endscreenPushAnti();
|
||||
setCurrentPlayerNum(prevplayernum);
|
||||
sp344 = true;
|
||||
isdialogopen = true;
|
||||
} else {
|
||||
mpPushEndscreenDialog(playernum, i);
|
||||
sp344 = true;
|
||||
isdialogopen = true;
|
||||
|
||||
if (g_PlayerConfigsArray[i].fileguid.fileid && g_PlayerConfigsArray[i].fileguid.deviceserial) {
|
||||
func0f0fd548(i);
|
||||
@@ -562,7 +561,7 @@ void menuTick(void)
|
||||
playernum++;
|
||||
}
|
||||
}
|
||||
} else if (g_MenuData.unk008 == -7) {
|
||||
} else if (g_MenuData.prevmenuroot == -7) {
|
||||
menuStop();
|
||||
g_FileState = FILESTATE_CHANGINGAGENT;
|
||||
gamefileLoadDefaults(&g_GameFile);
|
||||
@@ -571,8 +570,8 @@ void menuTick(void)
|
||||
musicQueueStopAllEvent();
|
||||
} else {
|
||||
bool startmusic = false;
|
||||
menuPushRootDialog(g_MenuData.unk00c, g_MenuData.unk008);
|
||||
sp344 = true;
|
||||
menuPushRootDialog(g_MenuData.prevmenudialog, g_MenuData.prevmenuroot);
|
||||
isdialogopen = true;
|
||||
|
||||
if (g_MenuData.root == MENUROOT_MPSETUP || g_MenuData.root == MENUROOT_4MBMAINMENU) {
|
||||
startmusic = true;
|
||||
@@ -598,8 +597,8 @@ void menuTick(void)
|
||||
}
|
||||
}
|
||||
|
||||
g_MenuData.unk00c = NULL;
|
||||
g_MenuData.unk008 = -1;
|
||||
g_MenuData.prevmenudialog = NULL;
|
||||
g_MenuData.prevmenuroot = -1;
|
||||
} else {
|
||||
switch (g_MenuData.root) {
|
||||
case MENUROOT_ENDSCREEN:
|
||||
@@ -751,5 +750,5 @@ void menuTick(void)
|
||||
}
|
||||
|
||||
g_ScaleX = 1;
|
||||
g_MenuData.unk5d5_06 = sp344 ? true : false;
|
||||
g_MenuData.isdialogopen = isdialogopen ? true : false;
|
||||
}
|
||||
File renamed without changes.
+74
-79
@@ -28,6 +28,9 @@
|
||||
#include "lib/lib_317f0.h"
|
||||
#include "data.h"
|
||||
#include "types.h"
|
||||
#include "fs.h"
|
||||
#include "system.h"
|
||||
#include "mpsetups.h"
|
||||
|
||||
// bss
|
||||
struct chrdata *g_MpAllChrPtrs[MAX_MPCHRS];
|
||||
@@ -515,12 +518,6 @@ void mpPlayerSetDefaults(s32 playernum, bool autonames)
|
||||
for (i = 0; i < ARRAYCOUNT(g_PlayerConfigsArray); i++) {
|
||||
g_PlayerConfigsArray[playernum].gunfuncs[i] = 0;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
g_MpWeaponSetRandomFilters[i] = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void func0f1881d4(s32 index)
|
||||
@@ -532,7 +529,7 @@ void func0f1881d4(s32 index)
|
||||
g_BotConfigsArray[index].difficulty = BOTDIFF_DISABLED;
|
||||
}
|
||||
|
||||
void mpInit(void)
|
||||
void mpInit(bool resetplayers)
|
||||
{
|
||||
s32 i;
|
||||
s32 j;
|
||||
@@ -565,8 +562,10 @@ void mpInit(void)
|
||||
|
||||
strcpy(g_MpSetup.name, "");
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_PlayerConfigsArray); i++) {
|
||||
mpPlayerSetDefaults(i, false);
|
||||
if (resetplayers) {
|
||||
for (i = 0; i < ARRAYCOUNT(g_PlayerConfigsArray); i++) {
|
||||
mpPlayerSetDefaults(i, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_BOTS; i++) {
|
||||
@@ -599,6 +598,16 @@ void mpInit(void)
|
||||
}
|
||||
|
||||
g_MpSetup.chrslots = 0;
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_Menus); i++) {
|
||||
g_Menus[i].mpsetup.showpresets = 1;
|
||||
}
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpWeapons); i++) {
|
||||
g_MpWeaponSetRandomFilters[i] = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if VERSION >= VERSION_PAL_BETA
|
||||
@@ -3532,7 +3541,7 @@ void mpplayerfileSaveWad(s32 playernum, struct savebuffer *buffer)
|
||||
s32 j;
|
||||
u32 stack;
|
||||
|
||||
func0f0d55a4(buffer, g_PlayerConfigsArray[playernum].base.name);
|
||||
savebufferWriteString(buffer, g_PlayerConfigsArray[playernum].base.name);
|
||||
|
||||
if (g_PlayerConfigsArray[playernum].time > 0x0fffffff) { // over 3106 days
|
||||
g_PlayerConfigsArray[playernum].time = 0x0fffffff;
|
||||
@@ -3683,8 +3692,6 @@ s32 mpplayerfileSave(s32 playernum, s32 device, s32 fileid, u16 deviceserial)
|
||||
if (device >= 0) {
|
||||
savebufferClear(&buffer);
|
||||
mpplayerfileSaveWad(playernum, &buffer);
|
||||
func0f0d54c4(&buffer);
|
||||
|
||||
var80075bd0[2] = true;
|
||||
|
||||
ret = pakSaveAtGuid(device, fileid, PAKFILETYPE_MPPLAYER, buffer.bytes, &newfileid, 0);
|
||||
@@ -3717,8 +3724,6 @@ s32 mpplayerfileLoad(s32 playernum, s32 device, s32 fileid, u16 deviceserial)
|
||||
g_PlayerConfigsArray[playernum].fileguid.deviceserial = deviceserial;
|
||||
|
||||
mpplayerfileLoadWad(playernum, &buffer, 1);
|
||||
func0f0d54c4(&buffer);
|
||||
|
||||
g_PlayerConfigsArray[playernum].handicap = 0x80;
|
||||
return 0;
|
||||
}
|
||||
@@ -3912,21 +3917,54 @@ void mp0f18dec4(s32 slot)
|
||||
#endif
|
||||
}
|
||||
|
||||
void mpsetupfileLoadWad(struct savebuffer *buffer)
|
||||
static u64 packWeaponSetRandomFilters()
|
||||
{
|
||||
u64 packed = 0;
|
||||
for (int i = 0; i < NUM_MPWEAPONS; ++i) {
|
||||
packed |= g_MpWeaponSetRandomFilters[i] != 0 ? (1LL << i) : 0;
|
||||
}
|
||||
|
||||
return packed;
|
||||
}
|
||||
|
||||
static void unpackWeaponSetRandomFilters(u64 packed)
|
||||
{
|
||||
for (int i = 0; i < NUM_MPWEAPONS; ++i) {
|
||||
g_MpWeaponSetRandomFilters[i] = (packed & (1LL << i)) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
void mpsetupfileLoadWad(struct savebuffer *buffer, u8 version)
|
||||
{
|
||||
s32 i;
|
||||
s32 j;
|
||||
|
||||
savebufferReadString(buffer, g_MpSetup.name, false);
|
||||
if (version > 0) {
|
||||
savebufferReadString_ext(buffer, g_MpSetup.name, false, MPSETUP_MAXNAME + 1);
|
||||
}
|
||||
else {
|
||||
savebufferReadString(buffer, g_MpSetup.name, false);
|
||||
}
|
||||
|
||||
savebufferReadBits(buffer, 4);
|
||||
|
||||
g_MpSetup.stagenum = savebufferReadBits(buffer, 7);
|
||||
g_MpSetup.scenario = savebufferReadBits(buffer, 3);
|
||||
|
||||
scenarioInit();
|
||||
scenarioReadSave(buffer);
|
||||
// version == 0 means we're only reading to convert, so no actions are needed
|
||||
if (version > 0) {
|
||||
scenarioInit();
|
||||
}
|
||||
|
||||
scenarioReadSave(buffer, version);
|
||||
|
||||
if (version > 0) {
|
||||
g_MpSetup.options = savebufferReadBits(buffer, 32);
|
||||
}
|
||||
else {
|
||||
g_MpSetup.options = savebufferReadBits(buffer, 21);
|
||||
}
|
||||
|
||||
g_MpSetup.options = savebufferReadBits(buffer, 21);
|
||||
g_MpSetup.chrslots &= 0x000f;
|
||||
|
||||
for (i = 0; i < MAX_BOTS; i++) {
|
||||
@@ -3947,13 +3985,20 @@ void mpsetupfileLoadWad(struct savebuffer *buffer)
|
||||
g_BotConfigsArray[i].base.team = savebufferReadBits(buffer, 3);
|
||||
}
|
||||
|
||||
mpGenerateBotNames();
|
||||
if (version > 0) {
|
||||
mpGenerateBotNames();
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpSetup.weapons); i++) {
|
||||
g_MpSetup.weapons[i] = savebufferReadBits(buffer, 7);
|
||||
}
|
||||
|
||||
func0f18913c();
|
||||
if (version > 0) {
|
||||
u64 wpnRndPacked = savebufferReadBits(buffer, 64);
|
||||
unpackWeaponSetRandomFilters(wpnRndPacked);
|
||||
}
|
||||
|
||||
g_MpWeaponSetNum = savebufferReadBits(buffer, 8);
|
||||
|
||||
g_MpSetup.timelimit = savebufferReadBits(buffer, 6);
|
||||
g_MpSetup.scorelimit = savebufferReadBits(buffer, 7);
|
||||
@@ -3972,7 +4017,7 @@ void mpsetupfileSaveWad(struct savebuffer *buffer)
|
||||
s32 mpbodynum;
|
||||
s32 i;
|
||||
|
||||
func0f0d55a4(buffer, g_MpSetup.name);
|
||||
savebufferWriteString_ext(buffer, g_MpSetup.name, MPSETUP_MAXNAME + 1);
|
||||
|
||||
for (i = 0; i < MAX_BOTS; i++) {
|
||||
if (g_MpSetup.chrslots & (1 << (i + 4))) {
|
||||
@@ -3986,7 +4031,7 @@ void mpsetupfileSaveWad(struct savebuffer *buffer)
|
||||
|
||||
scenarioWriteSave(buffer);
|
||||
|
||||
savebufferOr(buffer, g_MpSetup.options, 21);
|
||||
savebufferOr(buffer, g_MpSetup.options, 32);
|
||||
|
||||
for (i = 0; i < MAX_BOTS; i++) {
|
||||
savebufferOr(buffer, g_BotConfigsArray[i].type, 5);
|
||||
@@ -4019,6 +4064,10 @@ void mpsetupfileSaveWad(struct savebuffer *buffer)
|
||||
savebufferOr(buffer, g_MpSetup.weapons[i], 7);
|
||||
}
|
||||
|
||||
u64 wpnRndPacked = packWeaponSetRandomFilters();
|
||||
savebufferOr(buffer, wpnRndPacked, 64);
|
||||
savebufferOr(buffer, g_MpWeaponSetNum, 8);
|
||||
|
||||
savebufferOr(buffer, g_MpSetup.timelimit, 6);
|
||||
savebufferOr(buffer, g_MpSetup.scorelimit, 7);
|
||||
savebufferOr(buffer, g_MpSetup.teamscorelimit, 9);
|
||||
@@ -4032,69 +4081,15 @@ void mpsetupfileGetOverview(char *arg0, char *filename, u16 *numsims, u16 *stage
|
||||
{
|
||||
struct savebuffer buffer;
|
||||
|
||||
savebufferWriteData(&buffer, arg0, 15);
|
||||
savebufferWriteData(&buffer, arg0, 22);
|
||||
|
||||
savebufferReadString(&buffer, filename, 0);
|
||||
savebufferReadString_ext(&buffer, filename, 0, MPSETUP_MAXNAME+1);
|
||||
|
||||
*numsims = savebufferReadBits(&buffer, 4);
|
||||
*stagenum = savebufferReadBits(&buffer, 7);
|
||||
*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)
|
||||
{
|
||||
s32 i;
|
||||
|
||||
@@ -70,7 +70,7 @@ struct mpscenario {
|
||||
bool (*isroomhighlightedfunc)(RoomNum room);
|
||||
void (*highlightroomfunc)(RoomNum room, s32 *arg1, s32 *arg2, s32 *arg3);
|
||||
void *unk3c; // never hooked into nor fired
|
||||
void (*readsavefunc)(struct savebuffer *buffer);
|
||||
void (*readsavefunc)(struct savebuffer *buffer, u8 version);
|
||||
void (*writesavefunc)(struct savebuffer *buffer);
|
||||
};
|
||||
|
||||
@@ -416,12 +416,13 @@ MenuItemHandlerResult menuhandlerMpOpenOptions(s32 operation, struct menuitem *i
|
||||
*
|
||||
* Used by KOH to read the mphilltime.
|
||||
*/
|
||||
void scenarioReadSave(struct savebuffer *buffer)
|
||||
void scenarioReadSave(struct savebuffer *buffer, u8 version)
|
||||
{
|
||||
if (g_MpScenarios[g_MpSetup.scenario].readsavefunc) {
|
||||
g_MpScenarios[g_MpSetup.scenario].readsavefunc(buffer);
|
||||
g_MpScenarios[g_MpSetup.scenario].readsavefunc(buffer, version);
|
||||
} else {
|
||||
savebufferReadBits(buffer, 8);
|
||||
u8 sz = version > 0 ? 32 : 8;
|
||||
savebufferReadBits(buffer, sz);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +439,7 @@ void scenarioWriteSave(struct savebuffer *buffer)
|
||||
if (g_MpScenarios[g_MpSetup.scenario].writesavefunc) {
|
||||
g_MpScenarios[g_MpSetup.scenario].writesavefunc(buffer);
|
||||
} else {
|
||||
savebufferOr(buffer, 0, 8);
|
||||
savebufferOr(buffer, 0, 32);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -149,14 +149,15 @@ struct menudialogdef g_KohOptionsMenuDialog = {
|
||||
&g_ExtGameOptionsMenuDialog,
|
||||
};
|
||||
|
||||
void kohReadSave(struct savebuffer *buffer)
|
||||
void kohReadSave(struct savebuffer *buffer, u8 version)
|
||||
{
|
||||
g_Vars.mphilltime = savebufferReadBits(buffer, 8);
|
||||
u8 sz = version > 0 ? 32 : 8;
|
||||
g_Vars.mphilltime = savebufferReadBits(buffer, sz);
|
||||
}
|
||||
|
||||
void kohWriteSave(struct savebuffer *buffer)
|
||||
{
|
||||
savebufferOr(buffer, g_Vars.mphilltime, 8);
|
||||
savebufferOr(buffer, g_Vars.mphilltime, 32);
|
||||
}
|
||||
|
||||
void kohInit(void)
|
||||
|
||||
+100
-59
@@ -20,9 +20,13 @@
|
||||
#include "lib/vi.h"
|
||||
#include "lib/rng.h"
|
||||
#include "lib/str.h"
|
||||
#include "lib/joy.h"
|
||||
#include "data.h"
|
||||
#include "gbiex.h"
|
||||
#include "types.h"
|
||||
#include "system.h"
|
||||
#include "input.h"
|
||||
#include "mpsetups.h"
|
||||
|
||||
struct menuitem g_MpCharacterMenuItems[];
|
||||
struct menudialogdef g_MpAddSimulantMenuDialog;
|
||||
@@ -31,6 +35,10 @@ struct menudialogdef g_MpChangeTeamNameMenuDialog;
|
||||
struct menudialogdef g_MpEditSimulantMenuDialog;
|
||||
struct menudialogdef g_MpSaveSetupNameMenuDialog;
|
||||
|
||||
extern struct menudialogdef g_ManageSettingsDialog;
|
||||
extern struct menudialogdef g_FilemgrFileSavedMenuDialog;
|
||||
extern struct menudialogdef g_FilemgrErrorMenuDialog;
|
||||
|
||||
#ifndef PLATFORM_N64
|
||||
extern s32 g_MpWeaponSetNum;
|
||||
#endif
|
||||
@@ -451,9 +459,11 @@ MenuItemHandlerResult menuhandlerMpConfirmSaveChr(s32 operation, struct menuitem
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern struct menudialogdef g_StatusErrorDialog;
|
||||
MenuItemHandlerResult menuhandlerMpSetupName(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
char *name = data->keyboard.string;
|
||||
s32 err;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETTEXT:
|
||||
@@ -463,7 +473,14 @@ MenuItemHandlerResult menuhandlerMpSetupName(s32 operation, struct menuitem *ite
|
||||
strcpy(g_MpSetup.name, name);
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
filemgrPushSelectLocationDialog(7, FILETYPE_MPSETUP);
|
||||
err = mpsetupSaveSetup(g_MpSetupFile.numsetups, true);
|
||||
if (!err) {
|
||||
menuPushDialog(&g_FilemgrFileSavedMenuDialog);
|
||||
g_MpCurrentSetup = g_MpSetupFile.numsetups - 1;
|
||||
}
|
||||
else {
|
||||
menuPushDialog(&g_StatusErrorDialog);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -474,7 +491,8 @@ MenuItemHandlerResult menuhandlerMpSaveSetupOverwrite(s32 operation, struct menu
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
menuPopDialog();
|
||||
filemgrSaveOrLoad(&g_MpSetup.fileguid, FILEOP_SAVE_MPSETUP, 0);
|
||||
mpsetupSaveSetup(g_MpCurrentSetup, true);
|
||||
menuPushDialog(&g_FilemgrFileSavedMenuDialog);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1075,18 +1093,18 @@ struct menuitem g_MpSaveSetupNameMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LESSLEFTPADDING,
|
||||
L_MPMENU_189, // "Enter a name for your game setup file:"
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING,
|
||||
(uintptr_t)"Enter the setup name:\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
#endif
|
||||
{
|
||||
MENUITEMTYPE_KEYBOARD,
|
||||
MPSETUP_MAXNAME,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
menuhandlerMpSetupName,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
@@ -1112,10 +1130,10 @@ struct menuitem g_MpSaveSetupExistsMenuItems[] = {
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_SELECTABLE_CENTRE | MENUITEMFLAG_SMALLFONT,
|
||||
(uintptr_t)&filemgrMenuTextDeviceName,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
@@ -1123,8 +1141,16 @@ struct menuitem g_MpSaveSetupExistsMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LESSLEFTPADDING,
|
||||
L_MPMENU_184, // "Do you want to save over your original game file?"
|
||||
MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_LITERAL_TEXT,
|
||||
(uintptr_t)"Save over your\noriginal setup?\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
@@ -2232,36 +2258,31 @@ MenuItemHandlerResult mpPlayerNameMenuHandler(s32 operation, struct menuitem *it
|
||||
|
||||
MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
u8 presets = g_Menus[g_MpPlayerNum].mpsetup.showpresets;
|
||||
s32 numpresets = mpGetNumUnlockedPresets()*presets;
|
||||
|
||||
switch (operation) {
|
||||
case MENUOP_GETOPTIONCOUNT:
|
||||
data->list.value = mpGetNumUnlockedPresets();
|
||||
|
||||
if (g_FileLists[1] != NULL) {
|
||||
data->list.value += g_FileLists[1]->numfiles;
|
||||
}
|
||||
data->list.value = numpresets + g_MpSetupFile.numsetups;
|
||||
break;
|
||||
case MENUOP_GETOPTIONTEXT:
|
||||
if (data->list.value < mpGetNumUnlockedPresets()) {
|
||||
if (presets && data->list.value < mpGetNumUnlockedPresets()) {
|
||||
return (uintptr_t)mpGetPresetNameBySlot(data->list.value);
|
||||
}
|
||||
if (g_FileLists[1] != NULL) {
|
||||
func0f0d564c(g_FileLists[1]->files[data->list.value - mpGetNumUnlockedPresets()].name, g_StringPointer, false);
|
||||
if (g_MpSetupFile.numsetups > 0) {
|
||||
struct setupblock *block = &g_MpSetupFile.setups[data->list.value - numpresets];
|
||||
func0f0d564c_ext(block->bytes, g_StringPointer, false, MPSETUP_MAXNAME+1);
|
||||
return (uintptr_t)g_StringPointer;
|
||||
}
|
||||
break;
|
||||
case MENUOP_SET:
|
||||
mpCloseDialogsForNewSetup();
|
||||
|
||||
if (data->list.value < mpGetNumUnlockedPresets()) {
|
||||
if (presets && data->list.value < mpGetNumUnlockedPresets()) {
|
||||
mp0f18dec4(data->list.value);
|
||||
} else if (g_FileLists[1] != NULL) {
|
||||
struct filelistfile *file = &g_FileLists[1]->files[data->list.value - mpGetNumUnlockedPresets()];
|
||||
struct fileguid guid;
|
||||
|
||||
guid.fileid = file->fileid;
|
||||
guid.deviceserial = file->deviceserial;
|
||||
|
||||
filemgrSaveOrLoad(&guid, FILEOP_LOAD_MPSETUP, 0);
|
||||
g_MpCurrentSetup = -1;
|
||||
} else {
|
||||
mpsetupLoadSetup(data->list.value - numpresets);
|
||||
}
|
||||
|
||||
if (item->param == 1) {
|
||||
@@ -2276,36 +2297,21 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
|
||||
data->list.value = 0xfffff;
|
||||
break;
|
||||
case MENUOP_GETOPTGROUPCOUNT:
|
||||
data->list.value = 1;
|
||||
|
||||
if (g_FileLists[1] != NULL) {
|
||||
data->list.value += g_FileLists[1]->numdevices;
|
||||
}
|
||||
data->list.value = presets ? 2 : 1;
|
||||
break;
|
||||
case MENUOP_GETOPTGROUPTEXT:
|
||||
if (data->list.value == 0) {
|
||||
if (presets && data->list.value == 0) {
|
||||
return (uintptr_t)langGet(L_MPMENU_141); // "Presets"
|
||||
}
|
||||
if (g_FileLists[1] != NULL) {
|
||||
return (uintptr_t)filemgrGetDeviceNameOrStartIndex(1, operation, data->list.value - 1);
|
||||
}
|
||||
break;
|
||||
return (uintptr_t)"Custom";
|
||||
case MENUOP_GETGROUPSTARTINDEX:
|
||||
if (data->list.value == 0) {
|
||||
data->list.groupstartindex = 0;
|
||||
} else {
|
||||
data->list.groupstartindex = mpGetNumUnlockedPresets();
|
||||
|
||||
if (g_FileLists[1] != NULL) {
|
||||
data->list.groupstartindex += filemgrGetDeviceNameOrStartIndex(1, operation, data->list.value - 1);
|
||||
}
|
||||
}
|
||||
data->list.groupstartindex = data->list.value == 0 ? 0 : numpresets;
|
||||
break;
|
||||
case MENUOP_LISTITEMFOCUS:
|
||||
if (data->list.value < mpGetNumUnlockedPresets()) {
|
||||
if (presets && data->list.value < mpGetNumUnlockedPresets()) {
|
||||
g_Menus[g_MpPlayerNum].mpsetup.slotindex = 0xffff;
|
||||
} else {
|
||||
g_Menus[g_MpPlayerNum].mpsetup.slotindex = data->list.value - mpGetNumUnlockedPresets();
|
||||
g_Menus[g_MpPlayerNum].mpsetup.slotindex = data->list.value - numpresets;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2315,21 +2321,21 @@ MenuItemHandlerResult mpLoadSettingsMenuHandler(s32 operation, struct menuitem *
|
||||
|
||||
char *mpMenuTextMpconfigMarquee(struct menuitem *item)
|
||||
{
|
||||
char filename[20];
|
||||
char filename[MPSETUP_MAXNAME+1];
|
||||
u16 numsims;
|
||||
u16 stagenum;
|
||||
u16 scenarionum;
|
||||
s32 arenanum;
|
||||
s32 i;
|
||||
|
||||
if (g_Menus[g_MpPlayerNum].mpsetup.slotindex < 0xffff && g_FileLists[1]) {
|
||||
if (g_Menus[g_MpPlayerNum].mpsetup.slotindex < 0xffff && g_MpSetupFile.numsetups > 0) {
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
arenanum = -1;
|
||||
#else
|
||||
arenanum = 0;
|
||||
#endif
|
||||
|
||||
mpsetupfileGetOverview(g_FileLists[1]->files[g_Menus[g_MpPlayerNum].mpsetup.slotindex].name,
|
||||
mpsetupfileGetOverview(g_MpSetupFile.setups[g_Menus[g_MpPlayerNum].mpsetup.slotindex].bytes,
|
||||
filename, &numsims, &stagenum, &scenarionum);
|
||||
|
||||
for (i = 0; i < ARRAYCOUNT(g_MpArenas); i++) {
|
||||
@@ -2558,6 +2564,16 @@ MenuDialogHandlerResult menudialogMpSimulant(s32 operation, struct menudialogdef
|
||||
return false;
|
||||
}
|
||||
|
||||
MenuDialogHandlerResult mpLoadSettingsDialogHandler(s32 operation, struct menudialogdef *dialogdef, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_TICK) {
|
||||
if (menuAltAnyPressed(g_MpPlayerNum)) {
|
||||
u8 presets = g_Menus[g_MpPlayerNum].mpsetup.showpresets;
|
||||
g_Menus[g_MpPlayerNum].mpsetup.showpresets = 1 - presets;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct menuitem g_MpCharacterMenuItems[] = {
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
@@ -2633,6 +2649,22 @@ struct menuitem g_MpLoadSettingsMenuItems[] = {
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SEPARATOR,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_LABEL,
|
||||
0,
|
||||
MENUITEMFLAG_LITERAL_TEXT | MENUITEMFLAG_LESSLEFTPADDING | MENUITEMFLAG_SMALLFONT,
|
||||
(uintptr_t)"Menu Alt: Toggle Presets\n",
|
||||
0,
|
||||
NULL,
|
||||
},
|
||||
{ MENUITEMTYPE_END },
|
||||
};
|
||||
|
||||
@@ -2640,7 +2672,7 @@ struct menudialogdef g_MpLoadSettingsMenuDialog = {
|
||||
MENUDIALOGTYPE_DEFAULT,
|
||||
L_MPMENU_139, // "Load Game Settings"
|
||||
g_MpLoadSettingsMenuItems,
|
||||
NULL,
|
||||
mpLoadSettingsDialogHandler,
|
||||
MENUDIALOGFLAG_CLOSEONSELECT,
|
||||
NULL,
|
||||
};
|
||||
@@ -5016,13 +5048,10 @@ MenuItemHandlerResult menuhandler0017ef30(s32 operation, struct menuitem *item,
|
||||
MenuItemHandlerResult menuhandlerMpSaveSettings(s32 operation, struct menuitem *item, union handlerdata *data)
|
||||
{
|
||||
if (operation == MENUOP_SET) {
|
||||
if (g_MpSetup.fileguid.fileid == 0) {
|
||||
if (g_MpCurrentSetup < 0) {
|
||||
menuPushDialog(&g_MpSaveSetupNameMenuDialog);
|
||||
} else {
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
filemgrSetDevice1BySerial(g_MpSetup.fileguid.deviceserial);
|
||||
#endif
|
||||
|
||||
}
|
||||
else {
|
||||
menuPushDialog(&g_MpSaveSetupExistsMenuDialog);
|
||||
}
|
||||
}
|
||||
@@ -5365,6 +5394,10 @@ MenuDialogHandlerResult menudialogCombatSimulator(s32 operation, struct menudial
|
||||
g_Vars.waitingtojoin[1] = false;
|
||||
g_Vars.waitingtojoin[2] = false;
|
||||
g_Vars.waitingtojoin[3] = false;
|
||||
|
||||
// load the setup file when entering the Combat Simulator
|
||||
mpsetupCopyAllFromPak();
|
||||
mpsetupLoadCurrentFile();
|
||||
}
|
||||
|
||||
if (g_Menus[g_MpPlayerNum].curdialog
|
||||
@@ -5757,6 +5790,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_ManageSettingsDialog,
|
||||
},
|
||||
{
|
||||
MENUITEMTYPE_SELECTABLE,
|
||||
0,
|
||||
|
||||
+4
-4
@@ -3667,15 +3667,15 @@ void playerTick(bool arg0)
|
||||
f32 mdx, mdy;
|
||||
inputMouseGetScaledDelta(&mdx, &mdy);
|
||||
if (mdx || mdy) {
|
||||
mdx *= 48.f;
|
||||
mdy *= 48.f;
|
||||
mdx *= 0.022f;
|
||||
mdy *= 0.022f;
|
||||
mdx = (mdx < -128.f) ? -128.f : (mdx > 127.f) ? 127.f : mdx;
|
||||
mdy = (mdy < -128.f) ? -128.f : (mdy > 127.f) ? 127.f : mdy;
|
||||
if (g_Vars.currentplayerstats && !optionsGetForwardPitch(g_Vars.currentplayerstats->mpindex)) {
|
||||
mdy = -mdy;
|
||||
}
|
||||
sp178 += mdy * 0.00025f;
|
||||
sp174 -= mdx * 0.00025f;
|
||||
sp178 += mdy;
|
||||
sp174 -= mdx;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+32
-24
@@ -374,13 +374,13 @@ Gfx *menugfxDrawPlane(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32
|
||||
/**
|
||||
* Write the specified amount of bits to the buffer, advancing the internal pointer.
|
||||
*
|
||||
* numbits is expected to be 32 or less.
|
||||
* numbits is expected to be 64 or less.
|
||||
*
|
||||
* This function only sets bits to on and does not unset them.
|
||||
*/
|
||||
void savebufferOr(struct savebuffer *buffer, u32 value, s32 numbits)
|
||||
void savebufferOr(struct savebuffer *buffer, u64 value, s32 numbits)
|
||||
{
|
||||
u32 bit = 1 << (numbits - 1);
|
||||
u64 bit = 1LL << (numbits - 1LL);
|
||||
|
||||
for (; bit; bit >>= 1) {
|
||||
if (bit & value) {
|
||||
@@ -399,11 +399,11 @@ void savebufferOr(struct savebuffer *buffer, u32 value, s32 numbits)
|
||||
/**
|
||||
* Write the specified amount of bits to the buffer, advancing the internal pointer.
|
||||
*
|
||||
* numbits is expected to be 32 or less.
|
||||
* numbits is expected to be 64 or less.
|
||||
*/
|
||||
void savebufferWriteBits(struct savebuffer *buffer, u32 value, s32 numbits, u8 *dst)
|
||||
void savebufferWriteBits(struct savebuffer *buffer, u64 value, s32 numbits, u8 *dst)
|
||||
{
|
||||
u32 bit = 1 << (numbits - 1);
|
||||
u64 bit = 1LL << (numbits - 1);
|
||||
|
||||
for (; bit; bit >>= 1) {
|
||||
s32 bitindex = buffer->bitpos % 8;
|
||||
@@ -425,12 +425,12 @@ void savebufferWriteBits(struct savebuffer *buffer, u32 value, s32 numbits, u8 *
|
||||
* Read the specified amount of bits from the buffer and return it as an
|
||||
* integer, advancing the internal pointer.
|
||||
*
|
||||
* numbits is expected to be 32 or less.
|
||||
* numbits is expected to be 64 or less.
|
||||
*/
|
||||
u32 savebufferReadBits(struct savebuffer *buffer, s32 numbits)
|
||||
u64 savebufferReadBits(struct savebuffer *buffer, s32 numbits)
|
||||
{
|
||||
u32 bit = 1 << (numbits - 1);
|
||||
u32 value = 0;
|
||||
u64 bit = 1LL << (numbits - 1);
|
||||
u64 value = 0;
|
||||
|
||||
for (; bit; bit >>= 1) {
|
||||
s32 bitindex = buffer->bitpos % 8;
|
||||
@@ -470,24 +470,17 @@ void savebufferWriteData(struct savebuffer *buffer, u8 *data, u8 len)
|
||||
}
|
||||
}
|
||||
|
||||
void func0f0d54c4(struct savebuffer *buffer)
|
||||
{
|
||||
s32 tmp = buffer->bitpos;
|
||||
|
||||
if (tmp / 8 && buffer->bitpos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a zero-terminated string from the buffer and move the buffer's internal
|
||||
* pointer past the end of the string.
|
||||
*/
|
||||
void savebufferReadString(struct savebuffer *buffer, char *dst, bool addlinebreak)
|
||||
void savebufferReadString_ext(struct savebuffer *buffer, char *dst, bool addlinebreak, u8 len)
|
||||
{
|
||||
bool foundnull = false;
|
||||
s32 index = 0;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
s32 byte = savebufferReadBits(buffer, 8);
|
||||
|
||||
if (!foundnull) {
|
||||
@@ -509,12 +502,17 @@ void savebufferReadString(struct savebuffer *buffer, char *dst, bool addlinebrea
|
||||
dst[index] = '\0';
|
||||
}
|
||||
|
||||
void func0f0d55a4(struct savebuffer *buffer, char *src)
|
||||
void savebufferReadString(struct savebuffer *buffer, char *dst, bool addlinebreak)
|
||||
{
|
||||
savebufferReadString_ext(buffer, dst, addlinebreak, 10);
|
||||
}
|
||||
|
||||
void savebufferWriteString_ext(struct savebuffer *buffer, char *src, u8 len)
|
||||
{
|
||||
bool done = false;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!done) {
|
||||
if (src[i] == '\0') {
|
||||
done = true;
|
||||
@@ -532,12 +530,22 @@ void func0f0d55a4(struct savebuffer *buffer, char *src)
|
||||
}
|
||||
}
|
||||
|
||||
void func0f0d564c(u8 *data, char *dst, bool addlinebreak)
|
||||
void savebufferWriteString(struct savebuffer *buffer, char *src)
|
||||
{
|
||||
savebufferWriteString_ext(buffer, src, 10);
|
||||
}
|
||||
|
||||
void func0f0d564c_ext(u8 *data, char *dst, bool addlinebreak, u8 len)
|
||||
{
|
||||
struct savebuffer buffer;
|
||||
|
||||
savebufferWriteData(&buffer, data, 10);
|
||||
savebufferReadString(&buffer, dst, addlinebreak);
|
||||
savebufferWriteData(&buffer, data, len);
|
||||
savebufferReadString_ext(&buffer, dst, addlinebreak, len);
|
||||
}
|
||||
|
||||
void func0f0d564c(u8 *data, char *dst, bool addlinebreak)
|
||||
{
|
||||
func0f0d564c_ext(data, dst, addlinebreak, 10);
|
||||
}
|
||||
|
||||
#if VERSION >= VERSION_NTSC_1_0
|
||||
|
||||
+6
-6
@@ -17,7 +17,7 @@
|
||||
#ifndef PLATFORM_N64
|
||||
#include "video.h"
|
||||
#include "game/gfxmemory.h"
|
||||
#include "game/game_13c510.h"
|
||||
#include "game/artifact.h"
|
||||
#include "game/player.h"
|
||||
#endif
|
||||
|
||||
@@ -2518,11 +2518,11 @@ void skyCreateSunArtifact(struct artifact *artifact, s32 x, s32 y)
|
||||
sunpos.x = env->suns[i].pos[0];
|
||||
sunpos.y = env->suns[i].pos[1];
|
||||
sunpos.z = env->suns[i].pos[2];
|
||||
artifact->unk02 = artifactTestLos(&sunpos, &zero, x, y) * 0xfffc;
|
||||
artifact->visiblelos = artifactTestLos(&sunpos, &zero, x, y) * 0xfffc;
|
||||
#endif
|
||||
artifact->unk08 = &g_ZbufPtr1[(s32)camGetScreenWidth() * y + x];
|
||||
artifact->unk0c.u16_2 = x;
|
||||
artifact->unk0c.u16_1 = y;
|
||||
artifact->zbufptr = &g_ZbufPtr1[(s32)camGetScreenWidth() * y + x];
|
||||
artifact->screenx = x;
|
||||
artifact->screeny = y;
|
||||
artifact->type = ARTIFACTTYPE_CIRCLE;
|
||||
}
|
||||
}
|
||||
@@ -2533,7 +2533,7 @@ f32 skyGetArtifactGroupIntensityFrac(struct artifact *artifacts)
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (artifacts[i].type == ARTIFACTTYPE_CIRCLE && artifacts[i].unk02 == 0xfffc) {
|
||||
if (artifacts[i].type == ARTIFACTTYPE_CIRCLE && artifacts[i].actualdepth == 0xfffc) {
|
||||
sum += 0.125f;
|
||||
}
|
||||
}
|
||||
|
||||
+26
-18
@@ -177,23 +177,31 @@ u16 *zbufGetArtifactsCfb(s32 index)
|
||||
return addr;
|
||||
}
|
||||
|
||||
Gfx *zbufDrawArtifactsOffscreen(Gfx *gdl)
|
||||
/**
|
||||
* This method is designed to save artifact depths
|
||||
* prior to drawing the hands and weapon on-screen
|
||||
* since drawing them requires clearing the zbuffer
|
||||
* to avoid clipping the gun model on floors and walls.
|
||||
*
|
||||
* TODO: determine if this works with the PC port
|
||||
*/
|
||||
Gfx *zbufSaveArtifactDepths(Gfx *gdl)
|
||||
{
|
||||
struct artifact *artifacts = schedGetWriteArtifacts();
|
||||
u32 stack;
|
||||
u16 *sp4c = g_ZbufPtr1;
|
||||
u32 s4 = 0;
|
||||
u16 *sp44;
|
||||
u16 *s2;
|
||||
u16 *image;
|
||||
u16 *zbuf = g_ZbufPtr1;
|
||||
u32 numsamples = 0;
|
||||
u16 *samples;
|
||||
u16 *thissample;
|
||||
u16 *zbufrow;
|
||||
s32 i;
|
||||
|
||||
viGetBackBuffer();
|
||||
sp44 = zbufGetArtifactsCfb(g_SchedWriteArtifactsIndex);
|
||||
samples = zbufGetArtifactsCfb(g_SchedWriteArtifactsIndex);
|
||||
g_SchedSpecialArtifactIndexes[g_SchedWriteArtifactsIndex] = 1;
|
||||
|
||||
gDPPipeSync(gdl++);
|
||||
gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, viGetBufWidth(), OS_PHYSICAL_TO_K0(sp44));
|
||||
gDPSetColorImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, viGetBufWidth(), OS_PHYSICAL_TO_K0(samples));
|
||||
gDPSetScissor(gdl++, G_SC_NON_INTERLACE, 0, 0, SCREEN_320, SCREEN_240);
|
||||
gDPSetCycleType(gdl++, G_CYC_COPY);
|
||||
gDPSetTile(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, 0, 0x0000, 5, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD);
|
||||
@@ -220,24 +228,24 @@ Gfx *zbufDrawArtifactsOffscreen(Gfx *gdl)
|
||||
if (1);
|
||||
|
||||
if (artifacts[i].type != ARTIFACTTYPE_FREE) {
|
||||
s2 = &sp44[s4];
|
||||
image = &sp4c[artifacts[i].unk0c.u16_1 * viGetWidth()];
|
||||
thissample = &samples[numsamples];
|
||||
zbufrow = &zbuf[artifacts[i].screeny * viGetWidth()];
|
||||
|
||||
gDPPipeSync(gdl++);
|
||||
gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, image);
|
||||
gDPSetTextureImage(gdl++, G_IM_FMT_RGBA, G_IM_SIZ_16b, SCREEN_320, zbufrow);
|
||||
gDPLoadSync(gdl++);
|
||||
gDPLoadBlock(gdl++, 5, 0, 0, viGetWidth() - 1, 0);
|
||||
gDPPipeSync(gdl++);
|
||||
|
||||
gSPTextureRectangle(gdl++,
|
||||
s4 << 2, 0,
|
||||
(s4 + 3) << 2, 0,
|
||||
G_TX_RENDERTILE, (artifacts[i].unk0c.u16_2 * 32) + 16, 0x0010, 0x1000, 0);
|
||||
numsamples << 2, 0,
|
||||
(numsamples + 3) << 2, 0,
|
||||
G_TX_RENDERTILE, (artifacts[i].screenx * 32) + 16, 0x0010, 0x1000, 0);
|
||||
|
||||
artifacts[i].unk0c.u16p = s2;
|
||||
s4++;
|
||||
artifacts[i].depthptr = thissample;
|
||||
numsamples++;
|
||||
|
||||
if (s2);
|
||||
if (thissample);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +259,7 @@ Gfx *zbufDrawArtifactsOffscreen(Gfx *gdl)
|
||||
gDPSetTexturePersp(gdl++, G_TP_PERSP);
|
||||
gDPSetColorDither(gdl++, G_CD_BAYER);
|
||||
|
||||
if (sp44);
|
||||
if (samples);
|
||||
|
||||
return gdl;
|
||||
}
|
||||
@@ -4757,6 +4757,10 @@ enum weaponnum {
|
||||
|
||||
#define EXTRA_SLEEP_TIME 1000LL // 100us
|
||||
|
||||
#define MPSETUP_MAXSETUPS 128
|
||||
#define MPSETUP_MAXNAME 17
|
||||
#define MPSETUP_BLOCKSIZE 80
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -562,6 +562,9 @@ extern s32 g_FileAutoSelect;
|
||||
extern u8 g_MpWeaponSetRandomFilters[NUM_MPWEAPONS];
|
||||
extern s32 g_MpWeaponRandomFilterNum;
|
||||
|
||||
extern struct mpsetupfile g_MpSetupFile;
|
||||
extern s16 g_MpCurrentSetup;
|
||||
|
||||
#define PLAYER_EXTCFG() g_PlayerExtCfg[g_Vars.currentplayerstats->mpindex & 3]
|
||||
#define PLAYER_DEFAULT_FOV (PLAYER_EXTCFG().fovy)
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
|
||||
void artifactsClear(void);
|
||||
void artifactsTick(void);
|
||||
u16 func0f13c574(f32 arg0);
|
||||
s32 func0f13c710(f32 arg0);
|
||||
u16 floatToN64Depth(f32 arg0);
|
||||
s32 artifactsFloatToInt(f32 arg0);
|
||||
void artifactsCalculateGlaresForRoom(s32 roomnum);
|
||||
u8 func0f13d3c4(u8 arg0, u8 arg1);
|
||||
u8 artifactsClamp(u8 arg0, u8 arg1);
|
||||
Gfx *artifactsConfigureForGlares(Gfx *gdl);
|
||||
Gfx *artifactsUnconfigureForGlares(Gfx *gdl);
|
||||
Gfx *artifactsRenderGlaresForRoom(Gfx *gdl, s32 roomnum);
|
||||
@@ -113,6 +113,10 @@ MenuItemHandlerResult menuhandlerRepairPak(s32 operation, struct menuitem *item,
|
||||
MenuItemHandlerResult menuhandlerRetrySavePak(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
MenuItemHandlerResult menuhandlerWarnRepairPak(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
|
||||
s32 menuAlt1Pressed(s32 playerNum);
|
||||
s32 menuAlt2Pressed(s32 playerNum);
|
||||
s32 menuAltAnyPressed(s32 playerNum);
|
||||
|
||||
extern const char var7f1b2658[];
|
||||
extern const char var7f1b265c[];
|
||||
extern const char var7f1b2660[];
|
||||
|
||||
@@ -13,7 +13,7 @@ void func0f187fbc(s32 playernum);
|
||||
void func0f187fec(void);
|
||||
void mpPlayerSetDefaults(s32 playernum, bool autonames);
|
||||
void func0f1881d4(s32 index);
|
||||
void mpInit(void);
|
||||
void mpInit(bool resetplayers);
|
||||
void mpGetTeamsWithDefaultName(u8 *mask);
|
||||
void mpSetTeamNamesToDefault(u8 mask);
|
||||
void mpSetDefaultNamesIfEmpty(void);
|
||||
@@ -118,11 +118,10 @@ s32 mpGetNumUnlockedPresets(void);
|
||||
char *mpGetPresetNameBySlot(s32 slot);
|
||||
void mpApplyConfig(struct mpconfigfull *mpconfig);
|
||||
void mp0f18dec4(s32 arg0);
|
||||
void mpsetupfileLoadWad(struct savebuffer *buffer);
|
||||
void mpsetupfileLoadWad(struct savebuffer *buffer, u8 version);
|
||||
void mpsetupfileSaveWad(struct savebuffer *buffer);
|
||||
void mpsetupfileGetOverview(char *arg0, char *filename, u16 *numsims, u16 *stagenum, u16 *scenarionum);
|
||||
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);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ struct mpscenariooverview {
|
||||
extern struct mpscenariooverview g_MpScenarioOverviews[6];
|
||||
|
||||
MenuItemHandlerResult menuhandlerMpOpenOptions(s32 operation, struct menuitem *item, union handlerdata *data);
|
||||
void scenarioReadSave(struct savebuffer *buffer);
|
||||
void scenarioReadSave(struct savebuffer *buffer, u8 version);
|
||||
void scenarioWriteSave(struct savebuffer *buffer);
|
||||
void scenarioInit(void);
|
||||
s32 scenarioNumProps(void);
|
||||
|
||||
@@ -11,14 +11,16 @@ Gfx *func0f0d49c8(Gfx *gdl);
|
||||
Gfx *func0f0d4a3c(Gfx *gdl, s32 arg1);
|
||||
Gfx *func0f0d4c80(Gfx *gdl);
|
||||
Gfx *menugfxDrawPlane(Gfx *gdl, s32 x1, s32 y1, s32 x2, s32 y2, u32 colour1, u32 colour2, s32 type);
|
||||
void savebufferOr(struct savebuffer *buffer, u32 arg1, s32 arg2);
|
||||
void savebufferWriteBits(struct savebuffer *buffer, u32 value, s32 numbits, u8 *dst);
|
||||
u32 savebufferReadBits(struct savebuffer *buffer, s32 offset);
|
||||
void savebufferOr(struct savebuffer *buffer, u64 arg1, s32 arg2);
|
||||
void savebufferWriteBits(struct savebuffer *buffer, u64 value, s32 numbits, u8 *dst);
|
||||
u64 savebufferReadBits(struct savebuffer *buffer, s32 offset);
|
||||
void savebufferClear(struct savebuffer *buffer);
|
||||
void savebufferWriteData(struct savebuffer *buffer, u8 *data, u8 len);
|
||||
void func0f0d54c4(struct savebuffer *buffer);
|
||||
void savebufferReadString_ext(struct savebuffer *buffer, char *dst, bool addlinebreak, u8 len);
|
||||
void savebufferReadString(struct savebuffer *buffer, char *dst, bool addlinebreak);
|
||||
void func0f0d55a4(struct savebuffer *buffer, char *src);
|
||||
void savebufferWriteString_ext(struct savebuffer *buffer, char *src, u8 len);
|
||||
void savebufferWriteString(struct savebuffer *buffer, char *src);
|
||||
void func0f0d564c_ext(u8 *data, char *dst, bool addlinebreak, u8 len);
|
||||
void func0f0d564c(u8 *data, char *dst, bool addlinebreak);
|
||||
void func0f0d5690(u8 *dst, char *buffer);
|
||||
void savebufferWriteGuid(struct savebuffer *buffer, struct fileguid *guid);
|
||||
|
||||
+29
-14
@@ -3295,7 +3295,7 @@ struct menuitemdata_dropdown {
|
||||
};
|
||||
|
||||
struct menuitemdata_keyboard {
|
||||
char string[11];
|
||||
char string[MPSETUP_MAXNAME+1];
|
||||
s8 col;
|
||||
s8 row;
|
||||
u8 capslock : 1; // Pressed A on caps button
|
||||
@@ -3494,17 +3494,19 @@ struct audioconfig {
|
||||
|
||||
struct artifact {
|
||||
u16 type;
|
||||
u16 unk02;
|
||||
u16 unk04;
|
||||
u16 unk06;
|
||||
u16 *unk08;
|
||||
u16 actualdepth;
|
||||
u16 expecteddepth;
|
||||
u16 *zbufptr;
|
||||
#ifndef PLATFORM_N64
|
||||
u16 visiblelos;
|
||||
#endif
|
||||
union {
|
||||
u16 *u16p;
|
||||
u16 *depthptr;
|
||||
struct {
|
||||
u16 u16_1;
|
||||
u16 u16_2;
|
||||
u16 screeny;
|
||||
u16 screenx;
|
||||
};
|
||||
} unk0c;
|
||||
};
|
||||
struct light *light;
|
||||
};
|
||||
|
||||
@@ -3774,6 +3776,7 @@ struct menudata_main {
|
||||
struct menudata_mpsetup {
|
||||
u32 slotindex;
|
||||
u32 slotcount;
|
||||
u8 showpresets;
|
||||
u32 unke24;
|
||||
};
|
||||
|
||||
@@ -3982,13 +3985,14 @@ struct menu {
|
||||
union {
|
||||
struct menudata_endscreen endscreen;
|
||||
struct menudata_main main;
|
||||
struct menudata_mpsetup mpsetup;
|
||||
struct menudata_mppause mppause;
|
||||
struct menudata_mpend mpend;
|
||||
struct menudata_filemgr fm;
|
||||
struct menudata_main4mb main4mb;
|
||||
struct menudata_training training;
|
||||
};
|
||||
|
||||
struct menudata_mpsetup mpsetup;
|
||||
};
|
||||
|
||||
struct gamefile {
|
||||
@@ -4080,7 +4084,7 @@ struct missionconfig {
|
||||
};
|
||||
|
||||
struct mpsetup {
|
||||
/*0x800acb88*/ char name[12];
|
||||
/*0x800acb88*/ char name[MPSETUP_MAXNAME+1];
|
||||
/*0x800acb94*/ u32 options;
|
||||
/*0x800acb98*/ u8 scenario;
|
||||
/*0x800acb99*/ u8 stagenum;
|
||||
@@ -4783,8 +4787,8 @@ struct menudata_5d8 {
|
||||
struct menudata {
|
||||
/*0x000*/ s32 count;
|
||||
/*0x004*/ s32 root;
|
||||
/*0x008*/ s32 unk008; // also a menuroot constant
|
||||
/*0x00c*/ struct menudialogdef *unk00c;
|
||||
/*0x008*/ s32 prevmenuroot; // also a menuroot constant
|
||||
/*0x00c*/ struct menudialogdef *prevmenudialog;
|
||||
/*0x010*/ f32 unk010;
|
||||
/*0x014*/ u8 bg;
|
||||
/*0x015*/ u8 nextbg;
|
||||
@@ -4798,7 +4802,7 @@ struct menudata {
|
||||
/*0x5d5*/ u8 usezbuf : 1;
|
||||
/*0x5d5*/ u8 unk5d5_04 : 1;
|
||||
/*0x5d5*/ u8 unk5d5_05 : 1;
|
||||
/*0x5d5*/ u8 unk5d5_06 : 1;
|
||||
/*0x5d5*/ u8 isdialogopen : 1;
|
||||
/*0x5d5*/ u8 unk5d5_07 : 1;
|
||||
/*0x5d5*/ u8 unk5d5_08 : 1;
|
||||
/*0x5d8*/ struct menudata_5d8 unk5d8[12];
|
||||
@@ -6156,6 +6160,17 @@ struct extplayerconfig {
|
||||
s32 usereloads;
|
||||
};
|
||||
|
||||
struct setupblock {
|
||||
u8 bytes[MPSETUP_BLOCKSIZE];
|
||||
};
|
||||
|
||||
struct mpsetupfile {
|
||||
u8 version;
|
||||
u8 defaultsetup;
|
||||
u8 numsetups;
|
||||
struct setupblock setups[MPSETUP_MAXSETUPS];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+8
-8
@@ -540,20 +540,20 @@ void schedUpdatePendingArtifacts(void)
|
||||
struct artifact *artifact = &artifacts[i];
|
||||
|
||||
if (artifact->type != ARTIFACTTYPE_FREE) {
|
||||
u16 *unk08 = artifact->unk08;
|
||||
u16 value08 = unk08[0];
|
||||
u16 *currdepthptr = artifact->zbufptr;
|
||||
u16 currdepth = *currdepthptr;
|
||||
|
||||
if (g_SchedSpecialArtifactIndexes[g_SchedPendingArtifactsIndex] == 1) {
|
||||
u16 *unk0c = artifact->unk0c.u16p;
|
||||
u16 value0c = unk0c[0];
|
||||
u16 *prevdepthptr = artifact->depthptr;
|
||||
u16 prevdepth = *prevdepthptr;
|
||||
|
||||
if (value0c > value08) {
|
||||
artifact->unk02 = value08;
|
||||
if (currdepth < prevdepth) {
|
||||
artifact->actualdepth = currdepth;
|
||||
} else {
|
||||
artifact->unk02 = value0c;
|
||||
artifact->actualdepth = prevdepth;
|
||||
}
|
||||
} else {
|
||||
artifact->unk02 = value08;
|
||||
artifact->actualdepth = currdepth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user