Example #1
0
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);
}
Example #2
0
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;
}