mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
M-26: [A/E] atexit config+window persistence, --help/--version
- main.c: atexit(portAtExit) = videoSaveWindowState() + configSave(), fires on clean exit(0) (SDL_QUIT/ESC/close); abort() paths skip it. - video.c: new [Window] ini section (Width/Height/X/Y/Maximized); sentinels (0 / -1) reproduce native-size + centered. videoSaveWindowState() snapshots live geometry via the SDL2 wapi backend. Video.Fullscreen now round-trips. - main.c: --version / --help (-h) before crashInit — build id, usage, 21-level -level_XX table. - Verified: -level_09/-level_20 crash-free 6/6 frames, ge007.ini gains populated [Window] block on exit.
This commit is contained in:
1 parent
905eebf447
commit
db1834ca9b
3 files changed
+112
-6
No files matched your search
@@ -48,6 +48,10 @@ void videoResetTextureCache(void);
|
||||
/* Current FPS (measured). */
|
||||
float videoGetFPS(void);
|
||||
|
||||
/* Snapshot live window geometry into the config vars (call before configSave
|
||||
* on a clean exit). No-op if the window isn't up. */
|
||||
void videoSaveWindowState(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -38,10 +38,59 @@
|
||||
extern void mainproc(void *args);
|
||||
extern OSThread mainThread; /* src/init.c:75 */
|
||||
|
||||
/* name:number pairs for the 21 solo levels (matches tools_pc/level_sweep.sh
|
||||
* and playtest.sh --list). boss.c decodes -level_XX as d0*10 + d1 - 0x210. */
|
||||
static const struct { const char *name; const char *num; } kSoloLevels[] = {
|
||||
{"Dam","33"}, {"Facility","34"}, {"Runway","35"}, {"Surface1","36"},
|
||||
{"Bunker1","09"}, {"Silo","20"}, {"Frigate","26"}, {"Surface2","43"},
|
||||
{"Bunker2","27"}, {"Statue","22"}, {"Archives","24"}, {"Streets","29"},
|
||||
{"Depot","30"}, {"Train","25"}, {"Jungle","37"}, {"Control","23"},
|
||||
{"Caverns","39"}, {"Cradle","41"}, {"Aztec","28"}, {"Egypt","32"},
|
||||
{"Cuba","54"},
|
||||
};
|
||||
|
||||
static void portPrintVersion(void)
|
||||
{
|
||||
printf("GoldenEye 007 PC port\n"
|
||||
" rom : %s\n"
|
||||
" platform : %s\n"
|
||||
" build : %s\n",
|
||||
GE007_ROMID, GE007_TARGET_PLATFORM, GE007_VERSION_HASH);
|
||||
}
|
||||
|
||||
static void portPrintHelp(const char *argv0)
|
||||
{
|
||||
portPrintVersion();
|
||||
printf("\nusage: %s [options] [-level_XX]\n\n"
|
||||
" --help this message\n"
|
||||
" --version build id only\n"
|
||||
" -level_XX boot straight into a solo level (per-level\n"
|
||||
" memory pools are auto-injected)\n\n"
|
||||
"config: ge007.ini in the data dir (written on first run).\n\n"
|
||||
"solo levels (-level_XX):\n", argv0 ? argv0 : "ge007");
|
||||
for (size_t i = 0; i < sizeof(kSoloLevels) / sizeof(kSoloLevels[0]); ++i) {
|
||||
printf(" %-10s -level_%s\n", kSoloLevels[i].name, kSoloLevels[i].num);
|
||||
}
|
||||
}
|
||||
|
||||
static void portAtExit(void)
|
||||
{
|
||||
/* Clean-exit only (exit(0) from videoPumpEvents). Crash/fatal paths call
|
||||
* abort(), which does not run atexit handlers. */
|
||||
videoSaveWindowState();
|
||||
configSave();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
sysSetArgs(argc, argv);
|
||||
|
||||
if (sysArgCheck("--version")) { portPrintVersion(); return 0; }
|
||||
if (sysArgCheck("--help") || sysArgCheck("-h")) {
|
||||
portPrintHelp(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sysLogPrintf(LOG_INFO, "GoldenEye 007 PC port starting "
|
||||
"(%s, %s)", GE007_ROMID, GE007_VERSION_HASH);
|
||||
|
||||
@@ -50,6 +99,7 @@ int main(int argc, char **argv)
|
||||
|
||||
/* 1. Platform + config + filesystem. */
|
||||
configLoad();
|
||||
atexit(portAtExit); /* persist config + window geometry on clean exit */
|
||||
|
||||
/* 2. Load the ROM and map segments. */
|
||||
if (romdataInit() != 0) {
|
||||
|
||||
+58
-6
@@ -57,6 +57,18 @@ static int cfgMSAA = 1; /* 1/2/4/8 samples; 1 = off
|
||||
static int cfgTexFilter = 1; /* 0 = nearest (crisp), 1 = bilinear */
|
||||
static int cfgFullscreen = 0; /* 0 = windowed, 1 = borderless fullscreen */
|
||||
|
||||
/*
|
||||
* [Window] persistence. Defaults are sentinels that reproduce the old
|
||||
* hardcoded behaviour (native size, centered): W/H = 0 -> native, X/Y = -1 ->
|
||||
* let SDL centre the window. videoSaveWindowState() writes the live geometry
|
||||
* back into these on a clean exit (see main.c's atexit handler).
|
||||
*/
|
||||
static int cfgWinW = 0;
|
||||
static int cfgWinH = 0;
|
||||
static int cfgWinX = -1;
|
||||
static int cfgWinY = -1;
|
||||
static int cfgWinMax = 0;
|
||||
|
||||
PD_CONSTRUCTOR static void videoConfigInit(void)
|
||||
{
|
||||
configRegisterInt("Video.VSync", &cfgVSync, 0, 1);
|
||||
@@ -64,6 +76,11 @@ PD_CONSTRUCTOR static void videoConfigInit(void)
|
||||
configRegisterInt("Video.MSAA", &cfgMSAA, 1, 8);
|
||||
configRegisterInt("Video.TextureFilter", &cfgTexFilter, 0, 1);
|
||||
configRegisterInt("Video.Fullscreen", &cfgFullscreen, 0, 1);
|
||||
configRegisterInt("Window.Width", &cfgWinW, 0, 16384);
|
||||
configRegisterInt("Window.Height", &cfgWinH, 0, 16384);
|
||||
configRegisterInt("Window.X", &cfgWinX, -1, 16384);
|
||||
configRegisterInt("Window.Y", &cfgWinY, -1, 16384);
|
||||
configRegisterInt("Window.Maximized", &cfgWinMax, 0, 1);
|
||||
}
|
||||
|
||||
static u32 frames = 0;
|
||||
@@ -88,19 +105,23 @@ int videoInit(void)
|
||||
/* MSAA: snap the requested sample count down to a supported power of two. */
|
||||
gfx_msaa_level = cfgMSAA >= 8 ? 8 : cfgMSAA >= 4 ? 4 : cfgMSAA >= 2 ? 2 : 1;
|
||||
|
||||
int winW = cfgWinW > 0 ? cfgWinW : GE_NATIVE_W;
|
||||
int winH = cfgWinH > 0 ? cfgWinH : GE_NATIVE_H;
|
||||
int havePos = (cfgWinX >= 0 && cfgWinY >= 0);
|
||||
|
||||
struct GfxInitSettings set = {
|
||||
.wapi = wmAPI,
|
||||
.rapi = renderingAPI,
|
||||
.window_settings = {
|
||||
.title = "GoldenEye 007",
|
||||
.width = GE_NATIVE_W,
|
||||
.height = GE_NATIVE_H,
|
||||
.x = 100,
|
||||
.y = 100,
|
||||
.width = winW,
|
||||
.height = winH,
|
||||
.x = havePos ? cfgWinX : 100,
|
||||
.y = havePos ? cfgWinY : 100,
|
||||
.fullscreen = cfgFullscreen != 0,
|
||||
.fullscreen_is_exclusive = false,
|
||||
.maximized = false,
|
||||
.centered = true,
|
||||
.maximized = cfgWinMax != 0,
|
||||
.centered = !havePos,
|
||||
.allow_hidpi = false,
|
||||
},
|
||||
};
|
||||
@@ -292,6 +313,37 @@ float videoGetFPS(void)
|
||||
return vidAvgFPS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Snapshot the current window geometry into the [Window] / [Video] config
|
||||
* vars so the next configSave() persists it. Called from main.c's atexit
|
||||
* handler (runs on the host thread, which owns the window). A maximized or
|
||||
* fullscreen window keeps its last restored size/pos on disk; only the
|
||||
* flag is updated.
|
||||
*/
|
||||
void videoSaveWindowState(void)
|
||||
{
|
||||
if (!initDone || !wmAPI) {
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t fs = wmAPI->get_fullscreen_state ? wmAPI->get_fullscreen_state() : 0;
|
||||
int32_t mx = wmAPI->get_maximized_state ? wmAPI->get_maximized_state() : 0;
|
||||
cfgFullscreen = fs ? 1 : 0;
|
||||
cfgWinMax = mx ? 1 : 0;
|
||||
|
||||
if (!fs && !mx && wmAPI->get_dimensions) {
|
||||
uint32_t w = 0, h = 0;
|
||||
int32_t x = 0, y = 0;
|
||||
wmAPI->get_dimensions(&w, &h, &x, &y);
|
||||
if (w > 0 && h > 0) {
|
||||
cfgWinW = (int)w;
|
||||
cfgWinH = (int)h;
|
||||
cfgWinX = x < 0 ? 0 : x;
|
||||
cfgWinY = y < 0 ? 0 : y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void videoUpdateNativeResolution(s32 w, s32 h)
|
||||
{
|
||||
if (w <= 0 || h <= 0) {
|
||||
|
||||
Reference in new issue
Block a user