SharedAppState shared_app_state = ZI; //////////////////////////////// //~ Write directory String InitializeAppWriteDirectory(Arena *arena, String write_dir) { TempArena scratch = BeginScratch(arena); /* Create write path */ String base_write_dir = P_GetWritePath(scratch.arena); String write_path_fmt = base_write_dir.len > 0 ? Lit("%F/%F/") : Lit("%F%F/"); String write_path = StringFormat( arena, write_path_fmt, FmtString(base_write_dir), FmtString(write_dir) ); /* Create write dir if not present */ if (!P_IsDir(write_path)) { P_MkDir(write_path); /* TODO: handle failure */ } EndScratch(scratch); return write_path; } String CatAppWritePath(Arena *arena, String filename) { SharedAppState *g = &shared_app_state; return CatString(arena, g->write_path, filename); } //////////////////////////////// //~ Default settings P_WindowSettings GetDefaultAppWindowSettings(P_Window *window) { __prof; Vec2 monitor_size = P_GetWindowMonitorSize(window); i32 width = 1280; i32 height = RoundF32ToI32(width / (f32)(DEFAULT_CAMERA_WIDTH / DEFAULT_CAMERA_HEIGHT)); i32 x = RoundF32ToI32(monitor_size.x / 2.f - width / 2); i32 y = RoundF32ToI32(monitor_size.y / 2.f - height / 2); return (P_WindowSettings) { .title = WINDOW_TITLE, .floating_x = x, .floating_y = y, .floating_width = width, .floating_height = height }; } //////////////////////////////// //~ Args /* TODO: Remove this and do real argument parsing */ AppArgList ParseAppArgs(Arena *arena, String args_str) { AppArgList result = ZI; i64 mode = 0; i64 i = 0; i64 key_start = -1; i64 key_end = -1; i64 value_start = -1; i64 value_end = -1; while (i < (i64)args_str.len) { u8 c = args_str.text[i]; switch (mode) { case 0: { if (c == '-') { mode = 1; key_start = i + 1; } ++i; } break; case 1: { if (c == '=') { key_end = i; value_start = i + 1; mode = 2; } ++i; } break; case 2: { if (c == '-' || i == (i64)args_str.len - 1) { if (c == '-') { value_end = i; } else { value_end = i + 1; } if (key_start >= 0 && key_end > key_start && key_end <= (i64)args_str.len && value_start >= 0 && value_end > value_start && value_end <= (i64)args_str.len) { String key = PushString(arena, STRING(key_end - key_start, args_str.text + key_start)); String value = PushString(arena, STRING(value_end - value_start, args_str.text + value_start)); AppArg *arg = PushStruct(arena, AppArg); arg->key = key; arg->value = value; if (result.last) { result.last->next = arg; } else { result.first = arg; } result.last = arg; ++result.count; } key_start = i + 1; mode = 1; } ++i; } break; default: break; } } return result; } //////////////////////////////// //~ Entry point void P_AppStartup(String args_str) { __prof; TempArena scratch = BeginScratchNoConflict(); SharedAppState *g = &shared_app_state; AppArgList args = ParseAppArgs(scratch.arena, args_str); String logfile_name = Lit("log.log"); String settings_file_name = Lit("settings.txt"); String connect_address = ZI; for (AppArg *arg = args.first; arg; arg = arg->next) { String key = arg->key; String value = arg->value; if (EqString(key, Lit("log"))) { logfile_name = value; } else if (EqString(key, Lit("settings"))) { settings_file_name = value; } else if (EqString(key, Lit("connect"))) { connect_address = value; } } LAX args; LAX logfile_name; LAX settings_file_name; LAX connect_address; LAX GetDefaultAppWindowSettings; #if !RtcIsEnabled /* Verify test modes aren't left on by accident in release mode */ StaticAssert(BITBUFF_DEBUG == 0); StaticAssert(BITBUFF_TEST == 0); #endif #if BITBUFF_TEST BB_Test(); #endif g->arena = AllocArena(Gibi(64)); g->write_path = InitializeAppWriteDirectory(g->arena, Lit(WRITE_DIR)); /* Startup logging */ { TempArena temp = BeginTempArena(scratch.arena); String logfile_dir = CatString(temp.arena, g->write_path, Lit("logs/")); String logfile_path = CatString(temp.arena, logfile_dir, logfile_name); P_MkDir(logfile_dir); P_LogStartup(logfile_path); P_LogInfoF("Start of logs"); EndTempArena(temp); } P_LogInfoF("App started with args \"%F\" (%F parsed)", FmtString(args_str), FmtUint(args.count)); for (AppArg *arg = args.first; arg; arg = arg->next) { P_LogInfoF("Parsed arg: key = \"%F\", value = \"%F\"", FmtString(arg->key), FmtString(arg->value)); } #if 0 /* Read window settings from file */ { TempArena temp = BeginTempArena(scratch.arena); P_WindowSettings window_settings = ZI; String settings_path = CatAppWritePath(temp.arena, settings_file_name); P_LogInfoF("Looking for settings file \"%F\"", FmtString(settings_path)); if (P_IsFile(settings_path)) { P_LogInfoF("Settings file found"); P_File settings_file = P_OpenFileRead(settings_path); String file_data = P_ReadFile(temp.arena, settings_file); P_CloseFIle(settings_file); P_LogInfoF("Deserializing settings file data: %F", FmtString(file_data)); String error = ZI; P_WindowSettings *deser = SETTINGS_WindowSettingsFromString(temp.arena, file_data, &error); if (error.len > 0) { P_LogInfoF("Failed to load settings file with error - %F", FmtString(error)); String msg = StringFormat(temp.arena, Lit( "Failed to loading settings file \"%F\":\n" "------------\n" "%F\n" "------------\n" "To stop this error from appearing, either fix the issue above or delete the file from the system." ), FmtString(settings_path), FmtString(error)); P_Panic(msg); } P_LogInfoF("Settings file loaded successfully"); window_settings = *deser; } else { P_LogInfoF("Settings file not found, loading default"); window_settings = GetDefaultAppWindowSettings(window); } PushStringToBuffer(StringFromArray(window_settings.title), Lit(WINDOW_TITLE)); P_UpdateWindowSettings(window, &window_settings); EndTempArena(temp); } #endif /* Global systems */ RES_Startup(); W_Startup(); GPU_Startup(); /* Subsystems */ AC_StartupReceipt asset_cache_sr = AC_Startup(); TTF_Startup(); S_StartupReceipt sprite_sr = S_Startup(); MIX_StartupReceipt mixer_sr = MIX_Startup(); D_StartupReceipt draw_sr = D_Startup(); /* Interface systems */ SimStartupReceipt sim_sr = SimStartup(); PB_StartupReceipt playback_sr = PB_Startup(&mixer_sr); UserStartupReceipt user_sr = StartupUser(&sprite_sr, &draw_sr, &asset_cache_sr, &mixer_sr, &sim_sr, connect_address); LAX user_sr; LAX playback_sr; #if 0 /* Write window settings to file */ { __profn("Write settings file"); TempArena temp = BeginTempArena(scratch.arena); String window_settings_path = CatAppWritePath(temp.arena, settings_file_name); P_WindowSettings settings = P_GetWindowSettings(window); String str = SETTINGS_StringFromWindowSettings(temp.arena, &settings); P_LogInfoF("Serialized window settings: %F", FmtString(str)); P_LogInfoF("Writing settings file to path \"%F\"", FmtString(window_settings_path)); P_File settings_file = P_OpenFileWrite(window_settings_path); P_WriteFile(settings_file, str); P_CloseFIle(settings_file); P_LogInfoF("Finished writing settings file"); EndTempArena(temp); } #endif #if 0 P_ReleaseWindow(window); #endif //P_LogInfoF("Program exited normally"); EndScratch(scratch); }