// //////////////////////////////////////////////////////////////////////////// // return a players name. const char* getPlayerName(int player) { ASSERT_OR_RETURN(NULL, player < MAX_PLAYERS , "Wrong player index: %u", player); if (game.type != CAMPAIGN) { if (strcmp(playerName[player], "") != 0) { return (char*)&playerName[player]; } } if (strlen(NetPlay.players[player].name) == 0) { // make up a name for this player. return getPlayerColourName(player); } else if (NetPlay.players[player].ai >= 0 && !NetPlay.players[player].allocated) { static char names[MAX_PLAYERS][StringSize]; // Must be static, since the getPlayerName() return value is used in tool tips... Long live the widget system. // Add colour to player name. sstrcpy(names[player], getPlayerColourName(player)); sstrcat(names[player], "-"); sstrcat(names[player], NetPlay.players[player].name); return names[player]; } return NetPlay.players[player].name; }
static void poptPrintHelp(poptContext ctx, FILE *output, WZ_DECL_UNUSED int unused) { int i; fprintf(output, "Usage: %s [OPTION...]\n", ctx->argv[0]); for (i = 0; i < ctx->size; i++) { char txt[128]; if (ctx->table[i].short_form != '\0') { ssprintf(txt, " -%c, --%s", ctx->table[i].short_form, ctx->table[i].string); } else { ssprintf(txt, " --%s", ctx->table[i].string); } if (ctx->table[i].argument) { sstrcat(txt, "="); sstrcat(txt, ctx->table[i].argDescrip); } fprintf(output, "%-40s", txt); if (ctx->table[i].descrip) { fprintf(output, "%s", ctx->table[i].descrip); } fprintf(output, "\n"); } }
static void poptPrintHelp(poptContext ctx, FILE *output, bool show_all) { fprintf(output, "Usage: %s [OPTION...]\n", ctx->argv[0]); for (int i = 0; i < ctx->size; i++) { char txt[128]; if (ctx->table[i].hidden && !show_all) { continue; } if (ctx->table[i].short_form != '\0') { ssprintf(txt, " -%c, --%s", ctx->table[i].short_form, ctx->table[i].string); } else { ssprintf(txt, " --%s", ctx->table[i].string); } if (ctx->table[i].argument) { sstrcat(txt, "="); sstrcat(txt, ctx->table[i].argDescrip); } fprintf(output, "%-40s", txt); if (ctx->table[i].descrip) { fprintf(output, "%s", ctx->table[i].descrip); } fprintf(output, "\n"); } }
void printConsoleNameChange(const char *oldName, const char *newName) { char msg[MAX_CONSOLE_STRING_LENGTH]; // Player changed name. sstrcpy(msg, oldName); // Old name. sstrcat(msg, " → "); // Separator sstrcat(msg, newName); // New name. addConsoleMessage(msg, DEFAULT_JUSTIFY, selectedPlayer); // display }
// Write a message to the console. bool recvTextMessage(NETQUEUE queue) { UDWORD playerIndex; char msg[MAX_CONSOLE_STRING_LENGTH]; char newmsg[MAX_CONSOLE_STRING_LENGTH]; memset(msg, 0x0, sizeof(msg)); memset(newmsg, 0x0, sizeof(newmsg)); NETbeginDecode(queue, NET_TEXTMSG); // Who this msg is from NETuint32_t(&playerIndex); // The message to send NETstring(newmsg, MAX_CONSOLE_STRING_LENGTH); NETend(); if (whosResponsible(playerIndex) != queue.index) { playerIndex = queue.index; // Fix corrupted playerIndex. } if (playerIndex >= MAX_PLAYERS || (!NetPlay.players[playerIndex].allocated && NetPlay.players[playerIndex].ai == AI_OPEN)) { return false; } sstrcpy(msg, NetPlay.players[playerIndex].name); // Seperator sstrcat(msg, ": "); // Add message sstrcat(msg, newmsg); addConsoleMessage(msg, DEFAULT_JUSTIFY, playerIndex); // Multiplayer message callback // Received a console message from a player, save MultiMsgPlayerFrom = playerIndex; MultiMsgPlayerTo = selectedPlayer; sstrcpy(MultiplayMsg, newmsg); eventFireCallbackTrigger((TRIGGER_TYPE)CALL_AI_MSG); // make some noise! if (titleMode == MULTIOPTION || titleMode == MULTILIMIT) { audio_PlayTrack(FE_AUDIO_MESSAGEEND); } else if (!ingame.localJoiningInProgress) { audio_PlayTrack(ID_SOUND_MESSAGEEND); } return true; }
void initI18n(void) { const char *textdomainDirectory = NULL; if (!setLanguage("")) // set to system default { // no system default? debug(LOG_ERROR, "initI18n: No system language found"); } #if defined(WZ_OS_WIN) { // Retrieve an absolute path to the locale directory char localeDir[PATH_MAX]; sstrcpy(localeDir, PHYSFS_getBaseDir()); sstrcat(localeDir, "\\" LOCALEDIR); // Set locale directory and translation domain name textdomainDirectory = bindtextdomain(PACKAGE, localeDir); } #else #ifdef WZ_OS_MAC { char resourcePath[PATH_MAX]; CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); if( CFURLGetFileSystemRepresentation( resourceURL, true, (UInt8 *) resourcePath, PATH_MAX) ) { sstrcat(resourcePath, "/locale"); textdomainDirectory = bindtextdomain(PACKAGE, resourcePath); } else { debug( LOG_ERROR, "Could not change to resources directory." ); } if (resourceURL != NULL) { CFRelease(resourceURL); } debug(LOG_INFO, "resourcePath is %s", resourcePath); } #else textdomainDirectory = bindtextdomain(PACKAGE, LOCALEDIR); #endif #endif if (!textdomainDirectory) { debug(LOG_ERROR, "initI18n: bindtextdomain failed!"); } (void)bind_textdomain_codeset(PACKAGE, "UTF-8"); (void)textdomain(PACKAGE); }
FILE *MacFopen(const char *path, const char *mode) { static char TruncPath[NAME_MAX]; OSErr err = 0; AssertStr(path,path) /* open zipfile or tempzip */ if (strcmp(zipfile,path) == 0) { GetCompletePath(MacZip.ZipFullPath,path,&MacZip.ZipFileSpec,&err); err = PrintUserHFSerr((err != -43) && (err != 0), err, path); printerr("GetCompletePath:",err,err,__LINE__,__FILE__,path); if (CheckMountedVolumes(MacZip.ZipFullPath) > 1) DoWarnUserDupVol(MacZip.ZipFullPath); /* tempfile should appear in the same directory of the zipfile -> save path of zipfile */ TruncFilename(TruncPath, MacZip.ZipFullPath); return fopen(MacZip.ZipFullPath, mode); } if (strcmp(tempzip,path) == 0) { /* add path of zipfile */ sstrcat(TruncPath,tempzip); GetCompletePath(MacZip.TempZipFullPath,TruncPath,&MacZip.TempZipFileSpec,&err); err = PrintUserHFSerr((err != -43) && (err != 0), err, path); printerr("GetCompletePath:",err,err,__LINE__,__FILE__,path); return fopen(MacZip.TempZipFullPath, mode); } printerr("MacFopen:",err,err,__LINE__,__FILE__,path); return NULL; }
int bm_printboardapi(struct boardmanager *bm,char *farg) { if (getboard(bm->board)){ sstrcat(farg, "\"%s\",",bm->board); } return 0; }
static inline void iV_printFontList(void) { unsigned int i; unsigned int font_count = glcGeti(GLC_CURRENT_FONT_COUNT); debug(LOG_NEVER, "GLC_CURRENT_FONT_COUNT = %d", font_count); if (font_count == 0) { debug(LOG_ERROR, "The required font (%s) isn't loaded", font_family); // Fall back to unselected fonts since the requested font apparently // isn't available. glcEnable(GLC_AUTO_FONT); } for (i = 0; i < font_count; ++i) { GLint font = glcGetListi(GLC_CURRENT_FONT_LIST, i); /* The output of the family name and the face is printed using 2 steps * because glcGetFontc and glcGetFontFace return their result in the * same buffer (according to GLC specs). */ char prBuffer[1024]; snprintf(prBuffer, sizeof(prBuffer), "Font #%d : %s ", (int)font, (const char *)glcGetFontc(font, GLC_FAMILY)); prBuffer[sizeof(prBuffer) - 1] = 0; sstrcat(prBuffer, (char const *)glcGetFontFace(font)); debug(LOG_NEVER, "%s", prBuffer); } }
char *pstrcat(pool *p, ...) { char *argp, *ptr, *res; size_t len = 0; va_list ap; if (p == NULL) { errno = EINVAL; return NULL; } va_start(ap, p); while ((res = va_arg(ap, char *)) != NULL) { len += strlen(res); } va_end(ap); ptr = res = pcalloc(p, len + 1); va_start(ap, p); while ((argp = va_arg(ap, char *)) != NULL) { size_t arglen; arglen = strlen(argp); sstrcat(ptr, argp, len + 1); ptr += arglen; } va_end(ap); return res; }
/** Retrieve the texture number for a given texture resource. * * @note We keep textures in a separate data structure _TEX_PAGE apart from the * normal resource system. * * @param filename The filename of the texture page to search for. * @param compression If we need to load it, should we use texture compression? * * @return a non-negative index number for the texture, negative if no texture * with the given filename could be found */ int iV_GetTexture(const char *filename, bool compression) { iV_Image sSprite; char path[PATH_MAX]; /* Have we already loaded this one then? */ sstrcpy(path, filename); pie_MakeTexPageName(path); for (int i = 0; i < _TEX_PAGE.size(); i++) { if (strncmp(path, _TEX_PAGE[i].name, iV_TEXNAME_MAX) == 0) { return i; } } // Try to load it sstrcpy(path, "texpages/"); sstrcat(path, filename); if (!iV_loadImage_PNG(path, &sSprite)) { debug(LOG_ERROR, "Failed to load %s", path); return -1; } sstrcpy(path, filename); pie_MakeTexPageName(path); return pie_AddTexPage(&sSprite, path, compression); }
/** Retrieve the texture number for a given texture resource. * * @note We keep textures in a separate data structure _TEX_PAGE apart from the * normal resource system. * * @param filename The filename of the texture page to search for. * * @return a non-negative index number for the texture, negative if no texture * with the given filename could be found */ int iV_GetTexture(const char *filename) { unsigned int i = 0; iV_Image sSprite; char path[PATH_MAX]; /* Have we already loaded this one then? */ sstrcpy(path, filename); pie_MakeTexPageName(path); for (i = 0; i < iV_TEX_MAX; i++) { if (strncmp(path, _TEX_PAGE[i].name, iV_TEXNAME_MAX) == 0) { return i; } } // Try to load it sstrcpy(path, "texpages/"); sstrcat(path, filename); if (!iV_loadImage_PNG(path, &sSprite)) { debug(LOG_ERROR, "Failed to load %s", path); return -1; } sstrcpy(path, filename); pie_MakeTexPageName(path); return pie_AddTexPage(&sSprite, path, 0, -1, true); // FIXME, -1, use getTextureSize() }
//add a sequence to the list to be played void seq_AddSeqToList(const char *pSeqName, const char *pAudioName, const char *pTextName, bool bLoop) { currentSeq++; ASSERT_OR_RETURN(, currentSeq < MAX_SEQ_LIST, "too many sequences"); //OK so add it to the list aSeqList[currentSeq].pSeq = pSeqName; aSeqList[currentSeq].pAudio = pAudioName; aSeqList[currentSeq].bSeqLoop = bLoop; if (pTextName != NULL) { // Ordinary text shouldn't be justified seq_AddTextFromFile(pTextName, SEQ_TEXT_POSITION); } if (bSeqSubtitles) { char aSubtitleName[MAX_STR_LENGTH]; sstrcpy(aSubtitleName, pSeqName); // check for a subtitle file char *extension = strrchr(aSubtitleName, '.'); if (extension) { *extension = '\0'; } sstrcat(aSubtitleName, ".txt"); // Subtitles should be center justified seq_AddTextFromFile(aSubtitleName, SEQ_TEXT_JUSTIFY); } }
/** * Send the command to initialize the gprs of the modem. */ static void do_modem_init(gprs_t * gprs) { UNTIMEOUT(); gprs_set_state(gprs,GPRS_STATE_MODEM_INIT); sstrcpy(gprs->replyBuffer,"AT+CGDCONT=1,\"IP\",\"",sizeof(gprs->replyBuffer)); #if GPRS_RUNTIME_APN sstrcat(gprs->replyBuffer,gprs->apn,sizeof(gprs->replyBuffer)); #else sstrcat(gprs->replyBuffer,GPRS_APN,sizeof(gprs->replyBuffer)); #endif sstrcat(gprs->replyBuffer,"\"",sizeof(gprs->replyBuffer)); gprs_command(gprs,gprs->replyBuffer,'\r'); }
void debug_callback_win32debug(WZ_DECL_UNUSED void ** data, const char * outputBuffer) { char tmpStr[MAX_LEN_LOG_LINE]; sstrcpy(tmpStr, outputBuffer); if (!strchr(tmpStr, '\n')) { sstrcat(tmpStr, "\n"); } OutputDebugStringA( tmpStr ); }
void show_special_api(char *id2, char *output){ FILE *fp; char id1[80], name[80], buf[256]; fp=fopen("etc/special", "r"); if(fp!=0){ while(1){ if(fgets(buf, 256, fp)==0) break; if(sscanf(buf, "%s %s", id1, name)<2) continue; if(!strcasecmp(id1, id2)) sstrcat(output, "\"Title\":\"%s\",", name); } } close(fp); }
// show a background piccy (currently used for version and mods labels) static void displayTitleBitmap(WZ_DECL_UNUSED WIDGET *psWidget, WZ_DECL_UNUSED UDWORD xOffset, WZ_DECL_UNUSED UDWORD yOffset, WZ_DECL_UNUSED PIELIGHT *pColours) { char modListText[MAX_STR_LENGTH] = ""; iV_SetFont(font_regular); iV_SetTextColour(WZCOL_GREY); iV_DrawTextRotated(version_getFormattedVersionString(), pie_GetVideoBufferWidth() - 9, pie_GetVideoBufferHeight() - 14, 270.f); if (*getModList()) { sstrcat(modListText, _("Mod: ")); sstrcat(modListText, getModList()); iV_DrawText(modListText, 9, 14); } iV_SetTextColour(WZCOL_TEXT_BRIGHT); iV_DrawTextRotated(version_getFormattedVersionString(), pie_GetVideoBufferWidth() - 10, pie_GetVideoBufferHeight() - 15, 270.f); if (*getModList()) { iV_DrawText(modListText, 10, 15); } }
/*! * Register searchPath above the path with next lower priority * For information about what can be a search path, refer to PhysFS documentation */ void registerSearchPath(const char path[], unsigned int priority) { wzSearchPath *curSearchPath = searchPathRegistry, * tmpSearchPath = nullptr; tmpSearchPath = (wzSearchPath *)malloc(sizeof(*tmpSearchPath)); sstrcpy(tmpSearchPath->path, path); if (path[strlen(path) - 1] != *PHYSFS_getDirSeparator()) { sstrcat(tmpSearchPath->path, PHYSFS_getDirSeparator()); } tmpSearchPath->priority = priority; debug(LOG_WZ, "registerSearchPath: Registering %s at priority %i", path, priority); if (!curSearchPath) { searchPathRegistry = tmpSearchPath; searchPathRegistry->lowerPriority = nullptr; searchPathRegistry->higherPriority = nullptr; return; } while (curSearchPath->higherPriority && priority > curSearchPath->priority) { curSearchPath = curSearchPath->higherPriority; } while (curSearchPath->lowerPriority && priority < curSearchPath->priority) { curSearchPath = curSearchPath->lowerPriority; } if (priority < curSearchPath->priority) { tmpSearchPath->lowerPriority = curSearchPath->lowerPriority; tmpSearchPath->higherPriority = curSearchPath; } else { tmpSearchPath->lowerPriority = curSearchPath; tmpSearchPath->higherPriority = curSearchPath->higherPriority; } if (tmpSearchPath->lowerPriority) { tmpSearchPath->lowerPriority->higherPriority = tmpSearchPath; } if (tmpSearchPath->higherPriority) { tmpSearchPath->higherPriority->lowerPriority = tmpSearchPath; } }
static bool recvBeacon(NETQUEUE queue) { int32_t sender, receiver,locX, locY; char msg[MAX_CONSOLE_STRING_LENGTH]; NETbeginDecode(queue, NET_BEACONMSG); NETint32_t(&sender); // the actual sender NETint32_t(&receiver); // the actual receiver (might not be the same as the one we are actually sending to, in case of AIs) NETint32_t(&locX); NETint32_t(&locY); NETstring(msg, sizeof(msg)); // Receive the actual message NETend(); debug(LOG_WZ, "Received beacon for player: %d, from: %d",receiver, sender); sstrcat(msg, NetPlay.players[sender].name); // name sstrcpy(beaconReceiveMsg[sender], msg); return addBeaconBlip(locX, locY, receiver, sender, beaconReceiveMsg[sender]); }
VOID SetWinTitle(HWND hwnd, PATTMAN pam) { CHAR buf[LPATH + 32]; dprintf("Settaggio titolo finestra\n"); DlgLboxQueryItemText(hwnd, LB_FILE, pam->fsp.psSel[1], buf, LPATH + 32); // se Š una dir ed Š attiva opzione Selez All files in directory legge // attr primo file selezionato e titolo = nomedir\*.* if (pam->pro.sel.extsel && pam->pro.sel.dir && pam->fsp.pszFile[0] == '\\' && pam->fsp.psSel[0]) { sstrcpy(pam->fsp.pszFile, buf); //copia in pszFile nome Iø file selez sprintf(buf, "%s%s%s & *.*", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), pam->fsp.pszFile); // se Š una dir con opzione SelectAll non attiva o non ci sono file selez // legge attr dir corrente e titolo = nomedir\. } else if (pam->fsp.pszFile[0] == '\\' || !pam->fsp.psSel[0]) { if (!pam->fsp.psSel[0]) MyDlgLboxSelectItem(hwnd, LB_FILE, 0); pam->fsp.pszFile[0] = '.'; pam->fsp.pszFile[1] = 0; sstrcpy(buf, pam->fsp.pszPath); sstrcat(buf, pam->fsp.pszPath[3]? "\\.": "."); // se Š un file specificato con una mask di wildchar e ci sono + file // selez legge attr primo file e titolo = nomefile & mask } else if (isWildCh(pam->fsp.pszFile) && pam->fsp.psSel[0] > 1) { char tmp[256]; sstrcpy(tmp, buf); sprintf(buf, "%s%s%s & %s", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), tmp, pam->fsp.pszFile); sstrcpy(pam->fsp.pszFile, tmp); // pi— file selezionati non secondo una mask di wildchars } else if (pam->fsp.psSel[0] > 1) { sstrcpy(pam->fsp.pszFile, buf); sprintf(buf, "%s%s%s & ...", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), pam->fsp.pszFile); // un solo file selezionato } else { sstrcpy(pam->fsp.pszFile, buf); sprintf(buf, "%s%s%s", pam->fsp.pszPath, (pam->fsp.pszPath[3]? "\\": ""), pam->fsp.pszFile); } // endif --- se Š autoimport e subject e comment sono vuoti WinSetWindowText(hwnd, buf); }
//add a sequence to the list to be played void seq_AddSeqToList(const char *pSeqName, const char *pAudioName, const char *pTextName, BOOL bLoop) { currentSeq++; ASSERT(currentSeq < MAX_SEQ_LIST, "too many sequences"); if (currentSeq >= MAX_SEQ_LIST) { return; } //OK so add it to the list aSeqList[currentSeq].pSeq = pSeqName; aSeqList[currentSeq].pAudio = pAudioName; aSeqList[currentSeq].bSeqLoop = bLoop; if (pTextName != NULL) { // Ordinary text shouldn't be justified seq_AddTextFromFile(pTextName, SEQ_TEXT_POSITION); } if (bSeqSubtitles) { char aSubtitleName[MAX_STR_LENGTH]; size_t check_len = sstrcpy(aSubtitleName, pSeqName); char* extension; ASSERT(check_len < sizeof(aSubtitleName), "given sequence name (%s) longer (%lu) than buffer (%lu)", pSeqName, (unsigned long) check_len, (unsigned long) sizeof(aSubtitleName)); // check for a subtitle file extension = strrchr(aSubtitleName, '.'); if (extension) *extension = '\0'; check_len = sstrcat(aSubtitleName, ".txt"); ASSERT(check_len < sizeof(aSubtitleName), "sequence name to long to attach an extension too"); // Subtitles should be center justified seq_AddTextFromFile(aSubtitleName, SEQ_TEXT_JUSTIFY); } }
// //////////////////////////////////////////////////////////////////////////// // display a keymap on the interface. static void displayKeyMap(WIDGET *psWidget, UDWORD xOffset, UDWORD yOffset, WZ_DECL_UNUSED PIELIGHT *pColours) { UDWORD x = xOffset+psWidget->x; UDWORD y = yOffset+psWidget->y; UDWORD w = psWidget->width; UDWORD h = psWidget->height; KEY_MAPPING *psMapping = (KEY_MAPPING*)psWidget->pUserData; char sKey[MAX_STR_LENGTH]; if(psMapping == selectedKeyMap) { pie_BoxFill(x, y, x + w, y + h, WZCOL_KEYMAP_ACTIVE); } else if(psMapping->status == KEYMAP_ALWAYS || psMapping->status == KEYMAP_ALWAYS_PROCESS) { // when user can't edit something... pie_BoxFill(x, y , x + w, y + h, WZCOL_KEYMAP_FIXED); } else { drawBlueBox(x,y,w,h); } // draw name iV_SetFont(font_regular); // font type iV_SetTextColour(WZCOL_FORM_TEXT); iV_DrawText(_(psMapping->pName), x + 2, y + (psWidget->height / 2) + 3); // draw binding keyMapToString(sKey, psMapping); // Check to see if key is on the numpad, if so tell user and change color if (psMapping->subKeyCode >= KEY_KP_0 && psMapping->subKeyCode <= KEY_KPENTER) { iV_SetTextColour(WZCOL_YELLOW); sstrcat(sKey, " (numpad)"); } iV_DrawText(sKey, x + 364, y + (psWidget->height / 2) + 3); }
/*! * \brief Rebuilds the PHYSFS searchPath with mode specific subdirs * * Priority: * maps > mods > base > base.wz */ bool rebuildSearchPath( searchPathMode mode, bool force ) { static searchPathMode current_mode = mod_clean; static std::string current_current_map; wzSearchPath * curSearchPath = searchPathRegistry; char tmpstr[PATH_MAX] = "\0"; if (mode != current_mode || (current_map != NULL? current_map : "") != current_current_map || force || (use_override_mods && strcmp(override_mod_list, getModList()))) { if (mode != mod_clean) { rebuildSearchPath( mod_clean, false ); } current_mode = mode; current_current_map = current_map != NULL? current_map : ""; // Start at the lowest priority while( curSearchPath->lowerPriority ) curSearchPath = curSearchPath->lowerPriority; switch ( mode ) { case mod_clean: debug(LOG_WZ, "Cleaning up"); clearLoadedMods(); while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Removing [%s] from search path", curSearchPath->path); #endif // DEBUG // Remove maps and mods removeSubdirs( curSearchPath->path, "maps", NULL ); removeSubdirs( curSearchPath->path, "mods/music", NULL ); removeSubdirs( curSearchPath->path, "mods/global", NULL ); removeSubdirs( curSearchPath->path, "mods/campaign", NULL ); removeSubdirs( curSearchPath->path, "mods/multiplay", NULL ); removeSubdirs( curSearchPath->path, "mods/autoload", NULL ); // Remove multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // Remove plain dir PHYSFS_removeFromSearchPath( curSearchPath->path ); // Remove base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_removeFromSearchPath( tmpstr ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_removeFromSearchPath( tmpstr ); // remove video search path as well sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_removeFromSearchPath( tmpstr ); curSearchPath = curSearchPath->higherPriority; } break; case mod_campaign: debug(LOG_WZ, "*** Switching to campaign mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and campaign mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/campaign", PHYSFS_APPEND, use_override_mods?override_mods:campaign_mods, true ); if (!PHYSFS_removeFromSearchPath( curSearchPath->path )) { debug(LOG_WZ, "* Failed to remove path %s again", curSearchPath->path); } // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; case mod_multiplay: debug(LOG_WZ, "*** Switching to multiplay mods ***"); clearLoadedMods(); while (curSearchPath) { // make sure videos override included files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "sequences.wz"); PHYSFS_addToSearchPath(tmpstr, PHYSFS_APPEND); curSearchPath = curSearchPath->higherPriority; } // Add the selected map first, for mapmod support if (current_map != NULL) { std::string realPathAndDir = std::string(PHYSFS_getRealDir(current_map)) + current_map; PHYSFS_addToSearchPath(realPathAndDir.c_str(), PHYSFS_APPEND); } curSearchPath = searchPathRegistry; while (curSearchPath->lowerPriority) curSearchPath = curSearchPath->lowerPriority; while( curSearchPath ) { #ifdef DEBUG debug(LOG_WZ, "Adding [%s] to search path", curSearchPath->path); #endif // DEBUG // Add global and multiplay mods PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); addSubdirs( curSearchPath->path, "mods/music", PHYSFS_APPEND, NULL, false ); addSubdirs( curSearchPath->path, "mods/global", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods", PHYSFS_APPEND, use_override_mods?override_mods:global_mods, true ); addSubdirs( curSearchPath->path, "mods/autoload", PHYSFS_APPEND, use_override_mods?override_mods:NULL, true ); addSubdirs( curSearchPath->path, "mods/multiplay", PHYSFS_APPEND, use_override_mods?override_mods:multiplay_mods, true ); PHYSFS_removeFromSearchPath( curSearchPath->path ); // Add multiplay patches sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "mp.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); // Add plain dir PHYSFS_addToSearchPath( curSearchPath->path, PHYSFS_APPEND ); // Add base files sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); sstrcpy(tmpstr, curSearchPath->path); sstrcat(tmpstr, "base.wz"); PHYSFS_addToSearchPath( tmpstr, PHYSFS_APPEND ); curSearchPath = curSearchPath->higherPriority; } break; default: debug(LOG_ERROR, "Can't switch to unknown mods %i", mode); return false; } if (use_override_mods && mode != mod_clean) { if (strcmp(getModList(),override_mod_list)) { debug(LOG_POPUP, _("The required mod could not be loaded: %s\n\nWarzone will try to load the game without it."), override_mod_list); } clearOverrideMods(); current_mode = mod_override; } // User's home dir must be first so we allways see what we write PHYSFS_removeFromSearchPath(PHYSFS_getWriteDir()); PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); #ifdef DEBUG printSearchPath(); #endif // DEBUG } else if (use_override_mods) { // override mods are already the same as current mods, so no need to do anything clearOverrideMods(); } return true; }
/*! * \brief Adds default data dirs * * Priority: * Lower loads first. Current: * -datadir > User's home dir > source tree data > AutoPackage > BaseDir > DEFAULT_DATADIR * * Only -datadir and home dir are allways examined. Others only if data still not found. * * We need ParseCommandLine, before we can add any mods... * * \sa rebuildSearchPath */ static void scanDataDirs( void ) { char tmpstr[PATH_MAX], prefix[PATH_MAX]; char* separator; #if defined(WZ_OS_MAC) // version-independent location for video files registerSearchPath("/Library/Application Support/Warzone 2100/", 1); #endif // Find out which PREFIX we are in... sstrcpy(prefix, PHYSFS_getBaseDir()); separator = strrchr(prefix, *PHYSFS_getDirSeparator()); if (separator) { *separator = '\0'; // Trim ending '/', which getBaseDir always provides separator = strrchr(prefix, *PHYSFS_getDirSeparator()); if (separator) { *separator = '\0'; // Skip the last dir from base dir } } // Commandline supplied datadir if( strlen( datadir ) != 0 ) registerSearchPath( datadir, 1 ); // User's home dir registerSearchPath( PHYSFS_getWriteDir(), 2 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Data in source tree sstrcpy(tmpstr, prefix); sstrcat(tmpstr, "/data/"); registerSearchPath( tmpstr, 3 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Relocation for AutoPackage sstrcpy(tmpstr, prefix); sstrcat(tmpstr, "/share/warzone2100/"); registerSearchPath( tmpstr, 4 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Program dir registerSearchPath( PHYSFS_getBaseDir(), 5 ); rebuildSearchPath( mod_multiplay, true ); if( !PHYSFS_exists("gamedesc.lev") ) { // Guessed fallback default datadir on Unix registerSearchPath( WZ_DATADIR, 6 ); rebuildSearchPath( mod_multiplay, true ); } } } } #ifdef WZ_OS_MAC if( !PHYSFS_exists("gamedesc.lev") ) { CFURLRef resourceURL = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); char resourcePath[PATH_MAX]; if( CFURLGetFileSystemRepresentation( resourceURL, true, (UInt8 *) resourcePath, PATH_MAX) ) { chdir( resourcePath ); registerSearchPath( "data", 7 ); rebuildSearchPath( mod_multiplay, true ); } else { debug( LOG_ERROR, "Could not change to resources directory." ); } if( resourceURL != NULL ) { CFRelease( resourceURL ); } } #endif /** Debugging and sanity checks **/ printSearchPath(); if( PHYSFS_exists("gamedesc.lev") ) { debug( LOG_WZ, "gamedesc.lev found at %s", PHYSFS_getRealDir( "gamedesc.lev" ) ); } else { debug( LOG_FATAL, "Could not find game data. Aborting." ); exit(1); } }
static void getPlatformUserDir(char * const tmpstr, size_t const size) { #if defined(WZ_OS_WIN) // When WZ_PORTABLE is passed, that means we want the config directory at the same location as the program file DWORD dwRet; wchar_t tmpWStr[MAX_PATH]; #ifndef WZ_PORTABLE if ( SUCCEEDED( SHGetFolderPathW( NULL, CSIDL_PERSONAL|CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_CURRENT, tmpWStr ) ) ) { #else if (dwRet = GetCurrentDirectoryW(MAX_PATH, tmpWStr)) { if(dwRet > MAX_PATH) { debug(LOG_FATAL, "Buffer exceeds maximum path to create directory. Exiting."); exit(1); } #endif if (WideCharToMultiByte(CP_UTF8, 0, tmpWStr, -1, tmpstr, size, NULL, NULL) == 0) { debug(LOG_FATAL, "Config directory encoding conversion error."); exit(1); } strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else #elif defined(WZ_OS_MAC) FSRef fsref; OSErr error = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &fsref); if (!error) error = FSRefMakePath(&fsref, (UInt8 *) tmpstr, size); if (!error) strlcat(tmpstr, PHYSFS_getDirSeparator(), size); else #endif if (PHYSFS_getUserDir()) { strlcpy(tmpstr, PHYSFS_getUserDir(), size); // Use PhysFS supplied UserDir (As fallback on Windows / Mac, default on Linux) } // If PhysicsFS fails (might happen if environment variable HOME is unset or wrong) then use the current working directory else if (getCurrentDir(tmpstr, size)) { strlcat(tmpstr, PHYSFS_getDirSeparator(), size); } else { debug(LOG_FATAL, "Can't get UserDir?"); abort(); } } static void initialize_ConfigDir(void) { char tmpstr[PATH_MAX] = { '\0' }; if (strlen(configdir) == 0) { getPlatformUserDir(tmpstr, sizeof(tmpstr)); if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected. { debug(LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError()); exit(1); } if (!PHYSFS_mkdir(WZ_WRITEDIR)) // s.a. { debug(LOG_FATAL, "Error creating directory \"%s\": %s", WZ_WRITEDIR, PHYSFS_getLastError()); exit(1); } // Append the Warzone subdir sstrcat(tmpstr, WZ_WRITEDIR); sstrcat(tmpstr, PHYSFS_getDirSeparator()); if (!PHYSFS_setWriteDir(tmpstr)) { debug( LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError() ); exit(1); } } else { sstrcpy(tmpstr, configdir); // Make sure that we have a directory separator at the end of the string if (tmpstr[strlen(tmpstr) - 1] != PHYSFS_getDirSeparator()[0]) sstrcat(tmpstr, PHYSFS_getDirSeparator()); debug(LOG_WZ, "Using custom configuration directory: %s", tmpstr); if (!PHYSFS_setWriteDir(tmpstr)) // Workaround for PhysFS not creating the writedir as expected. { debug(LOG_FATAL, "Error setting write directory to \"%s\": %s", tmpstr, PHYSFS_getLastError()); exit(1); } // NOTE: This is currently only used for mingw builds for now. #if defined (WZ_CC_MINGW) if (!OverrideRPTDirectory(tmpstr)) { // since it failed, we just use our default path, and not the user supplied one. debug(LOG_ERROR, "Error setting exception hanlder to use directory %s", tmpstr); } #endif } // User's home dir first so we allways see what we write PHYSFS_addToSearchPath( PHYSFS_getWriteDir(), PHYSFS_PREPEND ); PHYSFS_permitSymbolicLinks(1); debug(LOG_WZ, "Write dir: %s", PHYSFS_getWriteDir()); debug(LOG_WZ, "Base dir: %s", PHYSFS_getBaseDir()); }
//**************************************************************************************** // Challenge menu //***************************************************************************************** bool addChallenges() { char sPath[PATH_MAX]; const char *sSearchPath = "challenges"; UDWORD slotCount; static char sSlotCaps[totalslots][totalslotspace]; static char sSlotTips[totalslots][totalslotspace]; static char sSlotFile[totalslots][totalslotspace]; char **i, **files; (void) PHYSFS_mkdir(sSearchPath); // just in case psRequestScreen = widgCreateScreen(); // init the screen widgSetTipFont(psRequestScreen, font_regular); /* add a form to place the tabbed form on */ W_FORMINIT sFormInit; sFormInit.formID = 0; //this adds the blue background, and the "box" behind the buttons -Q sFormInit.id = CHALLENGE_FORM; sFormInit.style = WFORM_PLAIN; sFormInit.x = (SWORD) CHALLENGE_X; sFormInit.y = (SWORD) CHALLENGE_Y; sFormInit.width = CHALLENGE_W; // we need the form to be long enough for all resolutions, so we take the total number of items * height // and * the gaps, add the banner, and finally, the fudge factor ;) sFormInit.height = (slotsInColumn * CHALLENGE_ENTRY_H + CHALLENGE_HGAP * slotsInColumn) + CHALLENGE_BANNER_DEPTH + 20; sFormInit.disableChildren = true; sFormInit.pDisplay = intOpenPlainForm; widgAddForm(psRequestScreen, &sFormInit); // Add Banner sFormInit.formID = CHALLENGE_FORM; sFormInit.id = CHALLENGE_BANNER; sFormInit.x = CHALLENGE_HGAP; sFormInit.y = CHALLENGE_VGAP; sFormInit.width = CHALLENGE_W - (2 * CHALLENGE_HGAP); sFormInit.height = CHALLENGE_BANNER_DEPTH; sFormInit.disableChildren = false; sFormInit.pDisplay = displayLoadBanner; sFormInit.UserData = 0; widgAddForm(psRequestScreen, &sFormInit); // Add Banner Label W_LABINIT sLabInit; sLabInit.formID = CHALLENGE_BANNER; sLabInit.id = CHALLENGE_LABEL; sLabInit.style = WLAB_ALIGNCENTRE; sLabInit.x = 0; sLabInit.y = 3; sLabInit.width = CHALLENGE_W - (2 * CHALLENGE_HGAP); //CHALLENGE_W; sLabInit.height = CHALLENGE_BANNER_DEPTH; //This looks right -Q sLabInit.pText = "Challenge"; widgAddLabel(psRequestScreen, &sLabInit); // add cancel. W_BUTINIT sButInit; sButInit.formID = CHALLENGE_BANNER; sButInit.x = 8; sButInit.y = 8; sButInit.width = iV_GetImageWidth(IntImages, IMAGE_NRUTER); sButInit.height = iV_GetImageHeight(IntImages, IMAGE_NRUTER); sButInit.UserData = PACKDWORD_TRI(0, IMAGE_NRUTER , IMAGE_NRUTER); sButInit.id = CHALLENGE_CANCEL; sButInit.pTip = _("Close"); sButInit.pDisplay = intDisplayImageHilight; widgAddButton(psRequestScreen, &sButInit); // add slots sButInit = W_BUTINIT(); sButInit.formID = CHALLENGE_FORM; sButInit.width = CHALLENGE_ENTRY_W; sButInit.height = CHALLENGE_ENTRY_H; sButInit.pDisplay = displayLoadSlot; for (slotCount = 0; slotCount < totalslots; slotCount++) { sButInit.id = slotCount + CHALLENGE_ENTRY_START; if (slotCount < slotsInColumn) { sButInit.x = 22 + CHALLENGE_HGAP; sButInit.y = (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + ( slotCount * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H))); } else if (slotCount >= slotsInColumn && (slotCount < (slotsInColumn *2))) { sButInit.x = 22 + (2 * CHALLENGE_HGAP + CHALLENGE_ENTRY_W); sButInit.y = (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + ( (slotCount % slotsInColumn) * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H))); } else { sButInit.x = 22 + (3 * CHALLENGE_HGAP + (2 * CHALLENGE_ENTRY_W)); sButInit.y = (SWORD)((CHALLENGE_BANNER_DEPTH + (2 * CHALLENGE_VGAP)) + ( (slotCount % slotsInColumn) * (CHALLENGE_VGAP + CHALLENGE_ENTRY_H))); } widgAddButton(psRequestScreen, &sButInit); } // fill slots. slotCount = 0; sstrcpy(sPath, sSearchPath); sstrcat(sPath, "/*.ini"); debug(LOG_SAVE, "Searching \"%s\" for challenges", sPath); // add challenges to buttons files = PHYSFS_enumerateFiles(sSearchPath); for (i = files; *i != NULL; ++i) { W_BUTTON *button; char description[totalslotspace]; char highscore[totalslotspace]; const char *name, *difficulty, *map, *givendescription; inifile *inif; // See if this filename contains the extension we're looking for if (!strstr(*i, ".ini")) { // If it doesn't, move on to the next filename continue; } /* First grab any high score associated with this challenge */ inif = inifile_load(CHALLENGE_SCORES); sstrcpy(sPath, *i); sPath[strlen(sPath) - 4] = '\0'; // remove .ini sstrcpy(highscore, "no score"); if (inif) { char key[64]; bool victory; int seconds; ssprintf(key, "%s:Player", sPath); name = inifile_get(inif, key, "NO NAME"); ssprintf(key, "%s:Victory", sPath); victory = inifile_get_as_bool(inif, key, false); ssprintf(key, "%s:Seconds", sPath); seconds = inifile_get_as_int(inif, key, -1); if (seconds > 0) { getAsciiTime(key, seconds * GAME_TICKS_PER_SEC); ssprintf(highscore, "%s by %s (%s)", key, name, victory ? "Victory" : "Survived"); } inifile_delete(inif); } ssprintf(sPath, "%s/%s", sSearchPath, *i); inif = inifile_load(sPath); inifile_set_current_section(inif, "challenge"); if (!inif) { debug(LOG_ERROR, "Could not open \"%s\"", sPath); continue; } name = inifile_get(inif, "Name", "BAD NAME"); map = inifile_get(inif, "Map", "BAD MAP"); difficulty = inifile_get(inif, "difficulty", "BAD DIFFICULTY"); givendescription = inifile_get(inif, "description", ""); ssprintf(description, "%s, %s, %s. %s", map, difficulty, highscore, givendescription); button = (W_BUTTON*)widgGetFromID(psRequestScreen, CHALLENGE_ENTRY_START + slotCount); debug(LOG_SAVE, "We found [%s]", *i); /* Set the button-text */ sstrcpy(sSlotCaps[slotCount], name); // store it! sstrcpy(sSlotTips[slotCount], description); // store it, too! sstrcpy(sSlotFile[slotCount], sPath); // store filename inifile_delete(inif); /* Add button */ button->pTip = sSlotTips[slotCount]; button->pText = sSlotCaps[slotCount]; button->pUserData = (void *)sSlotFile[slotCount]; slotCount++; // go to next button... if (slotCount == totalslots) { break; } } PHYSFS_freeList(files); challengesUp = true; return true; }
static int poptGetNextOpt(poptContext ctx) { static char match[PATH_MAX]; // static for bad function static char parameter[PATH_MAX]; // static for arg function char *pparam; int i; ctx->bad = NULL; ctx->parameter = NULL; parameter[0] = '\0'; match[0] = '\0'; if (ctx->current >= ctx->argc) // counts from 1 { return 0; } if (strstr(ctx->argv[ctx->current], "-psn_")) { ctx->current++; // skip mac -psn_* Yum! return POPT_SKIP_MAC_PSN; } sstrcpy(match, ctx->argv[ctx->current]); ctx->current++; pparam = strrchr(match, '='); if (pparam) // option's got a parameter { *pparam++ = '\0'; // split option from parameter and increment past '=' if (pparam[0] == '"') // found scary quotes { pparam++; // skip start quote sstrcpy(parameter, pparam); // copy first parameter if (!strrchr(pparam, '"')) // if no end quote, then find it { while (!strrchr(parameter, '"') && ctx->current < ctx->argc) { sstrcat(parameter, " "); // insert space sstrcat(parameter, ctx->argv[ctx->current]); ctx->current++; // next part, please! } } if (strrchr(parameter, '"')) // its not an else for above! { *strrchr(parameter, '"') = '\0'; // remove end qoute } } else { sstrcpy(parameter, pparam); // copy parameter } } for (i = 0; i < ctx->size; i++) { char sshort[3]; char slong[64]; ssprintf(sshort, "-%c", ctx->table[i].short_form); ssprintf(slong, "--%s", ctx->table[i].string); if ((strcmp(sshort, match) == 0 && ctx->table[i].short_form != '\0') || strcmp(slong, match) == 0) { if (ctx->table[i].argument && pparam) { ctx->parameter = parameter; } return ctx->table[i].enumeration; } } ctx->bad = match; ctx->current++; return POPT_ERROR_BADOPT; }
static GAMECODE renderLoop() { if (bMultiPlayer && !NetPlay.isHostAlive && NetPlay.bComms && !NetPlay.isHost) { intAddInGamePopup(); } int clearMode = 0; if(getDrawShadows()) { clearMode |= CLEAR_SHADOW; } if (loopMissionState == LMS_SAVECONTINUE) { pie_SetFogStatus(false); clearMode = CLEAR_BLACK; } pie_ScreenFlip(clearMode);//gameloopflip HandleClosingWindows(); // Needs to be done outside the pause case. audio_Update(); wzShowMouse(true); INT_RETVAL intRetVal = INT_NONE; if (!paused) { /* Run the in game interface and see if it grabbed any mouse clicks */ if (!rotActive && getWidgetsStatus() && dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING) { intRetVal = intRunWidgets(); } //don't process the object lists if paused or about to quit to the front end if (!gameUpdatePaused() && intRetVal != INT_QUIT) { if( dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING && ( intRetVal == INT_INTERCEPT || ( radarOnScreen && CoordInRadar(mouseX(), mouseY()) && getHQExists(selectedPlayer) ) ) ) { // Using software cursors (when on) for these menus due to a bug in SDL's SDL_ShowCursor() wzSetCursor(CURSOR_DEFAULT); intRetVal = INT_INTERCEPT; } #ifdef DEBUG // check all flag positions for duplicate delivery points checkFactoryFlags(); #endif //handles callbacks for positioning of DP's process3DBuilding(); //ajl. get the incoming netgame messages and process them. // FIXME Previous comment is deprecated. multiPlayerLoop does some other weird stuff, but not that anymore. if (bMultiPlayer) { multiPlayerLoop(); } for (unsigned i = 0; i < MAX_PLAYERS; i++) { for (DROID *psCurr = apsDroidLists[i]; psCurr; psCurr = psCurr->psNext) { // Don't copy the next pointer - if droids somehow get destroyed in the graphics rendering loop, who cares if we crash. calcDroidIllumination(psCurr); } } /* update animations */ animObj_Update(); } if (!consolePaused()) { /* Process all the console messages */ updateConsoleMessages(); } if (!scrollPaused() && !getWarCamStatus() && dragBox3D.status != DRAG_DRAGGING && intMode != INT_INGAMEOP ) { scroll(); } } else // paused { // Using software cursors (when on) for these menus due to a bug in SDL's SDL_ShowCursor() wzSetCursor(CURSOR_DEFAULT); if(dragBox3D.status != DRAG_DRAGGING) { scroll(); } if(InGameOpUp || isInGamePopupUp) // ingame options menu up, run it! { unsigned widgval = widgRunScreen(psWScreen); intProcessInGameOptions(widgval); if(widgval == INTINGAMEOP_QUIT_CONFIRM || widgval == INTINGAMEOP_POPUP_QUIT) { if(gamePaused()) { kf_TogglePauseMode(); } intRetVal = INT_QUIT; } } if(bLoadSaveUp && runLoadSave(true) && strlen(sRequestResult)) { debug( LOG_NEVER, "Returned %s", sRequestResult ); if(bRequestLoad) { loopMissionState = LMS_LOADGAME; NET_InitPlayers(); // otherwise alliances were not cleared sstrcpy(saveGameName, sRequestResult); } else { char msgbuffer[256]= {'\0'}; if (saveInMissionRes()) { if (saveGame(sRequestResult, GTYPE_SAVE_START)) { sstrcpy(msgbuffer, _("GAME SAVED: ")); sstrcat(msgbuffer, sRequestResult); addConsoleMessage( msgbuffer, LEFT_JUSTIFY, NOTIFY_MESSAGE); } else { ASSERT( false,"Mission Results: saveGame Failed" ); sstrcpy(msgbuffer, _("Could not save game!")); addConsoleMessage( msgbuffer, LEFT_JUSTIFY, NOTIFY_MESSAGE); deleteSaveGame(sRequestResult); } } else if (bMultiPlayer || saveMidMission()) { if (saveGame(sRequestResult, GTYPE_SAVE_MIDMISSION))//mid mission from [esc] menu { sstrcpy(msgbuffer, _("GAME SAVED: ")); sstrcat(msgbuffer, sRequestResult); addConsoleMessage( msgbuffer, LEFT_JUSTIFY, NOTIFY_MESSAGE); } else { ASSERT(!"saveGame(sRequestResult, GTYPE_SAVE_MIDMISSION) failed", "Mid Mission: saveGame Failed" ); sstrcpy(msgbuffer, _("Could not save game!")); addConsoleMessage( msgbuffer, LEFT_JUSTIFY, NOTIFY_MESSAGE); deleteSaveGame(sRequestResult); } } else { ASSERT( false, "Attempt to save game with incorrect load/save mode" ); } } } } /* Check for quit */ bool quitting = false; if (intRetVal == INT_QUIT) { if (!loop_GetVideoStatus()) { //quitting from the game to the front end //so get a new backdrop quitting = true; pie_LoadBackDrop(SCREEN_RANDOMBDROP); } } if (!loop_GetVideoStatus() && !quitting) { if (!gameUpdatePaused()) { if (dragBox3D.status != DRAG_DRAGGING && wallDrag.status != DRAG_DRAGGING) { ProcessRadarInput(); } processInput(); //no key clicks or in Intelligence Screen if (intRetVal == INT_NONE && !InGameOpUp && !isInGamePopupUp) { processMouseClickInput(); } displayWorld(); } /* Display the in game interface */ pie_SetDepthBufferStatus(DEPTH_CMP_ALWAYS_WRT_ON); pie_SetFogStatus(false); if(bMultiPlayer && bDisplayMultiJoiningStatus) { intDisplayMultiJoiningStatus(bDisplayMultiJoiningStatus); setWidgetsStatus(false); } if(getWidgetsStatus()) { intDisplayWidgets(); } pie_SetDepthBufferStatus(DEPTH_CMP_LEQ_WRT_ON); pie_SetFogStatus(true); } pie_GetResetCounts(&loopPieCount, &loopPolyCount, &loopStateChanges); if ((fogStatus & FOG_BACKGROUND) && (loopMissionState == LMS_SAVECONTINUE)) { pie_SetFogStatus(false); } if (!quitting) { /* Check for toggling display mode */ if ((keyDown(KEY_LALT) || keyDown(KEY_RALT)) && keyPressed(KEY_RETURN)) { screenToggleMode(); } } // deal with the mission state switch (loopMissionState) { case LMS_CLEAROBJECTS: missionDestroyObjects(); setScriptPause(true); loopMissionState = LMS_SETUPMISSION; break; case LMS_NORMAL: // default break; case LMS_SETUPMISSION: setScriptPause(false); if (!setUpMission(nextMissionType)) { return GAMECODE_QUITGAME; } break; case LMS_SAVECONTINUE: // just wait for this to be changed when the new mission starts break; case LMS_NEWLEVEL: //nextMissionType = MISSION_NONE; nextMissionType = LDS_NONE; return GAMECODE_NEWLEVEL; break; case LMS_LOADGAME: return GAMECODE_LOADGAME; break; default: ASSERT( false, "unknown loopMissionState" ); break; } if (quitting) { pie_SetFogStatus(false); pie_ScreenFlip(CLEAR_BLACK);//gameloopflip /* Check for toggling display mode */ if ((keyDown(KEY_LALT) || keyDown(KEY_RALT)) && keyPressed(KEY_RETURN)) { screenToggleMode(); } return GAMECODE_QUITGAME; } else if (loop_GetVideoStatus()) { audio_StopAll(); return GAMECODE_PLAYVIDEO; } return GAMECODE_CONTINUE; }
/** * Exception handling on Windows. * Ask the user whether he wants to safe a Minidump and then dump it into the temp directory. * NOTE: This is only for MSVC compiled programs. * * \param pExceptionInfo Information on the exception, passed from Windows * \return whether further exception handlers (i.e. the Windows internal one) should be invoked */ static LONG WINAPI windowsExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) { LPCSTR applicationName = "Warzone 2100"; char miniDumpPath[PATH_MAX] = {'\0'}, resultMessage[PATH_MAX] = {'\0'}; // Write to temp dir, to support unprivileged users if (!GetTempPathA(sizeof(miniDumpPath), miniDumpPath)) { sstrcpy(miniDumpPath, "c:\\temp\\"); } // Append the filename sstrcat(miniDumpPath, "warzone2100.mdmp"); /* Alternative: GetModuleFileName( NULL, miniDumpPath, MAX_PATH ); // Append extension sstrcat(miniDumpPath, ".mdmp"); */ if ( MessageBoxA( NULL, "Warzone crashed unexpectedly, would you like to save a diagnostic file?", applicationName, MB_YESNO ) == IDYES ) { HANDLE miniDumpFile = CreateFileA( miniDumpPath, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if (miniDumpFile != INVALID_HANDLE_VALUE) { MINIDUMP_USER_STREAM uStream = { LastReservedStream+1, strlen(PACKAGE_VERSION), PACKAGE_VERSION }; MINIDUMP_USER_STREAM_INFORMATION uInfo = { 1, &uStream }; MINIDUMP_EXCEPTION_INFORMATION eInfo = { GetCurrentThreadId(), pExceptionInfo, false }; if ( MiniDumpWriteDump( GetCurrentProcess(), GetCurrentProcessId(), miniDumpFile, MiniDumpNormal, pExceptionInfo ? &eInfo : NULL, &uInfo, NULL ) ) { snprintf(resultMessage, sizeof(resultMessage), "Saved dump file to '%s'", miniDumpPath); } else { snprintf(resultMessage, sizeof(resultMessage), "Failed to save dump file to '%s' (error %d)", miniDumpPath, (int)GetLastError()); } CloseHandle(miniDumpFile); } else { snprintf(resultMessage, sizeof(resultMessage), "Failed to create dump file '%s' (error %d)", miniDumpPath, (int)GetLastError()); } MessageBoxA( NULL, resultMessage, applicationName, MB_OK ); } if (prevExceptionHandler) return prevExceptionHandler(pExceptionInfo); else return EXCEPTION_CONTINUE_SEARCH; }
// ppFileData is incremented to the end of the file on exit! static iIMDShape *iV_ProcessIMD(const QString &filename, const char **ppFileData, const char *FileDataEnd) { const char *pFileData = *ppFileData; char buffer[PATH_MAX], texfile[PATH_MAX], normalfile[PATH_MAX], specfile[PATH_MAX]; int cnt, nlevels; iIMDShape *shape; UDWORD level; int32_t imd_version; uint32_t imd_flags; bool bTextured = false; iIMDShape *objanimpie[ANIM_EVENT_COUNT]; memset(normalfile, 0, sizeof(normalfile)); memset(specfile, 0, sizeof(specfile)); if (sscanf(pFileData, "%255s %d%n", buffer, &imd_version, &cnt) != 2) { debug(LOG_ERROR, "%s: bad PIE version: (%s)", filename.toUtf8().constData(), buffer); assert(false); return nullptr; } pFileData += cnt; if (strcmp(PIE_NAME, buffer) != 0) { debug(LOG_ERROR, "%s: Not an IMD file (%s %d)", filename.toUtf8().constData(), buffer, imd_version); return nullptr; } //Now supporting version PIE_VER and PIE_FLOAT_VER files if (imd_version != PIE_VER && imd_version != PIE_FLOAT_VER) { debug(LOG_ERROR, "%s: Version %d not supported", filename.toUtf8().constData(), imd_version); return nullptr; } // Read flag if (sscanf(pFileData, "%255s %x%n", buffer, &imd_flags, &cnt) != 2) { debug(LOG_ERROR, "%s: bad flags: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; /* This can be either texture or levels */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "%s: Expecting TEXTURE or LEVELS: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; // get texture page if specified if (strncmp(buffer, "TEXTURE", 7) == 0) { int i, pwidth, pheight; char ch, texType[PATH_MAX]; /* the first parameter for textures is always ignored; which is why we ignore * nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { texfile[i] = ch; } texfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "%s: Texture info corrupt: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "%s: Only png textures supported", filename.toUtf8().constData()); return nullptr; } sstrcat(texfile, ".png"); if (sscanf(pFileData, "%d %d%n", &pwidth, &pheight, &cnt) != 2) { debug(LOG_ERROR, "%s: Bad texture size: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; /* Now read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "%s: Bad levels info: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; bTextured = true; } if (strncmp(buffer, "NORMALMAP", 9) == 0) { char ch, texType[PATH_MAX]; int i; /* the first parameter for textures is always ignored; which is why we ignore * nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { normalfile[i] = ch; } normalfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "%s: Normal map info corrupt: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "%s: Only png normal maps supported", filename.toUtf8().constData()); return nullptr; } sstrcat(normalfile, ".png"); /* Now read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "%s: Bad levels info: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; } if (strncmp(buffer, "SPECULARMAP", 11) == 0) { char ch, texType[PATH_MAX]; int i; /* the first parameter for textures is always ignored; which is why we ignore nlevels read in above */ ch = *pFileData++; // Run up to the dot or till the buffer is filled. Leave room for the extension. for (i = 0; i < PATH_MAX - 5 && (ch = *pFileData++) != '\0' && ch != '.'; ++i) { specfile[i] = ch; } specfile[i] = '\0'; if (sscanf(pFileData, "%255s%n", texType, &cnt) != 1) { debug(LOG_ERROR, "%s specular map info corrupt: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; if (strcmp(texType, "png") != 0) { debug(LOG_ERROR, "%s: only png specular maps supported", filename.toUtf8().constData()); return nullptr; } sstrcat(specfile, ".png"); /* Try -again- to read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "%s: Bad levels info: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; } for (int i = 0; i < ANIM_EVENT_COUNT; i++) { objanimpie[i] = nullptr; } while (strncmp(buffer, "EVENT", 5) == 0) { char animpie[PATH_MAX]; ASSERT(nlevels < ANIM_EVENT_COUNT && nlevels >= 0, "Invalid event type %d", nlevels); pFileData++; if (sscanf(pFileData, "%255s%n", animpie, &cnt) != 1) { debug(LOG_ERROR, "%s animation model corrupt: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; objanimpie[nlevels] = modelGet(animpie); /* Try -yet again- to read in LEVELS directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &nlevels, &cnt) != 2) { debug(LOG_ERROR, "%s: Bad levels info: %s", filename.toUtf8().constData(), buffer); return nullptr; } pFileData += cnt; } if (strncmp(buffer, "LEVELS", 6) != 0) { debug(LOG_ERROR, "%s: Expecting 'LEVELS' directive (%s)", filename.toUtf8().constData(), buffer); return nullptr; } /* Read first LEVEL directive */ if (sscanf(pFileData, "%255s %d%n", buffer, &level, &cnt) != 2) { debug(LOG_ERROR, "(_load_level) file corrupt -J"); return nullptr; } pFileData += cnt; if (strncmp(buffer, "LEVEL", 5) != 0) { debug(LOG_ERROR, "%s: Expecting 'LEVEL' directive (%s)", filename.toUtf8().constData(), buffer); return nullptr; } shape = _imd_load_level(filename, &pFileData, FileDataEnd, nlevels, imd_version, level); if (shape == nullptr) { debug(LOG_ERROR, "%s: Unsuccessful", filename.toUtf8().constData()); return nullptr; } // load texture page if specified if (bTextured) { int texpage = iV_GetTexture(texfile); int normalpage = iV_TEX_INVALID; int specpage = iV_TEX_INVALID; ASSERT_OR_RETURN(nullptr, texpage >= 0, "%s could not load tex page %s", filename.toUtf8().constData(), texfile); if (normalfile[0] != '\0') { debug(LOG_TEXTURE, "Loading normal map %s for %s", normalfile, filename.toUtf8().constData()); normalpage = iV_GetTexture(normalfile, false); ASSERT_OR_RETURN(nullptr, normalpage >= 0, "%s could not load tex page %s", filename.toUtf8().constData(), normalfile); } if (specfile[0] != '\0') { debug(LOG_TEXTURE, "Loading specular map %s for %s", specfile, filename.toUtf8().constData()); specpage = iV_GetTexture(specfile, false); ASSERT_OR_RETURN(nullptr, specpage >= 0, "%s could not load tex page %s", filename.toUtf8().constData(), specfile); } // assign tex pages and flags to all levels for (iIMDShape *psShape = shape; psShape != nullptr; psShape = psShape->next) { psShape->texpage = texpage; psShape->normalpage = normalpage; psShape->specularpage = specpage; psShape->flags = imd_flags; } // check if model should use team colour mask if (imd_flags & iV_IMD_TCMASK) { int texpage_mask; pie_MakeTexPageTCMaskName(texfile); sstrcat(texfile, ".png"); texpage_mask = iV_GetTexture(texfile); ASSERT_OR_RETURN(shape, texpage_mask >= 0, "%s could not load tcmask %s", filename.toUtf8().constData(), texfile); // Propagate settings through levels for (iIMDShape *psShape = shape; psShape != nullptr; psShape = psShape->next) { psShape->tcmaskpage = texpage_mask; } } } // copy over model-wide animation information, stored only in the first level for (int i = 0; i < ANIM_EVENT_COUNT; i++) { shape->objanimpie[i] = objanimpie[i]; } *ppFileData = pFileData; return shape; }