Refactor main loop somewhat

This commit is contained in:
UnknownShadow200 2025-07-09 07:53:59 +10:00
parent 23aee471e5
commit 01c2e1c3fd
7 changed files with 107 additions and 68 deletions

View File

@ -61,6 +61,7 @@ ifeq ($(PLAT),web)
CFLAGS = -g CFLAGS = -g
LDFLAGS = -g -s WASM=1 -s NO_EXIT_RUNTIME=1 -s ABORTING_MALLOC=0 -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=256Kb --js-library $(SOURCE_DIR)/interop_web.js LDFLAGS = -g -s WASM=1 -s NO_EXIT_RUNTIME=1 -s ABORTING_MALLOC=0 -s ALLOW_MEMORY_GROWTH=1 -s TOTAL_STACK=256Kb --js-library $(SOURCE_DIR)/interop_web.js
BUILD_DIR = build/web BUILD_DIR = build/web
BEARSSL = 0
endif endif
ifeq ($(PLAT),mingw) ifeq ($(PLAT),mingw)

View File

@ -44,7 +44,7 @@
struct _GameData Game; struct _GameData Game;
static cc_uint64 frameStart; static cc_uint64 frameStart;
cc_bool Game_UseCPEBlocks; cc_bool Game_UseCPEBlocks, Game_Running;
struct RayTracer Game_SelectedPos; struct RayTracer Game_SelectedPos;
int Game_ViewDistance = DEFAULT_VIEWDIST; int Game_ViewDistance = DEFAULT_VIEWDIST;
@ -53,7 +53,6 @@ int Game_MaxViewDistance = DEFAULT_MAX_VIEWDIST;
int Game_FpsLimit, Game_Vertices; int Game_FpsLimit, Game_Vertices;
cc_bool Game_SimpleArmsAnim; cc_bool Game_SimpleArmsAnim;
static cc_bool gameRunning;
static float gfx_minFrameMs; static float gfx_minFrameMs;
static cc_bool autoPause; static cc_bool autoPause;
@ -410,7 +409,7 @@ static void LoadPlugins(void) {
static void LoadPlugins(void) { } static void LoadPlugins(void) { }
#endif #endif
static void Game_PendingClose(void* obj) { gameRunning = false; } static void Game_PendingClose(void* obj) { Game_Running = false; }
static void Game_Load(void) { static void Game_Load(void) {
struct IGameComponent* comp; struct IGameComponent* comp;
Game_UpdateDimensions(); Game_UpdateDimensions();
@ -844,8 +843,7 @@ static CC_INLINE void Game_RenderFrame(void) {
if (gfx_minFrameMs) LimitFPS(); if (gfx_minFrameMs) LimitFPS();
} }
void Game_Free(void) {
static void Game_Free(void) {
struct IGameComponent* comp; struct IGameComponent* comp;
/* Most components will call OnContextLost in their Free functions */ /* Most components will call OnContextLost in their Free functions */
/* Set to false so components will always free managed textures too */ /* Set to false so components will always free managed textures too */
@ -858,7 +856,7 @@ static void Game_Free(void) {
if (comp->Free) comp->Free(); if (comp->Free) comp->Free();
} }
gameRunning = false; Game_Running = false;
Logger_WarnFunc = Logger_DialogWarn; Logger_WarnFunc = Logger_DialogWarn;
Gfx_Free(); Gfx_Free();
Options_SaveIfChanged(); Options_SaveIfChanged();
@ -867,7 +865,7 @@ static void Game_Free(void) {
#ifdef CC_BUILD_WEB #ifdef CC_BUILD_WEB
void Game_DoFrame(void) { void Game_DoFrame(void) {
if (gameRunning) { if (Game_Running) {
Game_RenderFrame(); Game_RenderFrame();
} else if (tasksCount) { } else if (tasksCount) {
Game_Free(); Game_Free();
@ -881,7 +879,7 @@ static void Game_RunLoop(void) {
} }
cc_bool Game_ShouldClose(void) { cc_bool Game_ShouldClose(void) {
if (!gameRunning) return true; if (!Game_Running) return true;
if (Server.IsSinglePlayer) { if (Server.IsSinglePlayer) {
/* Close if map was saved within last 5 seconds */ /* Close if map was saved within last 5 seconds */
@ -895,15 +893,15 @@ cc_bool Game_ShouldClose(void) {
} }
#else #else
static void Game_RunLoop(void) { static void Game_RunLoop(void) {
while (gameRunning) while (Game_Running)
{ {
Game_RenderFrame(); Game_RenderFrame();
} }
Game_Free();
} }
#endif #endif
void Game_Setup(const cc_string* title) { void Game_Setup(void) {
cc_string title; char titleBuffer[STRING_SIZE];
int width = Options_GetInt(OPT_WINDOW_WIDTH, 0, DisplayInfo.Width, 0); int width = Options_GetInt(OPT_WINDOW_WIDTH, 0, DisplayInfo.Width, 0);
int height = Options_GetInt(OPT_WINDOW_HEIGHT, 0, DisplayInfo.Height, 0); int height = Options_GetInt(OPT_WINDOW_HEIGHT, 0, DisplayInfo.Height, 0);
@ -913,19 +911,21 @@ void Game_Setup(const cc_string* title) {
if (DisplayInfo.Width < 854) width = 640; if (DisplayInfo.Width < 854) width = 640;
} }
String_InitArray(title, titleBuffer);
String_Format2(&title, "%c (%s)", GAME_APP_TITLE, &Game_Username);
Window_Create3D(width, height); Window_Create3D(width, height);
Window_SetTitle(title); Window_SetTitle(&title);
Window_Show(); Window_Show();
gameRunning = true; Game_Running = true;
Game.CurrentState = 0; Game.CurrentState = 0;
Game_Load(); Game_Load();
Event_RaiseVoid(&WindowEvents.Resized); Event_RaiseVoid(&WindowEvents.Resized);
frameStart = Stopwatch_Measure();
} }
void Game_Run(void) { void Game_Run(void) {
frameStart = Stopwatch_Measure();
Game_RunLoop(); Game_RunLoop();
Window_Destroy();
} }

View File

@ -24,7 +24,7 @@ CC_VAR extern struct _GameData {
} Game; } Game;
extern struct RayTracer Game_SelectedPos; extern struct RayTracer Game_SelectedPos;
extern cc_bool Game_UseCPEBlocks; extern cc_bool Game_UseCPEBlocks, Game_Running;
extern cc_string Game_Username; extern cc_string Game_Username;
extern cc_string Game_Mppass; extern cc_string Game_Mppass;
@ -124,10 +124,12 @@ cc_bool Game_ValidateBitmap(const cc_string* file, struct Bitmap* bmp);
/* NOTE: Game_ValidateBitmap should nearly always be used instead of this */ /* NOTE: Game_ValidateBitmap should nearly always be used instead of this */
cc_bool Game_ValidateBitmapPow2(const cc_string* file, struct Bitmap* bmp); cc_bool Game_ValidateBitmapPow2(const cc_string* file, struct Bitmap* bmp);
/* Initialises and loads state, and creates the main window */ /* Initialises and loads state, and creates the main game window */
void Game_Setup(const cc_string* title); void Game_Setup(void);
/* Runs the main game loop until the window is closed. */ /* Runs the main game loop until the game loop is finished. */
/* (e.g. by the user pressing Quit Game, or closing the game window) */
void Game_Run(void); void Game_Run(void);
void Game_Free(void);
/* Whether the game should be allowed to automatically close */ /* Whether the game should be allowed to automatically close */
cc_bool Game_ShouldClose(void); cc_bool Game_ShouldClose(void);

View File

@ -311,7 +311,6 @@ void Launcher_Finish(void) {
cc_result res = Updater_Start(&action); cc_result res = Updater_Start(&action);
if (res) Logger_SysWarn(res, action); if (res) Logger_SysWarn(res, action);
} }
Window_Destroy();
} }

View File

@ -353,9 +353,8 @@ cc_bool Process_OpenSupported = true;
void Process_Exit(cc_result code) { void Process_Exit(cc_result code) {
/* 'Window' (i.e. the web canvas) isn't implicitly closed when process is exited */ /* 'Window' (i.e. the web canvas) isn't implicitly closed when process is exited */
if (code) Window_RequestClose(); Window_Free();
/* game normally calls exit with code = 0 due to async IndexedDB loading */ exit(code);
if (code) exit(code);
} }
extern int interop_OpenTab(const char* url); extern int interop_OpenTab(const char* url);
@ -439,11 +438,20 @@ static char** _argv;
/* webclient does some asynchronous initialisation first, then kickstarts the game after that */ /* webclient does some asynchronous initialisation first, then kickstarts the game after that */
static void web_main(void) { static void web_main(void) {
SetupProgram(_argc, _argv); SetupProgram(_argc, _argv);
cc_result res = RunProgram(_argc, _argv);
if (!res) return; switch (ProcessProgramArgs(_argc, _argv))
Window_Free(); {
Process_Exit(res); case ARG_RESULT_RUN_LAUNCHER:
String_AppendConst(&Game_Username, DEFAULT_USERNAME);
/* fallthrough */
case ARG_RESULT_RUN_GAME:
Game_Setup();
Game_Run();
return;
default:
Process_Exit(1);
}
} }
@ -451,7 +459,7 @@ extern void interop_FS_Init(void);
extern void interop_DirectorySetWorking(const char* path); extern void interop_DirectorySetWorking(const char* path);
extern void interop_AsyncDownloadTexturePack(const char* path); extern void interop_AsyncDownloadTexturePack(const char* path);
int main(int argc, char** argv) { EMSCRIPTEN_KEEPALIVE int main(int argc, char** argv) {
_argc = argc; _argv = argv; _argc = argc; _argv = argv;
/* Game loads resources asynchronously, then actually starts itself */ /* Game loads resources asynchronously, then actually starts itself */

View File

@ -76,22 +76,18 @@ void DirectUrl_ExtractAddress(const cc_string* addr, cc_string* ip, cc_string* p
*------------------------------------------------------Game setup/run-----------------------------------------------------* *------------------------------------------------------Game setup/run-----------------------------------------------------*
*#########################################################################################################################*/ *#########################################################################################################################*/
static void RunGame(void) { static void RunGame(void) {
cc_string title; char titleBuffer[STRING_SIZE]; Game_Setup();
String_InitArray(title, titleBuffer);
String_Format2(&title, "%c (%s)", GAME_APP_TITLE, &Game_Username);
Game_Setup(&title);
Game_Run(); Game_Run();
Game_Free();
Window_Destroy();
} }
static void RunLauncher(void) { static void RunLauncher(void) {
#ifdef CC_BUILD_WEB #ifndef CC_BUILD_WEB
String_AppendConst(&Game_Username, DEFAULT_USERNAME);
RunGame();
#else
Launcher_Setup(); Launcher_Setup();
Launcher_Run(); Launcher_Run();
Launcher_Finish(); Launcher_Finish();
Window_Destroy();
#endif #endif
} }
@ -160,8 +156,12 @@ static int ParseMPArgs(const cc_string* user, const cc_string* mppass, const cc_
return true; return true;
} }
static int RunProgram(int argc, char** argv) { #define ARG_RESULT_RUN_LAUNCHER 1
cc_string args[GAME_MAX_CMDARGS]; #define ARG_RESULT_RUN_GAME 2
#define ARG_RESULT_INVALID_ARGS 3
static int ProcessProgramArgs(int argc, char** argv) {
cc_string args[GAME_MAX_CMDARGS];
int argsCount = Platform_GetCommandLineArgs(argc, argv, args); int argsCount = Platform_GetCommandLineArgs(argc, argv, args);
struct ResumeInfo r; struct ResumeInfo r;
cc_string host; cc_string host;
@ -173,52 +173,81 @@ static int RunProgram(int argc, char** argv) {
//argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4); //argsCount = String_UNSAFE_Split(&rawArgs, ' ', args, 4);
#endif #endif
if (argsCount == 0) { if (argsCount == 0)
RunLauncher(); return ARG_RESULT_RUN_LAUNCHER;
#ifndef CC_BUILD_WEB #ifndef CC_BUILD_WEB
/* :[hash] - auto join server with the given hash */ /* :[hash] - auto join server with the given hash */
} else if (argsCount == 1 && args[0].buffer[0] == ':') { if (argsCount == 1 && args[0].buffer[0] == ':') {
args[0] = String_UNSAFE_SubstringAt(&args[0], 1); args[0] = String_UNSAFE_SubstringAt(&args[0], 1);
String_Copy(&Launcher_AutoHash, &args[0]); String_Copy(&Launcher_AutoHash, &args[0]);
RunLauncher(); return ARG_RESULT_RUN_LAUNCHER;
}
/* --resume - try to resume to last server */ /* --resume - try to resume to last server */
} else if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_RESUME_ARG)) { if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_RESUME_ARG)) {
if (!Resume_Parse(&r, true)) { if (!Resume_Parse(&r, true)) {
WarnInvalidArg("No server to resume to", &args[0]); WarnInvalidArg("No server to resume to", &args[0]);
return 1; return ARG_RESULT_INVALID_ARGS;
} }
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port)) return 1; if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port))
RunGame(); return ARG_RESULT_INVALID_ARGS;
return ARG_RESULT_RUN_GAME;
}
/* --singleplayer' - run singleplayer with default user */ /* --singleplayer' - run singleplayer with default user */
} else if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_SINGLEPLAYER_ARG)) { if (argsCount == 1 && String_CaselessEqualsConst(&args[0], DEFAULT_SINGLEPLAYER_ARG)) {
Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME); Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME);
RunGame(); return ARG_RESULT_RUN_GAME;
}
/* [file path] - run singleplayer with auto loaded map */ /* [file path] - run singleplayer with auto loaded map */
} else if (argsCount == 1 && IsOpenableFile(&args[0])) { if (argsCount == 1 && IsOpenableFile(&args[0])) {
Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME); Options_Get(LOPT_USERNAME, &Game_Username, DEFAULT_USERNAME);
String_Copy(&SP_AutoloadMap, &args[0]); /* TODO: don't copy args? */ String_Copy(&SP_AutoloadMap, &args[0]); /* TODO: don't copy args? */
RunGame(); return ARG_RESULT_RUN_GAME;
}
#endif #endif
/* mc://[addr]:[port]/[user]/[mppass] - run multiplayer using direct URL form arguments */ /* mc://[addr]:[port]/[user]/[mppass] - run multiplayer using direct URL form arguments */
} else if (argsCount == 1 && DirectUrl_Claims(&args[0], &host, &r.user, &r.mppass)) { if (argsCount == 1 && DirectUrl_Claims(&args[0], &host, &r.user, &r.mppass)) {
DirectUrl_ExtractAddress(&host, &r.ip, &r.port); DirectUrl_ExtractAddress(&host, &r.ip, &r.port);
if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port)) return 1; if (!ParseMPArgs(&r.user, &r.mppass, &r.ip, &r.port))
RunGame(); return ARG_RESULT_INVALID_ARGS;
/* [user] - run multiplayer using explicit username */ return ARG_RESULT_RUN_GAME;
} else if (argsCount == 1) { }
String_Copy(&Game_Username, &args[0]);
RunGame(); /* [user] - run multiplayer using explicit username */
/* 2 to 3 arguments - unsupported at present */ if (argsCount == 1) {
} else if (argsCount < 4) { String_Copy(&Game_Username, &args[0]);
WarnMissingArgs(argsCount, args); return ARG_RESULT_RUN_GAME;
return 1; }
/* [user] [mppass] [address] [port] - run multiplayer using explicit arguments */
} else { /* 2 to 3 arguments - unsupported at present */
if (!ParseMPArgs(&args[0], &args[1], &args[2], &args[3])) return 1; if (argsCount < 4) {
RunGame(); WarnMissingArgs(argsCount, args);
return ARG_RESULT_INVALID_ARGS;
}
/* [user] [mppass] [address] [port] - run multiplayer using explicit arguments */
if (!ParseMPArgs(&args[0], &args[1], &args[2], &args[3]))
return ARG_RESULT_INVALID_ARGS;
return ARG_RESULT_RUN_GAME;
}
static int RunProgram(int argc, char** argv) {
switch (ProcessProgramArgs(argc, argv))
{
case ARG_RESULT_RUN_LAUNCHER:
RunLauncher();
return 0;
case ARG_RESULT_RUN_GAME:
RunGame();
return 0;
default:
return 1;
} }
return 0;
} }

View File

@ -209,7 +209,7 @@ static void ProcessCircleInput(int port, int axis, int x, int y, float delta) {
} }
static void ProcessPadInput(float delta) { static void ProcessPadInput(float delta) {
int port = Gamepad_Connect(0x503, PadBind_Defaults); int port = Gamepad_Connect(0x503, vita_padbinds);
SceCtrlData pad; SceCtrlData pad;
// sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that // sceCtrlReadBufferPositive is blocking (seems to block until vblank), and don't want that