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); }
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; }
// 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); }
// 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; } } }
// 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; }
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; }
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); }
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; }