Пример #1
0
int
WriteStateFile (const void *lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp)
{
	DWORD bytes = size * count;
	
	if (fp->ptr + bytes > fp->size)
	{	// dont have that much space available
		DWORD newsize = fp->ptr + bytes;
		// grab more space in advance
		if (newsize < fp->size * 3 / 2)
			newsize = fp->size * 3 / 2;

		fp->data = HRealloc (fp->data, newsize);
		if (!fp->data)
			return 0;
		
		fp->size = newsize;
		if (newsize > fp->size_hint)
			fp->size_hint = newsize;
	}
	
	if (bytes > 0)
	{
		memcpy (fp->data + fp->ptr, lpBuf, bytes);
		fp->ptr += bytes;
		if (fp->ptr > fp->used)
			fp->used = fp->ptr;
	}
	return (bytes / size);
}
Пример #2
0
static cdp_EventBind*
cdp_AllocEventBinds (cdp_EventBind* binds, uint32 ccur, uint32 cnew)
{
	cdp_EventBind* newbinds;
	uint32 newsize;

	newsize = cnew * sizeof (cdp_EventBind);
	if (binds)
		newbinds = HRealloc (binds, newsize);
	else
		newbinds = HMalloc (newsize);

	if (cnew > ccur)
		memset (newbinds + ccur, 0,
				(cnew - ccur) * sizeof (cdp_EventBind));

	return newbinds;
}
Пример #3
0
		// Number of files to try to open before giving up.
void
initTempDir (void) {
	size_t len;
	DWORD num;
	int i;
	char *tempPtr;
			// Pointer to the location in the tempDirName string where the
			// path to the temp dir ends and the dir starts.

	tempDirName = HMalloc (PATH_MAX);
	getTempDir (tempDirName, PATH_MAX - 21);
			// reserve 8 chars for dirname, 1 for slash, and 12 for filename
	len = strlen(tempDirName);

	num = ((DWORD) time (NULL));
//	num = GetTimeCounter () % 0xffffffff;
	tempPtr = tempDirName + len;
	for (i = 0; i < NUM_TEMP_RETRIES; i++)
	{
		sprintf (tempPtr, "%08x", num + i);
		if (createDirectory (tempDirName, 0700) == -1)
			continue;
		
		// Success, we've got a temp dir.
		tempDirName = HRealloc (tempDirName, len + 9);
		atexit (removeTempDir);
		if (mountTempDir (tempDirName) == -1)
			exit (EXIT_FAILURE);
		return;
	}
	
	// Failure, could not make a temporary directory.
	log_add (log_Fatal, "Fatal error: Cannot get a name for a temporary "
			"directory.");
	exit (EXIT_FAILURE);
}
Пример #4
0
// XXX: This code and the entire trackplayer are begging to be overhauled
void
SpliceTrack (UNICODE *TrackName, UNICODE *TrackText, UNICODE *TimeStamp, CallbackFunction cb)
{
    static UNICODE last_track_name[128] = "";
    static unsigned long dec_offset = 0;
#define MAX_PAGES 50
    UNICODE *pages[MAX_PAGES];
    sint32 time_stamps[MAX_PAGES];
    int num_pages;
    int page;

    if (!TrackText)
        return;

    if (!TrackName)
    {   // Appending a piece of subtitles to the last track
        int slen1, slen2;

        if (track_count == 0)
        {
            log_add (log_Warning, "SpliceTrack(): Tried to append a subtitle,"
                     " but no current track");
            return;
        }

        if (!last_sub || !last_sub->text)
        {
            log_add (log_Warning, "SpliceTrack(): Tried to append a subtitle"
                     " to a NULL string");
            return;
        }

        num_pages = SplitSubPages (TrackText, pages, time_stamps, MAX_PAGES);
        if (num_pages == 0)
        {
            log_add (log_Warning, "SpliceTrack(): Failed to parse subtitles");
            return;
        }
        // The last page's stamp is a suggested value. The track should
        // actually play to the end.
        time_stamps[num_pages - 1] = -time_stamps[num_pages - 1];

        // Add the first piece to the last subtitle page
        slen1 = strlen (last_sub->text);
        slen2 = strlen (pages[0]);
        last_sub->text = HRealloc (last_sub->text, slen1 + slen2 + 1);
        strcpy (last_sub->text + slen1, pages[0]);
        HFree (pages[0]);

        // Add the rest of the pages
        for (page = 1; page < num_pages; ++page)
        {
            TFB_SoundChunk *next_sub = find_next_page (last_sub);
            if (next_sub)
            {   // nodes prepared by previous call, just fill in the subs
                next_sub->text = pages[page];
                last_sub = next_sub;
            }
            else
            {   // probably no timestamps were provided, so need more work
                TFB_SoundDecoder *decoder = SoundDecoder_Load (contentDir,
                                            last_track_name, 4096, dec_offset, time_stamps[page]);
                if (!decoder)
                {
                    log_add (log_Warning, "SpliceTrack(): couldn't load %s", TrackName);
                    break;
                }
                dec_offset += (unsigned long)(decoder->length * 1000);
                chunks_tail->next = create_SoundChunk (decoder, sound_sample->length);
                chunks_tail = chunks_tail->next;
                chunks_tail->tag_me = 1;
                chunks_tail->track_num = track_count - 1;
                chunks_tail->text = pages[page];
                chunks_tail->callback = cb;
                // TODO: We may have to tag only one page with a callback
                //cb = NULL;
                last_sub = chunks_tail;
                sound_sample->length += decoder->length;
            }
        }
    }
    else
    {   // Adding a new track
        int num_timestamps = 0;

        utf8StringCopy (last_track_name, sizeof (last_track_name), TrackName);

        num_pages = SplitSubPages (TrackText, pages, time_stamps, MAX_PAGES);
        if (num_pages == 0)
        {
            log_add (log_Warning, "SpliceTrack(): Failed to parse sutitles");
            return;
        }
        // The last page's stamp is a suggested value. The track should
        // actually play to the end.
        time_stamps[num_pages - 1] = -time_stamps[num_pages - 1];

        if (no_page_break && track_count)
        {
            int slen1, slen2;

            slen1 = strlen (last_sub->text);
            slen2 = strlen (pages[0]);
            last_sub->text = HRealloc (last_sub->text, slen1 + slen2 + 1);
            strcpy (last_sub->text + slen1, pages[0]);
            HFree (pages[0]);
        }
        else
            track_count++;

        log_add (log_Info, "SpliceTrack(): loading %s", TrackName);

        if (TimeStamp)
        {
            num_timestamps = GetTimeStamps (TimeStamp, time_stamps) + 1;
            if (num_timestamps < num_pages)
            {
                log_add (log_Warning, "SpliceTrack(): number of timestamps"
                         " doesn't match number of pages!");
            }
            else if (num_timestamps > num_pages)
            {   // We most likely will get more subtitles appended later
                // Set the last page to the rest of the track
                time_stamps[num_timestamps - 1] = -100000;
            }
        }
        else
        {
            num_timestamps = num_pages;
        }

        // Reset the offset for the new track
        dec_offset = 0;
        for (page = 0; page < num_timestamps; ++page)
        {
            TFB_SoundDecoder *decoder = SoundDecoder_Load (contentDir,
                                        TrackName, 4096, dec_offset, time_stamps[page]);
            if (!decoder)
            {
                log_add (log_Warning, "SpliceTrack(): couldn't load %s", TrackName);
                break;
            }

            if (!sound_sample)
            {
                sound_sample = TFB_CreateSoundSample (NULL, 8, &trackCBs);
                chunks_head = create_SoundChunk (decoder, 0.0);
                chunks_tail = chunks_head;
            }
            else
            {
                chunks_tail->next = create_SoundChunk (decoder, sound_sample->length);
                chunks_tail = chunks_tail->next;
            }
            dec_offset += (unsigned long)(decoder->length * 1000);
#if 0
            log_add (log_Debug, "page (%d of %d): %d ts: %d",
                     page, num_pages,
                     dec_offset, time_stamps[page]);
#endif
            sound_sample->length += decoder->length;
            chunks_tail->track_num = track_count - 1;
            if (!no_page_break)
            {
                chunks_tail->tag_me = 1;
                if (page < num_pages)
                {
                    chunks_tail->text = pages[page];
                    last_sub = chunks_tail;
                }
                chunks_tail->callback = cb;
                // TODO: We may have to tag only one page with a callback
                //cb = NULL;
            }
            no_page_break = 0;
        }
    }
}
Пример #5
0
// decodes several tracks into one and adds it to queue
// track list is NULL-terminated
// May only be called after at least one SpliceTrack(). This is a limitation
// for the sake of timestamps, but it does not have to be so.
void
SpliceMultiTrack (UNICODE *TrackNames[], UNICODE *TrackText)
{
#define MAX_MULTI_TRACKS  20
#define MAX_MULTI_BUFFERS 100
    TFB_SoundDecoder* track_decs[MAX_MULTI_TRACKS + 1];
    int tracks;
    int slen1, slen2;

    if (!TrackText)
    {
        log_add (log_Debug, "SpliceMultiTrack(): no track text");
        return;
    }

    if (!sound_sample || !chunks_tail)
    {
        log_add (log_Warning, "SpliceMultiTrack(): Cannot be called before SpliceTrack()");
        return;
    }

    log_add (log_Info, "SpliceMultiTrack(): loading...");
    for (tracks = 0; *TrackNames && tracks < MAX_MULTI_TRACKS; TrackNames++, tracks++)
    {
        track_decs[tracks] = SoundDecoder_Load (contentDir, *TrackNames,
                                                32768, 0, - 3 * TEXT_SPEED);
        if (track_decs[tracks])
        {
            log_add (log_Info, "  track: %s, decoder: %s, rate %d format %x",
                     *TrackNames,
                     SoundDecoder_GetName (track_decs[tracks]),
                     track_decs[tracks]->frequency,
                     track_decs[tracks]->format);
            SoundDecoder_DecodeAll (track_decs[tracks]);

            chunks_tail->next = create_SoundChunk (track_decs[tracks], sound_sample->length);
            chunks_tail = chunks_tail->next;
            chunks_tail->track_num = track_count - 1;
            sound_sample->length += track_decs[tracks]->length;
        }
        else
        {
            log_add (log_Warning, "SpliceMultiTrack(): couldn't load %s\n",
                     *TrackNames);
            tracks--;
        }
    }
    track_decs[tracks] = 0; // term

    if (tracks == 0)
    {
        log_add (log_Warning, "SpliceMultiTrack(): no tracks loaded");
        return;
    }

    slen1 = strlen (last_sub->text);
    slen2 = strlen (TrackText);
    last_sub->text = HRealloc (last_sub->text, slen1 + slen2 + 1);
    strcpy (last_sub->text + slen1, TrackText);

    no_page_break = 1;
}
Пример #6
0
void
_GetConversationData (const char *path, RESOURCE_DATA *resdata)
{
	uio_Stream *fp;
	long dataLen;
	void *result;
	int n, path_len, num_data_sets;
	DWORD opos,
		slen[MAX_STRINGS], StringOffs, tot_string_size,
		clen[MAX_STRINGS], ClipOffs, tot_clip_size,
		tslen[MAX_STRINGS], TSOffs, tot_ts_size;
	char CurrentLine[1024], paths[1024], *clip_path, *ts_path,
		*strdata, *clipdata, *ts_data;
	uio_Stream *timestamp_fp = NULL;

	/* Parse out the conversation components. */
	strncpy (paths, path, 1023);
	paths[1023] = '\0';
	clip_path = strchr (paths, ':');
	if (clip_path == NULL)
	{
		ts_path = NULL;
	}
	else
	{
		*clip_path = '\0';
		clip_path++;

		ts_path = strchr (clip_path, ':');
		if (ts_path != NULL)
		{
			*ts_path = '\0';
			ts_path++;
		}
	}

	fp = res_OpenResFile (contentDir, paths, "rb");
	if (fp == NULL)
	{
		log_add (log_Warning, "Warning: Can't open '%s'", paths);
		resdata->ptr = NULL;
		return;
	}

	dataLen = LengthResFile (fp);
	log_add (log_Info, "\t'%s' -- conversation phrases -- %lu bytes", paths, dataLen);
	if (clip_path)
		log_add (log_Info, "\t'%s' -- voice clip directory", clip_path);
	else
		log_add (log_Info, "\tNo associated voice clips");
	if (ts_path)
		log_add (log_Info, "\t'%s' -- timestamps", ts_path);
	else
		log_add (log_Info, "\tNo associated timestamp file");

	
	if (dataLen == 0)
	{
		log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path);
		goto err;
	}
	
	if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0)
		goto err;
	
	if ((clipdata = HMalloc (tot_clip_size = POOL_SIZE)) == 0)
	{
		HFree (strdata);
		goto err;
	}
	ts_data = NULL;
	
	path_len = clip_path ? strlen (clip_path) : 0;

	if (ts_path && (timestamp_fp = uio_fopen (contentDir, ts_path,
			"rb")))
	{
		if ((ts_data = HMalloc (tot_ts_size = POOL_SIZE)) == 0)
			goto err;
	}
	
	opos = uio_ftell (fp);
	n = -1;
	StringOffs = ClipOffs = TSOffs = 0;
	while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1)
	{
		int l;

		if (CurrentLine[0] == '#')
		{
			char CopyLine[1024];
			char *s;

			strcpy (CopyLine, CurrentLine);
			s = strtok (&CopyLine[1], "()");
			if (s)
			{
				if (n >= 0)
				{
					while (slen[n] > 1 && 
							(strdata[StringOffs - 2] == '\n' ||
							strdata[StringOffs - 2] == '\r'))
					{
						--slen[n];
						--StringOffs;
						strdata[StringOffs - 1] = '\0';
					}
				}

				slen[++n] = 0;
				// now lets check for timestamp data
				if (timestamp_fp)
				{
					char TimeStampLine[1024], *tsptr;
					BOOLEAN ts_ok = FALSE;
					uio_fgets (TimeStampLine, sizeof (TimeStampLine), timestamp_fp);
					if (TimeStampLine[0] == '#')
					{
						tslen[n] = 0;
						if ((tsptr = strstr (TimeStampLine,s)) 
								&& (tsptr += strlen(s))
								&& (++tsptr))
						{
							ts_ok = TRUE;
							while (! strcspn(tsptr," \t\r\n") && *tsptr)
								tsptr++;
							if (*tsptr)
							{
								l = strlen (tsptr)  + 1;
								if (TSOffs + l > tot_ts_size
									&& (ts_data = HRealloc (ts_data,
										tot_ts_size += POOL_SIZE)) == 0)
								{
									HFree (strdata);
									goto err;
								}
								strcpy (&ts_data[TSOffs], tsptr);
								TSOffs += l;
								tslen[n] = l;
							}
						}
					}
					if (!ts_ok)
					{
						// timestamp data is invalid, remove all of it
						log_add (log_Warning, "Invalid timestamp data "
								"for '%s'.  Disabling timestamps", s);
						HFree (ts_data);
						ts_data = NULL;
						uio_fclose (timestamp_fp);
						timestamp_fp = NULL;
						TSOffs = 0;
					}
				}
				clen[n] = 0;
				s = strtok (NULL, " \t\r\n)");
				if (s)
				{
					l = path_len + strlen (s) + 1;
					if (ClipOffs + l > tot_clip_size
							&& (clipdata = HRealloc (clipdata,
							tot_clip_size += POOL_SIZE)) == 0)
					{
						HFree (strdata);
						goto err;
					}

					if (clip_path)
						strcpy (&clipdata[ClipOffs], clip_path);
					strcpy (&clipdata[ClipOffs + path_len], s);
					ClipOffs += l;
					clen[n] = l;
				}
			}
		}
		else if (n >= 0)
		{
			char *s;
			l = strlen (CurrentLine) + 1;
			if (StringOffs + l > tot_string_size
					&& (strdata = HRealloc (strdata,
					tot_string_size += POOL_SIZE)) == 0)
			{
				HFree (clipdata);
				goto err;
			}

			if (slen[n])
			{
				--slen[n];
				--StringOffs;
			}
			s = &strdata[StringOffs];
			slen[n] += l;
			StringOffs += l;

			strcpy (s, CurrentLine);
		}

		if ((int)uio_ftell (fp) - (int)opos >= (int)dataLen)
			break;
	}
	if (n >= 0)
	{
		while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n'
				|| strdata[StringOffs - 2] == '\r'))
		{
			--slen[n];
			--StringOffs;
			strdata[StringOffs - 1] = '\0';
		}
	}

	if (timestamp_fp)
		uio_fclose (timestamp_fp);

	result = NULL;
	num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1;
	if (++n)
	{
		int flags = 0;
		if (ClipOffs)
			flags |= HAS_SOUND_CLIPS;
		if (TSOffs)
			flags |= HAS_TIMESTAMP;
		result = AllocStringTable (n, flags);
		if (result)
		{
			int StringIndex, ClipIndex, TSIndex;
			STRING_TABLE_DESC *lpST;

			lpST = (STRING_TABLE) result;

			StringIndex = 0;
			ClipIndex = n;
			TSIndex = n * ((flags & HAS_SOUND_CLIPS) ? 2 : 1);

			StringOffs = ClipOffs = TSOffs = 0;

			for (n = 0; n < (int)lpST->size;
					++n, ++StringIndex, ++ClipIndex, ++TSIndex)
			{
				set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]);
				StringOffs += slen[n];
				if (lpST->flags & HAS_SOUND_CLIPS)
				{
					set_strtab_entry(lpST, ClipIndex, clipdata + ClipOffs, clen[n]);
					ClipOffs += clen[n];
				}
				if (lpST->flags & HAS_TIMESTAMP)
				{
					set_strtab_entry(lpST, TSIndex, ts_data + TSOffs, tslen[n]);
					TSOffs += tslen[n];
				}
			}
		}
	}
	HFree (strdata);
	HFree (clipdata);
	if (ts_data)
		HFree (ts_data);

	resdata->ptr = result;
	return;

err:
	res_CloseResFile (fp);
	resdata->ptr = NULL;

}
Пример #7
0
void *
_GetStringData (uio_Stream *fp, DWORD length)
{
	void *result;

	int n;
	DWORD opos, slen[MAX_STRINGS], StringOffs, tot_string_size;
	char CurrentLine[1024], *strdata;

	if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0)
		return (0);

	opos = uio_ftell (fp);
	n = -1;
	StringOffs = 0;
	while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1)
	{
		int l;

		if (CurrentLine[0] == '#')
		{
			char CopyLine[1024];
			char *s;

			strcpy (CopyLine, CurrentLine);
			s = strtok (&CopyLine[1], "()");
			if (s)
			{
				if (n >= 0)
				{
					while (slen[n] > 1 && 
							(strdata[StringOffs - 2] == '\n' ||
							strdata[StringOffs - 2] == '\r'))
					{
						--slen[n];
						--StringOffs;
						strdata[StringOffs - 1] = '\0';
					}
				}

				slen[++n] = 0;
			}
		}
		else if (n >= 0)
		{
			char *s;
			l = strlen (CurrentLine) + 1;
			if (StringOffs + l > tot_string_size
					&& (strdata = HRealloc (strdata,
					tot_string_size += POOL_SIZE)) == 0)
			{
				return (0);
			}

			if (slen[n])
			{
				--slen[n];
				--StringOffs;
			}
			s = &strdata[StringOffs];
			slen[n] += l;
			StringOffs += l;

			strcpy (s, CurrentLine);
		}

		if ((int)uio_ftell (fp) - (int)opos >= (int)length)
			break;
	}
	if (n >= 0)
	{
		while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n'
				|| strdata[StringOffs - 2] == '\r'))
		{
			--slen[n];
			--StringOffs;
			strdata[StringOffs - 1] = '\0';
		}
	}

	result = NULL;
	if (++n)
	{
		int flags = 0;
		result = AllocStringTable (n, flags);
		if (result)
		{
			int StringIndex;
			STRING_TABLE_DESC *lpST;

			lpST = (STRING_TABLE) result;

			StringIndex = 0;

			StringOffs = 0;

			for (n = 0; n < (int)lpST->size;
					++n, ++StringIndex)
			{
				set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]);
				StringOffs += slen[n];
			}
		}
	}
	HFree (strdata);

	return (result);
}
Пример #8
0
static int
parseOptions (int argc, char *argv[], struct options_struct *options)
{
	int optionIndex;
	BOOLEAN badArg = FALSE;

	options->addons = HMalloc (1 * sizeof (const char *));
	options->addons[0] = NULL;
	options->numAddons = 0;

	if (argc == 0)
	{
		log_add (log_Fatal, "Error: Bad command line.");
		return EXIT_FAILURE;
	}

	while (!badArg)
	{
		int c;
		optionIndex = -1;
		c = getopt_long (argc, argv, optString, longOptions, &optionIndex);
		if (c == -1)
			break;

		switch (c) {
			case 'r':
			{
				int width, height;
				if (sscanf (optarg, "%dx%d", &width, &height) != 2)
				{
					log_add (log_Fatal, "Error: invalid argument specified "
							"as resolution.");
					badArg = TRUE;
					break;
				}
				options->width = width;
				options->height = height;
				break;
			}
			case 'f':
				options->gfxFlags |= TFB_GFXFLAGS_FULLSCREEN;
				break;
			case 'o':
				options->gfxDriver = TFB_GFXDRIVER_SDL_OPENGL;
				break;
			case 'c':
				// make sure whatever was set by saved config is cleared
				options->gfxFlags &= ~TFB_GFXFLAGS_SCALE_ANY;
				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;
				else if (strcmp (optarg, "none") != 0)
				{
					InvalidArgument (optarg, "--scale or -c");
					badArg = TRUE;
				}
				break;
			case 'b':
				if (!strcmp (optarg, "smooth") || !strcmp (optarg, "3do"))
					options->meleeScale = TFB_SCALE_TRILINEAR;
				else if (!strcmp (optarg, "step") || !strcmp (optarg, "pc"))
					options->meleeScale = TFB_SCALE_STEP;
				else
				{
					InvalidArgument (optarg, "--meleezoom or -b");
					badArg = TRUE;
				}
				break;
			case 's':
				options->gfxFlags |= TFB_GFXFLAGS_SCANLINES;
				break;
			case 'p':
				options->gfxFlags |= TFB_GFXFLAGS_SHOWFPS;
				break;
			case 'n':
				options->contentDir = optarg;
				break;
			case 'M':
			{
				int err = parseVolume (optarg, &options->musicVolumeScale,
						"music volume");
				if (err)
					badArg = TRUE;
				break;
			}
			case 'S':
			{
				int err = parseVolume (optarg, &options->sfxVolumeScale,
						"sfx volume");
				if (err)
					badArg = TRUE;
				break;
			}
			case 'T':
			{
				int err = parseVolume (optarg, &options->speechVolumeScale,
						"speech volume");
				if (err)
					badArg = TRUE;
				break;
			}
			case 'q':
				if (!strcmp (optarg, "high"))
				{
					options->soundFlags &=
							~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW);
					options->soundFlags |= audio_QUALITY_HIGH;
				}
				else if (!strcmp (optarg, "medium"))
				{
					options->soundFlags &=
							~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW);
					options->soundFlags |= audio_QUALITY_MEDIUM;
				}
				else if (!strcmp (optarg, "low"))
				{
					options->soundFlags &=
							~(audio_QUALITY_MEDIUM | audio_QUALITY_LOW);
					options->soundFlags |= audio_QUALITY_LOW;
				}
				else
				{
					InvalidArgument (optarg, "--audioquality or -q");
					badArg = TRUE;
				}
				break;
			case 'u':
				options->subTitles = FALSE;
				break;
			case 'm':
			{
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						optionIndex >= 0 ? longOptions[optionIndex].name : "m",
						&options->whichMusic) == -1)
					badArg = TRUE;
				break;
			}
			case 'g':
			{
				int result = parseFloatOption (optarg, &options->gamma,
						"gamma correction");
				if (result == -1)
					badArg = TRUE;
				else
					options->gammaSet = TRUE;
				break;
			}
			case 'l':
			case 'C':
				// -l and -C are no-ops on the second pass.
				break;			
			case 'i':
			{
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						optionIndex >= 0 ? longOptions[optionIndex].name : "i",
						&options->whichIntro) == -1)
					badArg = TRUE;
				break;
			}
			case CSCAN_OPT:
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						longOptions[optionIndex].name,
						&options->whichCoarseScan) == -1)
					badArg = TRUE;
				break;
			case MENU_OPT:
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						longOptions[optionIndex].name,
						&options->whichMenu) == -1)
					badArg = TRUE;
				break;
			case FONT_OPT:
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						longOptions[optionIndex].name,
						&options->whichFonts) == -1)
					badArg = TRUE;
				break;
			case SHIELD_OPT:
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						longOptions[optionIndex].name,
						&options->whichShield) == -1)
					badArg = TRUE;
				break;
			case SCROLL_OPT:
				if (Check_PC_3DO_opt (optarg, OPT_PC | OPT_3DO,
						longOptions[optionIndex].name,
						&options->smoothScroll) == -1)
					badArg = TRUE;
				break;
			case SOUND_OPT:
				if (!strcmp (optarg, "openal"))
					options->soundDriver = audio_DRIVER_OPENAL;
				else if (!strcmp (optarg, "mixsdl"))
					options->soundDriver = audio_DRIVER_MIXSDL;
				else if (!strcmp (optarg, "none"))
				{
					options->soundDriver = audio_DRIVER_NOSOUND;
					options->speechVolumeScale = 0.0f;
				}
				else
				{
					log_add (log_Fatal, "Error: Invalid sound driver "
							"specified.");
					badArg = TRUE;
				}
				break;
			case STEREOSFX_OPT:
				options->stereoSFX = TRUE;
				break;
			case ADDON_OPT:
				options->numAddons++;
				options->addons = HRealloc ((void *) options->addons,
						(options->numAddons + 1) * sizeof (const char *));
				options->addons[options->numAddons - 1] = optarg;
				options->addons[options->numAddons] = NULL;
				break;
			case ACCEL_OPT:
				force_platform = PLATFORM_NULL;
				if (!strcmp (optarg, "mmx"))
					force_platform = PLATFORM_MMX;
				else if (!strcmp (optarg, "sse"))
					force_platform = PLATFORM_SSE;
				else if (!strcmp (optarg, "3dnow"))
					force_platform = PLATFORM_3DNOW;
				else if (!strcmp (optarg, "none"))
					force_platform = PLATFORM_C;
				else if (strcmp (optarg, "detect") != 0)
				{
					InvalidArgument (optarg, "--accel");
					badArg = TRUE;
				}
				break;
#ifdef NETPLAY
			case NETHOST1_OPT:
				netplayOptions.peer[0].isServer = false;
				netplayOptions.peer[0].host = optarg;
				break;
			case NETPORT1_OPT:
				netplayOptions.peer[0].port = optarg;
				break;
			case NETHOST2_OPT:
				netplayOptions.peer[1].isServer = false;
				netplayOptions.peer[1].host = optarg;
				break;
			case NETPORT2_OPT:
				netplayOptions.peer[1].port = optarg;
				break;
			case NETDELAY_OPT:
			{
				if (parseIntOption (optarg, &netplayOptions.inputDelay,
						"network input delay") == -1)
				{
					badArg = TRUE;
					break;
				}

				if (netplayOptions.inputDelay > 60 * BATTLE_FRAME_RATE)
				{
					log_add (log_Fatal, "Network input delay is absurdly "
							"large.");
					badArg = TRUE;
				}
				break;
			}
#endif
			default:
				log_add (log_Fatal, "Error: Invalid option '%s' not found.",
							longOptions[optionIndex].name);
				badArg = TRUE;
				break;
		}
	}

	if (optind != argc)
	{
		log_add (log_Fatal, "\nError: Extra arguments found on the command "
				"line.");
		badArg = TRUE;
	}

	if (badArg)
	{
		log_add (log_Fatal, "Run with -h to see the allowed arguments.");
		return EXIT_FAILURE;
	}

	return EXIT_SUCCESS;
}