void RebindInputState (int templat, int control, int index) { VCONTROL_GESTURE g; char keybuf[40], valbuf[40]; keybuf[39] = valbuf[39] = '\0'; if (templat >= num_templ || control >= num_flight || index >= MAX_FLIGHT_ALTERNATES) { log_add (log_Warning, "RebindInputState(): invalid control index"); return; } /* Remove the old binding on this spot */ RemoveInputState (templat, control, index); /* Wait for the next interesting bit of user input */ VControl_ClearGesture (); while (!VControl_GetLastGesture (&g)) { TaskSwitch (); } /* And now, add the new binding. */ VControl_AddGestureBinding (&g, (int *)(flight_vec + templat * num_flight + control)); *CONTROL_PTR(templat, control, index) = g; snprintf (keybuf, 39, "keys.%d.%s.%d", templat+1, flight_res_names[control], index+1); VControl_DumpGesture (valbuf, 39, &g); res_PutString (keybuf, valbuf); }
int main (int argc, char *argv[]) { struct options_struct options = { /* .logFile = */ NULL, /* .runMode = */ runMode_normal, /* .gfxdriver = */ TFB_GFXDRIVER_SDL_PURE, /* .gfxflags = */ 0, /* .soundDriver = */ audio_DRIVER_MIXSDL, /* .soundFlags = */ audio_QUALITY_MEDIUM, /* .width = */ 640, /* .height = */ 480, /* .configDir = */ NULL, /* .contentDir = */ NULL, /* .addons = */ NULL, /* .numAddons = */ 0, /* .gammaSet = */ 0, /* .gamma = */ 0.0f, /* .whichMusic = */ OPT_3DO, /* .whichCoarseScan = */ OPT_PC, /* .whichMenu = */ OPT_PC, /* .whichFont = */ OPT_PC, /* .whichIntro = */ OPT_3DO, /* .whichShield = */ OPT_PC, /* .smoothScroll = */ OPT_PC, /* .meleeScale = */ TFB_SCALE_TRILINEAR, /* .subtitles = */ TRUE, /* .stereoSFX = */ FALSE, /* .musicVolumeScale = */ 1.0f, /* .sfxVolumeScale = */ 1.0f, /* .speechVolumeScale = */ 1.0f, }; int optionsResult; log_init (15); optionsResult = preParseOptions (argc, argv, &options); if (optionsResult != 0) { // TODO: various uninitialisations return optionsResult; } if (options.logFile != NULL) { int i; freopen (options.logFile, "w", stderr); for (i = 0; i < argc; ++i) log_add (log_User, "argv[%d] = [%s]", i, argv[i]); } if (options.runMode == runMode_version) { printf ("%d.%d.%d%s\n", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION); log_showBox (false, false); return EXIT_SUCCESS; } log_add (log_User, "The Ur-Quan Masters v%d.%d.%d%s (compiled %s %s)\n" "This software comes with ABSOLUTELY NO WARRANTY;\n" "for details see the included 'COPYING' file.\n", UQM_MAJOR_VERSION, UQM_MINOR_VERSION, UQM_PATCH_VERSION, UQM_EXTRA_VERSION, __DATE__, __TIME__); #ifdef NETPLAY log_add (log_User, "Netplay protocol version %d.%d. Requiring remote " "UQM version %d.%d.%d.", NETPLAY_PROTOCOL_VERSION_MAJOR, NETPLAY_PROTOCOL_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_MAJOR, NETPLAY_MIN_UQM_VERSION_MINOR, NETPLAY_MIN_UQM_VERSION_PATCH); #endif if (options.runMode == runMode_usage) { usage (stdout, &options); log_showBox (true, false); return EXIT_SUCCESS; } /* mem_init () uses mutexes. Mutex creation cannot use the memory system until the memory system is rewritten to rely on a thread-safe allocator. */ TFB_PreInit (); mem_init (); InitThreadSystem (); log_initThreads (); initIO (); prepareConfigDir (options.configDir); PlayerOne = CONTROL_TEMPLATE_KB_1; PlayerTwo = CONTROL_TEMPLATE_JOY_1; // Fill in the options struct based on uqm.cfg res_LoadFilename (configDir, "uqm.cfg"); if (res_HasKey ("config.reswidth")) { options.width = res_GetInteger ("config.reswidth"); } if (res_HasKey ("config.resheight")) { options.height = res_GetInteger ("config.resheight"); } if (res_HasKey ("config.alwaysgl")) { if (res_GetBoolean ("config.alwaysgl")) { options.gfxDriver = TFB_GFXDRIVER_SDL_OPENGL; } } if (res_HasKey ("config.usegl")) { options.gfxDriver = res_GetBoolean ("config.usegl") ? TFB_GFXDRIVER_SDL_OPENGL : TFB_GFXDRIVER_SDL_PURE; } if (res_HasKey ("config.scaler")) { const char *optarg = res_GetString ("config.scaler"); if (!strcmp (optarg, "bilinear")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_BILINEAR; else if (!strcmp (optarg, "biadapt")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPT; else if (!strcmp (optarg, "biadv")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_BIADAPTADV; else if (!strcmp (optarg, "triscan")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_TRISCAN; else if (!strcmp (optarg, "hq")) options.gfxFlags |= TFB_GFXFLAGS_SCALE_HQXX; } if (res_HasKey ("config.scanlines") && res_GetBoolean ("config.scanlines")) { options.gfxFlags |= TFB_GFXFLAGS_SCANLINES; } if (res_HasKey ("config.fullscreen") && res_GetBoolean ("config.fullscreen")) { options.gfxFlags |= TFB_GFXFLAGS_FULLSCREEN; } if (res_HasKey ("config.subtitles")) { options.subTitles = res_GetBoolean ("config.subtitles"); } if (res_HasKey ("config.textmenu")) { options.whichMenu = res_GetBoolean ("config.textmenu") ? OPT_PC : OPT_3DO; } if (res_HasKey ("config.textgradients")) { options.whichFonts = res_GetBoolean ("config.textgradients") ? OPT_PC : OPT_3DO; } if (res_HasKey ("config.iconicscan")) { options.whichCoarseScan = res_GetBoolean ("config.iconicscan") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.smoothscroll")) { options.smoothScroll = res_GetBoolean ("config.smoothscroll") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.3domusic")) { options.whichMusic = res_GetBoolean ("config.3domusic") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.3domovies")) { options.whichIntro = res_GetBoolean ("config.3domovies") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.showfps") && res_GetBoolean ("config.showfps")) { options.gfxFlags |= TFB_GFXFLAGS_SHOWFPS; } if (res_HasKey ("config.smoothmelee")) { options.meleeScale = res_GetBoolean ("config.smoothmelee") ? TFB_SCALE_TRILINEAR : TFB_SCALE_STEP; } if (res_HasKey ("config.positionalsfx")) { options.stereoSFX = res_GetBoolean ("config.positionalsfx"); } if (res_HasKey ("config.audiodriver")) { const char *driverstr = res_GetString ("config.audiodriver"); if (!strcmp (driverstr, "openal")) { options.soundDriver = audio_DRIVER_OPENAL; } else if (!strcmp (driverstr, "none")) { options.soundDriver = audio_DRIVER_NOSOUND; options.speechVolumeScale = 0.0f; } else if (!strcmp (driverstr, "mixsdl")) { options.soundDriver = audio_DRIVER_MIXSDL; } else { /* Can't figure it out, leave as initial default */ } } if (res_HasKey ("config.audioquality")) { const char *qstr = res_GetString ("config.audioquality"); if (!strcmp (qstr, "low")) { options.soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_HIGH); options.soundFlags |= audio_QUALITY_LOW; } else if (!strcmp (qstr, "medium")) { options.soundFlags &= ~(audio_QUALITY_HIGH | audio_QUALITY_LOW); options.soundFlags |= audio_QUALITY_MEDIUM; } else if (!strcmp (qstr, "high")) { options.soundFlags &= ~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW); options.soundFlags |= audio_QUALITY_HIGH; } else { /* Can't figure it out, leave as initial default */ } } if (res_HasKey ("config.pulseshield")) { options.whichShield = res_GetBoolean ("config.pulseshield") ? OPT_3DO : OPT_PC; } if (res_HasKey ("config.player1control")) { PlayerOne = res_GetInteger ("config.player1control"); /* This is an unsigned, so no < 0 check is necessary */ if (PlayerOne >= NUM_TEMPLATES) { log_add (log_Error, "Illegal control template '%d' for Player One.", PlayerOne); PlayerOne = CONTROL_TEMPLATE_KB_1; } } if (res_HasKey ("config.player2control")) { /* This is an unsigned, so no < 0 check is necessary */ PlayerTwo = res_GetInteger ("config.player2control"); if (PlayerTwo >= NUM_TEMPLATES) { log_add (log_Error, "Illegal control template '%d' for Player Two.", PlayerTwo); PlayerTwo = CONTROL_TEMPLATE_JOY_1; } } if (res_HasKey ("config.musicvol")) { parseVolume (res_GetString ("config.musicvol"), &options.musicVolumeScale, "music volume"); } if (res_HasKey ("config.sfxvol")) { parseVolume (res_GetString ("config.sfxvol"), &options.sfxVolumeScale, "SFX volume"); } if (res_HasKey ("config.speechvol")) { parseVolume (res_GetString ("config.speechvol"), &options.speechVolumeScale, "speech volume"); } { /* init control template names */ static const char* defaultNames[] = { "Arrows", "WASD", "Arrows (2)", "ESDF", "Joystick 1", "Joystick 2" }; int i; for (i = 0; i < 6; ++i) { char cfgkey[64]; snprintf(cfgkey, sizeof(cfgkey), "config.keys.%d.name", i + 1); cfgkey[sizeof(cfgkey) - 1] = '\0'; if (res_HasKey (cfgkey)) { strncpy (input_templates[i].name, res_GetString (cfgkey), 30); input_templates[i].name[29] = 0; } else { strcpy (input_templates[i].name, defaultNames[i]); res_PutString (cfgkey, input_templates[i].name); } } } optionsResult = parseOptions (argc, argv, &options); if (optionsResult != 0) { // TODO: various uninitialisations return optionsResult; } /* TODO: Once threading is gone, these become local variables again. In the meantime, they must be global so that initAudio (in StarCon2Main) can see them. initAudio needed to be moved there because calling AssignTask in the main thread doesn't work */ snddriver = options.soundDriver; soundflags = options.soundFlags; // Fill in global variables: optWhichMusic = options.whichMusic; optWhichCoarseScan = options.whichCoarseScan; optWhichMenu = options.whichMenu; optWhichFonts = options.whichFonts; optWhichIntro = options.whichIntro; optWhichShield = options.whichShield; optSmoothScroll = options.smoothScroll; optMeleeScale = options.meleeScale; optSubtitles = options.subTitles; optStereoSFX = options.stereoSFX; musicVolumeScale = options.musicVolumeScale; sfxVolumeScale = options.sfxVolumeScale; speechVolumeScale = options.speechVolumeScale; prepareContentDir (options.contentDir, options.addons); HFree ((void *) options.addons); prepareMeleeDir (); prepareSaveDir (); initTempDir (); InitTimeSystem (); InitTaskSystem (); #ifdef NETPLAY Network_init (); Alarm_init (); Callback_init (); NetManager_init (); #endif GraphicsLock = CreateMutex ("Graphics", SYNC_CLASS_TOPLEVEL | SYNC_CLASS_VIDEO); TFB_InitGraphics (options.gfxDriver, options.gfxFlags, options.width, options.height); if (options.gammaSet) TFB_SetGamma (options.gamma); InitColorMaps (); init_communication (); /* TODO: Once threading is gone, restore initAudio here. initAudio calls AssignTask, which currently blocks on ProcessThreadLifecycles... */ // initAudio (snddriver, soundflags); TFB_InitInput (TFB_INPUTDRIVER_SDL, 0); StartThread (Starcon2Main, NULL, 1024, "Starcon2Main"); for (;;) { TFB_ProcessEvents (); ProcessThreadLifecycles (); TFB_FlushGraphics (); } unInitTempDir (); uninitIO (); #ifdef NETPLAY Network_uninit (); #endif return EXIT_SUCCESS; }