//runtime selection of optimized tmappers. 12/07/99 Matthew Mueller //the reason I did it this way rather than having a *tmap_funcs that then points to a c_tmap or fp_tmap struct thats already filled in, is to avoid a second pointer dereference. void select_tmap(char *type) { if (!type) { #if !defined(NO_ASM) && !defined(OGL) select_tmap("i386"); #elif defined(macintosh) && !defined(OGL) select_tmap("ppc"); #else select_tmap("c"); #endif return; } #if !defined(NO_ASM) && !defined(OGL) if (d_stricmp(type, "i386")==0) { cur_tmap_scanline_per=asm_tmap_scanline_per; cur_tmap_scanline_per_nolight=asm_tmap_scanline_per; cur_tmap_scanline_lin=asm_tmap_scanline_lin_lighted; cur_tmap_scanline_lin_nolight=asm_tmap_scanline_lin; cur_tmap_scanline_flat=asm_tmap_scanline_flat; cur_tmap_scanline_shaded=asm_tmap_scanline_shaded; } else #elif defined(macintosh) && !defined(OGL) if (d_stricmp(type,"ppc")==0) { cur_tmap_scanline_per=asm_tmap_scanline_per; cur_tmap_scanline_per_nolight=asm_tmap_scanline_per; cur_tmap_scanline_lin=c_tmap_scanline_lin; cur_tmap_scanline_lin_nolight=c_tmap_scanline_lin_nolight; cur_tmap_scanline_flat=c_tmap_scanline_flat; cur_tmap_scanline_shaded=c_tmap_scanline_shaded; } else #endif if (d_stricmp(type,"fp")==0) { cur_tmap_scanline_per=c_fp_tmap_scanline_per; cur_tmap_scanline_per_nolight=c_fp_tmap_scanline_per_nolight; cur_tmap_scanline_lin=c_tmap_scanline_lin; cur_tmap_scanline_lin_nolight=c_tmap_scanline_lin_nolight; cur_tmap_scanline_flat=c_tmap_scanline_flat; cur_tmap_scanline_shaded=c_tmap_scanline_shaded; } else if (d_stricmp(type,"quad")==0) { cur_tmap_scanline_per=c_tmap_scanline_quad; cur_tmap_scanline_per_nolight=c_tmap_scanline_per_nolight; cur_tmap_scanline_lin=c_tmap_scanline_lin; cur_tmap_scanline_lin_nolight=c_tmap_scanline_lin_nolight; cur_tmap_scanline_flat=c_tmap_scanline_flat; cur_tmap_scanline_shaded=c_tmap_scanline_shaded; } else { cur_tmap_scanline_per=c_tmap_scanline_per; cur_tmap_scanline_per_nolight=c_tmap_scanline_per_nolight; cur_tmap_scanline_lin=c_tmap_scanline_lin; cur_tmap_scanline_lin_nolight=c_tmap_scanline_lin_nolight; cur_tmap_scanline_flat=c_tmap_scanline_flat; cur_tmap_scanline_shaded=c_tmap_scanline_shaded; } }
void ogl_get_verinfo(void) { #ifndef OGLES gl_vendor = (const char *) glGetString (GL_VENDOR); gl_renderer = (const char *) glGetString (GL_RENDERER); gl_version = (const char *) glGetString (GL_VERSION); gl_extensions = (const char *) glGetString (GL_EXTENSIONS); con_printf(CON_VERBOSE, "OpenGL: vendor: %s\nOpenGL: renderer: %s\nOpenGL: version: %s\n",gl_vendor,gl_renderer,gl_version); #ifdef _WIN32 dglMultiTexCoord2fARB = (glMultiTexCoord2fARB_fp)wglGetProcAddress("glMultiTexCoord2fARB"); dglActiveTextureARB = (glActiveTextureARB_fp)wglGetProcAddress("glActiveTextureARB"); dglMultiTexCoord2fSGIS = (glMultiTexCoord2fSGIS_fp)wglGetProcAddress("glMultiTexCoord2fSGIS"); dglSelectTextureSGIS = (glSelectTextureSGIS_fp)wglGetProcAddress("glSelectTextureSGIS"); #endif //add driver specific hacks here. whee. if ((d_stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.0\n")==0 || d_stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.2\n")==0) && d_stricmp(gl_version,"1.2 Mesa 3.0")==0) { GameArg.DbgGlIntensity4Ok=0;//ignores alpha, always black background instead of transparent. GameArg.DbgGlReadPixelsOk=0;//either just returns all black, or kills the X server entirely GameArg.DbgGlGetTexLevelParamOk=0;//returns random data.. } if (d_stricmp(gl_vendor,"Matrox Graphics Inc.")==0) { //displays garbage. reported by // [email protected] (render="Matrox G400" version="1.1.3 5.52.015") // orulz (Matrox G200) GameArg.DbgGlIntensity4Ok=0; } #ifdef macintosh if (d_stricmp(gl_renderer,"3dfx Voodoo 3")==0) // strangely, includes Voodoo 2 GameArg.DbgGlGetTexLevelParamOk=0; // Always returns 0 #endif #ifndef NDEBUG con_printf(CON_VERBOSE,"gl_intensity4:%i gl_luminance4_alpha4:%i gl_rgba2:%i gl_readpixels:%i gl_gettexlevelparam:%i\n",GameArg.DbgGlIntensity4Ok,GameArg.DbgGlLuminance4Alpha4Ok,GameArg.DbgGlRGBA2Ok,GameArg.DbgGlReadPixelsOk,GameArg.DbgGlGetTexLevelParamOk); #endif if (!d_stricmp(gl_extensions,"GL_EXT_texture_filter_anisotropic")==0) { glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &ogl_maxanisotropy); con_printf(CON_VERBOSE,"ogl_maxanisotropy:%f\n",ogl_maxanisotropy); } else if (GameCfg.TexFilt >= 3) GameCfg.TexFilt = 2; #endif }
//----------------------------------------------------------------------------- // Load Descent briefing text. static int load_screen_text(const d_fname &filename, std::unique_ptr<char[]> &buf) { int len, have_binary = 0; auto e = end(filename); auto ext = std::find(begin(filename), e, '.'); if (ext == e) return (0); if (!d_stricmp(&*ext, ".txb")) have_binary = 1; auto tfile = PHYSFSX_openReadBuffered(filename); if (!tfile) return (0); len = PHYSFS_fileLength(tfile); buf = make_unique<char[]>(len + 1); #if defined(DXX_BUILD_DESCENT_I) PHYSFS_read(tfile, buf.get(), 1, len); #elif defined(DXX_BUILD_DESCENT_II) for (int x=0, i=0; i < len; i++, x++) { PHYSFS_read(tfile, &buf[x], 1, 1); if (buf[x] == 13) x--; } #endif if (have_binary) decode_text(buf.get(), len); buf[len] = '\0'; return (1); }
static int FindArg(const char *const s) { int i; for (i=0; i<Num_args; i++ ) if (! d_stricmp( Args[i], s)) return i; return 0; }
//loads the named mission if exists. //Returns true if mission loaded ok, else false. int load_mission_by_name(char *mission_name) { int i; mle *mission_list = build_mission_list(1); bool found = 0; for (i = 0; i < num_missions; i++) if (!d_stricmp(mission_name, mission_list[i].filename)) found = load_mission(mission_list + i); free_mission_list(mission_list); return found; }
// checks which archives are supported by PhysFS. Return 0 if some essential (HOG) is not supported int PHYSFSX_checkSupportedArchiveTypes() { const PHYSFS_ArchiveInfo **i; int hog_sup = 0, mvl_sup = 0; con_printf(CON_DEBUG, "PHYSFS: Checking supported archive types.\n"); for (i = PHYSFS_supportedArchiveTypes(); *i != NULL; i++) { con_printf(CON_DEBUG, "PHYSFS: Supported archive: [%s], which is [%s].\n", (*i)->extension, (*i)->description); if (!d_stricmp((*i)->extension, "HOG")) hog_sup = 1; if (!d_stricmp((*i)->extension, "MVL")) mvl_sup = 1; } if (!hog_sup) con_printf(CON_CRITICAL, "PHYSFS: HOG not supported. The game will not work without!\n"); if (!mvl_sup) con_printf(CON_URGENT, "PHYSFS: MVL not supported. Won't be able to play movies!\n"); return hog_sup; }
int select_mission(int anarchy_mode, char *message, int (*when_selected)(void)) { mle *mission_list = build_mission_list(anarchy_mode); int new_mission_num; if (num_missions <= 1) { new_mission_num = load_mission(mission_list) ? 0 : -1; free_mission_list(mission_list); (*when_selected)(); return (new_mission_num >= 0); } else { mission_menu *mm; int i, default_mission; char **m; MALLOC(m, char *, num_missions); if (!m) { free_mission_list(mission_list); return 0; } MALLOC(mm, mission_menu, 1); if (!mm) { d_free(m); free_mission_list(mission_list); return 0; } mm->mission_list = mission_list; mm->when_selected = when_selected; default_mission = 0; for (i = 0; i < num_missions; i++) { m[i] = mission_list[i].mission_name; if ( !d_stricmp( m[i], GameCfg.LastMission ) ) default_mission = i; } newmenu_listbox1( message, num_missions, m, 1, default_mission, (int (*)(listbox *, d_event *, void *))mission_menu_handler, mm ); } return 1; // presume success }
// Play tracks from Jukebox directory. Play track specified in GameCfg.CMLevelMusicTrack[0] and loop depending on GameCfg.CMLevelMusicPlayOrder int jukebox_play() { const char *music_filename; uint_fast32_t size_full_filename = 0; if (!JukeboxSongs.list) return 0; if (CGameCfg.CMLevelMusicTrack[0] < 0 || CGameCfg.CMLevelMusicTrack[0] + 1 > CGameCfg.CMLevelMusicTrack[1]) return 0; music_filename = JukeboxSongs.list[CGameCfg.CMLevelMusicTrack[0]]; if (!music_filename) return 0; size_t size_music_filename = strlen(music_filename); auto &cfgpath = CGameCfg.CMLevelMusicPath; size_t musiclen = strlen(cfgpath.data()); size_full_filename = musiclen + size_music_filename + 1; RAIIdmem<char[]> full_filename; CALLOC(full_filename, char[], size_full_filename); const char *LevelMusicPath; if (musiclen > 4 && !d_stricmp(&cfgpath[musiclen - 4], ".m3u")) // if it's from an M3U playlist LevelMusicPath = ""; else // if it's from a specified path LevelMusicPath = cfgpath.data(); snprintf(full_filename.get(), size_full_filename, "%s%s", LevelMusicPath, music_filename); int played = songs_play_file(full_filename.get(), (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL ? 1 : 0), (GameCfg.CMLevelMusicPlayOrder == MUSIC_CM_PLAYORDER_LEVEL ? nullptr : jukebox_hook_next)); full_filename.reset(); if (!played) { return 0; // whoops, got an error } // Formatting a pretty message const char *prefix = "..."; if (size_music_filename >= MUSIC_HUDMSG_MAXLEN) { music_filename += size_music_filename - MUSIC_HUDMSG_MAXLEN; } else { prefix += 3; } HUD_init_message(HM_DEFAULT, "%s %s%s", JUKEBOX_HUDMSG_PLAYING, prefix, music_filename); return 1; }
int hashtable_search( hashtable *ht, char *key ) { int i,j,k; d_strlwr( key ); k = hashtable_getkey( key ); i = 0; while(i < ht->size ) { j = (k+(i++)) & ht->and_mask; if ( ht->key[j] == NULL ) return -1; if (!d_stricmp(ht->key[j], key )) return ht->value[j]; } return -1; }
/* move <mission_name> to <place> on mission list, increment <place> */ void promote (mle *mission_list, char * mission_name, int * top_place) { int i; char name[FILENAME_LEN], * t; strcpy(name, mission_name); if ((t = strchr(name,'.')) != NULL) *t = 0; //kill extension for (i = *top_place; i < num_missions; i++) if (!d_stricmp(mission_list[i].filename, name)) { //swap mission positions mle temp; temp = mission_list[*top_place]; mission_list[*top_place] = mission_list[i]; mission_list[i] = temp; ++(*top_place); break; } }
void hashtable_insert( hashtable *ht, char *key, int value ) { int i,j,k; d_strlwr( key ); k = hashtable_getkey( key ); i = 0; while(i < ht->size) { j = (k+(i++)) & ht->and_mask; if ( ht->key[j] == NULL ) { ht->nitems++; ht->key[j] = key; ht->value[j] = value; return; } else if (!d_stricmp( key, ht->key[j] )) { return; } } Error( "Out of hash slots\n" ); }
static PHYSFSX_counted_list file_getfilelist(const char *filespec, const char *dir) { PHYSFSX_counted_list list{PHYSFS_enumerateFiles(dir)}; if (!list) return nullptr; if (*filespec == '*') filespec++; const auto predicate = [&](char *i) -> bool { auto ext = strrchr(i, '.'); if (ext && (!d_stricmp(ext, filespec))) return false; free(i); return true; }; auto j = std::remove_if(list.begin(), list.end(), predicate); *j = NULL; auto NumFiles = j.get() - list.get(); list.set_count(NumFiles); qsort(list.get(), NumFiles, sizeof(char *), string_array_sort_func); return list; }
//loads the specfied mission from the mission list. //build_mission_list() must have been called. //Returns true if mission loaded ok, else false. int load_mission(mle *mission) { PHYSFS_file *mfile; char buf[PATH_MAX], *v; if (Current_mission) free_mission(); Current_mission = d_malloc(sizeof(Mission)); if (!Current_mission) return 0; *(mle *) Current_mission = *mission; Current_mission->path = d_strdup(mission->path); Current_mission->filename = Current_mission->path + (mission->filename - mission->path); Current_mission->n_secret_levels = 0; Current_mission->enhanced = 0; //init vars Last_level = 0; Last_secret_level = 0; memset(&Briefing_text_filename, '\0', sizeof(Briefing_text_filename)); memset(&Ending_text_filename, '\0', sizeof(Ending_text_filename)); // for Descent 1 missions, load descent.hog if (EMULATING_D1) { if (!PHYSFSX_contfile_init("descent.hog", 1)) Warning("descent.hog not available, this mission may be missing some files required for briefings and exit sequence\n"); if (!d_stricmp(Current_mission_filename, D1_MISSION_FILENAME)) return load_mission_d1(); } if (PLAYING_BUILTIN_MISSION) { switch (Current_mission->builtin_hogsize) { case SHAREWARE_MISSION_HOGSIZE: case MAC_SHARE_MISSION_HOGSIZE: strcpy(Briefing_text_filename,BIMD2_BRIEFING_FILE_SHARE); strcpy(Ending_text_filename,BIMD2_ENDING_FILE_SHARE); return load_mission_shareware(); break; case OEM_MISSION_HOGSIZE: strcpy(Briefing_text_filename,BIMD2_BRIEFING_FILE_OEM); strcpy(Ending_text_filename,BIMD2_ENDING_FILE_OEM); return load_mission_oem(); break; default: Int3(); // fall through case FULL_MISSION_HOGSIZE: case FULL_10_MISSION_HOGSIZE: case MAC_FULL_MISSION_HOGSIZE: strcpy(Briefing_text_filename,BIMD2_BRIEFING_FILE); // continue on... (use d2.mn2 from hogfile) break; } } //read mission from file switch (mission->location) { case ML_MISSIONDIR: strcpy(buf,MISSION_DIR); break; default: Int3(); //fall through case ML_CURDIR: strcpy(buf,""); break; } strcat(buf, mission->path); if (mission->descent_version == 2) strcat(buf,".mn2"); else strcat(buf,".msn"); PHYSFSEXT_locateCorrectCase(buf); mfile = PHYSFSX_openReadBuffered(buf); if (mfile == NULL) { free_mission(); return 0; //error! } //for non-builtin missions, load HOG if (!PLAYING_BUILTIN_MISSION) { strcpy(buf+strlen(buf)-4,".hog"); //change extension PHYSFSEXT_locateCorrectCase(buf); if (PHYSFSX_exists(buf,1)) PHYSFSX_contfile_init(buf, 0); snprintf(Briefing_text_filename, sizeof(Briefing_text_filename), "%s.tex",Current_mission_filename); if (!PHYSFSX_exists(Briefing_text_filename,1)) snprintf(Briefing_text_filename, sizeof(Briefing_text_filename), "%s.txb",Current_mission_filename); snprintf(Ending_text_filename, sizeof(Ending_text_filename), "%s.tex",Current_mission_filename); if (!PHYSFSX_exists(Ending_text_filename,1)) snprintf(Ending_text_filename, sizeof(Ending_text_filename), "%s.txb",Current_mission_filename); } while (PHYSFSX_fgets(buf,80,mfile)) { if (istok(buf,"name") && !Current_mission->enhanced) { Current_mission->enhanced = 0; continue; //already have name, go to next line } if (istok(buf,"xname") && !Current_mission->enhanced) { Current_mission->enhanced = 1; continue; //already have name, go to next line } if (istok(buf,"zname") && !Current_mission->enhanced) { Current_mission->enhanced = 2; continue; //already have name, go to next line } else if (istok(buf,"type")) continue; //already have name, go to next line else if (istok(buf,"briefing")) { if ((v = get_value(buf)) != NULL) { add_term(v); if (strlen(v) < FILENAME_LEN && strlen(v) > 0) { char *tmp, *ptr; MALLOC(tmp, char, FILENAME_LEN); snprintf(tmp, FILENAME_LEN, "%s", v); if ((ptr = strrchr(tmp, '.'))) // if there's a filename extension, kill it. No one knows it's the right one. *ptr = '\0'; strncat(tmp, ".tex", sizeof(char)*FILENAME_LEN); // apply tex-extenstion if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Briefing_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... else // ... otherwise ... { if ((ptr = strrchr(tmp, '.'))) *ptr = '\0'; strncat(tmp, ".txb", sizeof(char)*FILENAME_LEN); // apply txb extension if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Briefing_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... } d_free(tmp); } } } else if (istok(buf,"ending")) { if ((v = get_value(buf)) != NULL) { add_term(v); if (strlen(v) < FILENAME_LEN && strlen(v) > 0) { char *tmp, *ptr; MALLOC(tmp, char, FILENAME_LEN); snprintf(tmp, FILENAME_LEN, "%s", v); if ((ptr = strrchr(tmp, '.'))) // if there's a filename extension, kill it. No one knows it's the right one. *ptr = '\0'; strncat(tmp, ".tex", sizeof(char)*FILENAME_LEN); // apply tex-extenstion if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Briefing_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... else // ... otherwise ... { if ((ptr = strrchr(tmp, '.'))) *ptr = '\0'; strncat(tmp, ".txb", sizeof(char)*FILENAME_LEN); // apply txb extension if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Ending_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... } d_free(tmp); } } } else if (istok(buf,"num_levels")) { if ((v=get_value(buf))!=NULL) { int n_levels,i; n_levels = atoi(v); for (i=0;i<n_levels;i++) { PHYSFSX_fgets(buf,80,mfile); add_term(buf); if (strlen(buf) <= 12) { strcpy(Level_names[i],buf); Last_level++; } else break; } } } else if (istok(buf,"num_secrets")) { if ((v=get_value(buf))!=NULL) { int i; N_secret_levels = atoi(v); Assert(N_secret_levels <= MAX_SECRET_LEVELS_PER_MISSION); for (i=0;i<N_secret_levels;i++) { char *t; PHYSFSX_fgets(buf,80,mfile); if ((t=strchr(buf,','))!=NULL) *t++=0; else break; add_term(buf); if (strlen(buf) <= 12) { strcpy(Secret_level_names[i],buf); Secret_level_table[i] = atoi(t); if (Secret_level_table[i]<1 || Secret_level_table[i]>Last_level) break; Last_secret_level--; } else break; } } } } PHYSFS_close(mfile); if (Last_level <= 0) { free_mission(); //no valid mission loaded return 0; } // re-read default HAM file, in case this mission brings it's own version of it free_polygon_models(); read_hamfile(); if (Current_mission->enhanced) { char t[50]; extern void bm_read_extra_robots(); sprintf(t,"%s.ham",Current_mission_filename); bm_read_extra_robots(t, Current_mission->enhanced); init_extra_robot_movie(Current_mission_filename); } return 1; }
int ml_sort_func(mle *e0,mle *e1) { return d_stricmp(e0->mission_name,e1->mission_name); }
void verify_object( object * obj ) { obj->lifeleft = IMMORTAL_TIME; //all loaded object are immortal, for now if ( obj->type == OBJ_ROBOT ) { Gamesave_num_org_robots++; // Make sure valid id... if ( obj->id >= N_robot_types ) obj->id = obj->id % N_robot_types; // Make sure model number & size are correct... if ( obj->render_type == RT_POLYOBJ ) { obj->rtype.pobj_info.model_num = Robot_info[obj->id].model_num; obj->size = Polygon_models[obj->rtype.pobj_info.model_num].rad; //@@if (obj->control_type==CT_AI && Robot_info[obj->id].attack_type) //@@ obj->size = obj->size*3/4; } if (obj->movement_type == MT_PHYSICS) { obj->mtype.phys_info.mass = Robot_info[obj->id].mass; obj->mtype.phys_info.drag = Robot_info[obj->id].drag; } } else { //Robots taken care of above if ( obj->render_type == RT_POLYOBJ ) { int i; char *name = Save_pof_names[obj->rtype.pobj_info.model_num]; for (i=0;i<N_polygon_models;i++) if (!d_stricmp(Pof_names[i],name)) { //found it! obj->rtype.pobj_info.model_num = i; break; } } } if ( obj->type == OBJ_POWERUP ) { if ( obj->id >= N_powerup_types ) { obj->id = 0; Assert( obj->render_type != RT_POLYOBJ ); } obj->control_type = CT_POWERUP; obj->size = Powerup_info[obj->id].size; if (Game_mode & GM_NETWORK) { if (multi_powerup_is_4pack(obj->id)) { PowerupsInMine[obj->id-1]+=4; MaxPowerupsAllowed[obj->id-1]+=4; } else { PowerupsInMine[obj->id]++; MaxPowerupsAllowed[obj->id]++; } } } if ( obj->type == OBJ_WEAPON ) { if ( obj->id >= N_weapon_types ) { obj->id = 0; Assert( obj->render_type != RT_POLYOBJ ); } } if ( obj->type == OBJ_CNTRLCEN ) { int i; obj->render_type = RT_POLYOBJ; obj->control_type = CT_CNTRLCEN; // Make model number is correct... for (i=0; i<Num_total_object_types; i++ ) if ( ObjType[i] == OL_CONTROL_CENTER ) { obj->rtype.pobj_info.model_num = ObjId[i]; obj->shields = ObjStrength[i]; break; } } if ( obj->type == OBJ_PLAYER ) { //int i; //Assert(obj == Player); if ( obj == ConsoleObject ) init_player_object(); else if (obj->render_type == RT_POLYOBJ) //recover from Matt's pof file matchup bug obj->rtype.pobj_info.model_num = Player_ship->model_num; //Make sure orient matrix is orthogonal check_and_fix_matrix(&obj->orient); obj->id = Gamesave_num_players++; } if (obj->type == OBJ_HOSTAGE) { if (obj->id > N_hostage_types) obj->id = 0; obj->render_type = RT_HOSTAGE; obj->control_type = CT_POWERUP; } }
//loads the specfied mission from the mission list. //build_mission_list() must have been called. //Returns true if mission loaded ok, else false. int load_mission(mle *mission) { PHYSFS_file *mfile; char buf[PATH_MAX], *v; if (Current_mission) free_mission(); Current_mission = d_malloc(sizeof(Mission)); if (!Current_mission) return 0; *(mle *) Current_mission = *mission; Current_mission->path = d_strdup(mission->path); Current_mission->filename = Current_mission->path + (mission->filename - mission->path); Current_mission->n_secret_levels = 0; //init vars Last_level = 0; Last_secret_level = 0; memset(&Briefing_text_filename, '\0', sizeof(Briefing_text_filename)); memset(&Ending_text_filename, '\0', sizeof(Ending_text_filename)); Secret_level_table = NULL; Level_names = NULL; Secret_level_names = NULL; // for Descent 1 missions, load descent.hog if (!PHYSFSX_contfile_init("descent.hog", 1)) Error("descent.hog not available!\n"); if (!d_stricmp(Current_mission_filename, D1_MISSION_FILENAME)) return load_mission_d1(); //read mission from file switch (mission->location) { case ML_MISSIONDIR: strcpy(buf,MISSION_DIR); break; default: Int3(); //fall through case ML_CURDIR: strcpy(buf,""); break; } strcat(buf, mission->path); strcat(buf,".msn"); PHYSFSEXT_locateCorrectCase(buf); mfile = PHYSFSX_openReadBuffered(buf); if (mfile == NULL) { free_mission(); return 0; //error! } //for non-builtin missions, load HOG strcpy(buf+strlen(buf)-4,".hog"); //change extension PHYSFSEXT_locateCorrectCase(buf); if (PHYSFSX_exists(buf,1)) PHYSFSX_contfile_init(buf, 0); snprintf(Briefing_text_filename, sizeof(Briefing_text_filename), "%s.tex",Current_mission_filename); if (!PHYSFSX_exists(Briefing_text_filename,1)) snprintf(Briefing_text_filename, sizeof(Briefing_text_filename), "%s.txb",Current_mission_filename); snprintf(Ending_text_filename, sizeof(Ending_text_filename), "%s.tex",Current_mission_filename); if (!PHYSFSX_exists(Ending_text_filename,1)) snprintf(Ending_text_filename, sizeof(Ending_text_filename), "%s.txb",Current_mission_filename); while (PHYSFSX_fgets(buf,sizeof(buf),mfile)) { if (istok(buf,"type")) continue; //already have name, go to next line else if (istok(buf,"briefing")) { if ((v = get_value(buf)) != NULL) { add_term(v); if (strlen(v) < FILENAME_LEN && strlen(v) > 0) { char *tmp, *ptr; MALLOC(tmp, char, FILENAME_LEN); snprintf(tmp, FILENAME_LEN, "%s", v); if ((ptr = strrchr(tmp, '.'))) // if there's a filename extension, kill it. No one knows it's the right one. *ptr = '\0'; strncat(tmp, ".tex", sizeof(char)*FILENAME_LEN); // apply tex-extenstion if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Briefing_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... else // ... otherwise ... { if ((ptr = strrchr(tmp, '.'))) *ptr = '\0'; strncat(tmp, ".txb", sizeof(char)*FILENAME_LEN); // apply txb extension if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Briefing_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... } d_free(tmp); } } } else if (istok(buf,"ending")) { if ((v = get_value(buf)) != NULL) { add_term(v); if (strlen(v) < FILENAME_LEN && strlen(v) > 0) { char *tmp, *ptr; MALLOC(tmp, char, FILENAME_LEN); snprintf(tmp, FILENAME_LEN, "%s", v); if ((ptr = strrchr(tmp, '.'))) // if there's a filename extension, kill it. No one knows it's the right one. *ptr = '\0'; strncat(tmp, ".tex", sizeof(char)*FILENAME_LEN); // apply tex-extenstion if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Briefing_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... else // ... otherwise ... { if ((ptr = strrchr(tmp, '.'))) *ptr = '\0'; strncat(tmp, ".txb", sizeof(char)*FILENAME_LEN); // apply txb extension if (PHYSFSX_exists(tmp,1)) // check if this file exists ... snprintf(Ending_text_filename, FILENAME_LEN, "%s", tmp); // ... and apply ... } d_free(tmp); } } } else if (istok(buf,"num_levels")) { if ((v=get_value(buf))!=NULL) { int n_levels,i; n_levels = atoi(v); Assert(n_levels <= MAX_LEVELS_PER_MISSION); n_levels = min(n_levels, MAX_LEVELS_PER_MISSION); MALLOC(Level_names, d_fname, n_levels); if (!Level_names) { free_mission(); return 0; } for (i=0;i<n_levels;i++) { PHYSFSX_fgets(buf,sizeof(buf),mfile); add_term(buf); if (strlen(buf) <= 12) { strcpy(Level_names[i],buf); Last_level++; } else break; } } } else if (istok(buf,"num_secrets")) { if ((v=get_value(buf))!=NULL) { int i; N_secret_levels = atoi(v); Assert(N_secret_levels <= MAX_SECRET_LEVELS_PER_MISSION); N_secret_levels = min(N_secret_levels, MAX_SECRET_LEVELS_PER_MISSION); MALLOC(Secret_level_names, d_fname, N_secret_levels); if (!Secret_level_names) { free_mission(); return 0; } MALLOC(Secret_level_table, ubyte, N_secret_levels); if (!Secret_level_table) { free_mission(); return 0; } for (i=0;i<N_secret_levels;i++) { char *t; PHYSFSX_fgets(buf,sizeof(buf),mfile); if ((t=strchr(buf,','))!=NULL) *t++=0; else break; add_term(buf); if (strlen(buf) <= 12) { strcpy(Secret_level_names[i],buf); Secret_level_table[i] = atoi(t); if (Secret_level_table[i]<1 || Secret_level_table[i]>Last_level) break; Last_secret_level--; } else break; } } } } PHYSFS_close(mfile); if (Last_level <= 0) { free_mission(); //no valid mission loaded return 0; } return 1; }
/* Loads music file names from a given directory or M3U playlist */ void jukebox_load() { jukebox_unload(); // Check if it's an M3U file auto &cfgpath = CGameCfg.CMLevelMusicPath; size_t musiclen = strlen(cfgpath.data()); if (musiclen > 4 && !d_stricmp(&cfgpath[musiclen - 4], ".m3u")) read_m3u(); else // a directory { class PHYSFS_path_deleter { public: void operator()(const char *const p) const noexcept { PHYSFS_removeFromSearchPath(p); } }; std::unique_ptr<const char, PHYSFS_path_deleter> new_path; const char *sep = PHYSFS_getDirSeparator(); size_t seplen = strlen(sep); // stick a separator on the end if necessary. if (musiclen >= seplen) { auto p = &cfgpath[musiclen - seplen]; if (strcmp(p, sep)) cfgpath.copy_if(musiclen, sep, seplen); } const auto p = cfgpath.data(); // Read directory using PhysicsFS if (PHYSFS_isDirectory(p)) // find files in relative directory JukeboxSongs.list.reset(PHYSFSX_findFiles(p, jukebox_exts)); else { if (PHYSFSX_isNewPath(p)) new_path.reset(p); PHYSFS_addToSearchPath(p, 0); // as mountpoints are no option (yet), make sure only files originating from GameCfg.CMLevelMusicPath are aded to the list. JukeboxSongs.list.reset(PHYSFSX_findabsoluteFiles("", p, jukebox_exts)); } if (!JukeboxSongs.list) { return; } JukeboxSongs.num_songs = std::distance(JukeboxSongs.list.begin(), JukeboxSongs.list.end()); } if (JukeboxSongs.num_songs) { con_printf(CON_DEBUG,"Jukebox: %d music file(s) found in %s", JukeboxSongs.num_songs, cfgpath.data()); if (CGameCfg.CMLevelMusicTrack[1] != JukeboxSongs.num_songs) { CGameCfg.CMLevelMusicTrack[1] = JukeboxSongs.num_songs; CGameCfg.CMLevelMusicTrack[0] = 0; // number of songs changed so start from beginning. } } else { CGameCfg.CMLevelMusicTrack[0] = -1; CGameCfg.CMLevelMusicTrack[1] = -1; con_puts(CON_DEBUG,"Jukebox music could not be found!"); } }
int mix_play_file(char *filename, int loop, void (*hook_finished_track)()) { SDL_RWops *rw = NULL; PHYSFS_file *filehandle = NULL; char full_path[PATH_MAX]; char *fptr; unsigned int bufsize = 0; mix_free_music(); // stop and free what we're already playing, if anything fptr = strrchr(filename, '.'); if (fptr == NULL) return 0; // It's a .hmp! if (!d_stricmp(fptr, ".hmp")) { hmp2mid(filename, ¤t_music_hndlbuf, &bufsize); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); current_music = Mix_LoadMUS_RW(rw); } // try loading music via given filename if (!current_music) current_music = Mix_LoadMUS(filename); // allow the shell convention tilde character to mean the user's home folder // chiefly used for default jukebox level song music referenced in 'descent.m3u' for Mac OS X if (!current_music && *filename == '~') { snprintf(full_path, PATH_MAX, "%s%s", PHYSFS_getUserDir(), &filename[1 + (!strncmp(&filename[1], PHYSFS_getDirSeparator(), strlen(PHYSFS_getDirSeparator())) ? strlen(PHYSFS_getDirSeparator()) : 0)]); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // no luck. so it might be in Searchpath. So try to build absolute path if (!current_music) { PHYSFSX_getRealPath(filename, full_path); current_music = Mix_LoadMUS(full_path); if (current_music) filename = full_path; // used later for possible error reporting } // still nothin'? Let's open via PhysFS in case it's located inside an archive if (!current_music) { filehandle = PHYSFS_openRead(filename); if (filehandle != NULL) { current_music_hndlbuf = d_realloc(current_music_hndlbuf, sizeof(char *)*PHYSFS_fileLength(filehandle)); bufsize = PHYSFS_read(filehandle, current_music_hndlbuf, sizeof(char), PHYSFS_fileLength(filehandle)); rw = SDL_RWFromConstMem(current_music_hndlbuf,bufsize*sizeof(char)); PHYSFS_close(filehandle); current_music = Mix_LoadMUS_RW(rw); } } if (current_music) { Mix_PlayMusic(current_music, (loop ? -1 : 1)); Mix_HookMusicFinished(hook_finished_track ? hook_finished_track : mix_free_music); return 1; } else { con_printf(CON_CRITICAL,"Music %s could not be loaded: %s\n", filename, Mix_GetError()); mix_stop_music(); } return 0; }
static void ReadCmdArgs(Inilist &ini, Arglist &Args) { for (Arglist::iterator pp = Args.begin(), end = Args.end(); pp != end; ++pp) { const char *p = pp->c_str(); // System Options if (!d_stricmp(p, "-help") || !d_stricmp(p, "-h") || !d_stricmp(p, "-?") || !d_stricmp(p, "?")) CGameArg.SysShowCmdHelp = true; else if (!d_stricmp(p, "-nonicefps")) CGameArg.SysNoNiceFPS = true; else if (!d_stricmp(p, "-maxfps")) CGameArg.SysMaxFPS = arg_integer(pp, end); else if (!d_stricmp(p, "-hogdir")) CGameArg.SysHogDir = arg_string(pp, end); #if PHYSFS_VER_MAJOR >= 2 else if (!d_stricmp(p, "-add-missions-dir")) CGameArg.SysMissionDir = arg_string(pp, end); #endif else if (!d_stricmp(p, "-nohogdir")) { /* No effect on non-Unix. Ignore it so that players can * pass it via a cross-platform ini. */ #if defined(__unix__) CGameArg.SysNoHogDir = true; #endif } else if (!d_stricmp(p, "-use_players_dir")) CGameArg.SysUsePlayersDir = static_cast<int8_t>(- (sizeof(PLAYER_DIRECTORY_TEXT) - 1)); else if (!d_stricmp(p, "-lowmem")) CGameArg.SysLowMem = true; else if (!d_stricmp(p, "-pilot")) CGameArg.SysPilot = arg_string(pp, end); else if (!d_stricmp(p, "-record-demo-format")) CGameArg.SysRecordDemoNameTemplate = arg_string(pp, end); else if (!d_stricmp(p, "-auto-record-demo")) CGameArg.SysAutoRecordDemo = true; else if (!d_stricmp(p, "-window")) CGameArg.SysWindow = true; else if (!d_stricmp(p, "-noborders")) CGameArg.SysNoBorders = true; else if (!d_stricmp(p, "-notitles")) CGameArg.SysNoTitles = true; #if defined(DXX_BUILD_DESCENT_II) else if (!d_stricmp(p, "-nomovies")) GameArg.SysNoMovies = 1; #endif else if (!d_stricmp(p, "-autodemo")) CGameArg.SysAutoDemo = true; // Control Options else if (!d_stricmp(p, "-nocursor")) CGameArg.CtlNoCursor = true; else if (!d_stricmp(p, "-nomouse")) CGameArg.CtlNoMouse = true; else if (!d_stricmp(p, "-nojoystick")) { #if DXX_MAX_JOYSTICKS CGameArg.CtlNoJoystick = 1; #endif } else if (!d_stricmp(p, "-nostickykeys")) CGameArg.CtlNoStickyKeys = true; // Sound Options else if (!d_stricmp(p, "-nosound")) CGameArg.SndNoSound = 1; else if (!d_stricmp(p, "-nomusic")) CGameArg.SndNoMusic = true; #if defined(DXX_BUILD_DESCENT_II) else if (!d_stricmp(p, "-sound11k")) GameArg.SndDigiSampleRate = SAMPLE_RATE_11K; #endif else if (!d_stricmp(p, "-nosdlmixer")) { #if DXX_USE_SDLMIXER CGameArg.SndDisableSdlMixer = true; #endif } // Graphics Options else if (!d_stricmp(p, "-lowresfont")) CGameArg.GfxSkipHiresFNT = true; #if defined(DXX_BUILD_DESCENT_II) else if (!d_stricmp(p, "-lowresgraphics")) GameArg.GfxSkipHiresGFX = 1; else if (!d_stricmp(p, "-lowresmovies")) GameArg.GfxSkipHiresMovie = 1; #endif #if DXX_USE_OGL // OpenGL Options else if (!d_stricmp(p, "-gl_fixedfont")) CGameArg.OglFixedFont = true; else if (!d_stricmp(p, "-gl_syncmethod")) CGameArg.OglSyncMethod = arg_enum<SyncGLMethod>(pp, end); else if (!d_stricmp(p, "-gl_syncwait")) CGameArg.OglSyncWait = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_darkedges")) CGameArg.OglDarkEdges = true; #endif // Multiplayer Options #if DXX_USE_UDP else if (!d_stricmp(p, "-udp_hostaddr")) CGameArg.MplUdpHostAddr = arg_string(pp, end); else if (!d_stricmp(p, "-udp_hostport")) /* Peers use -udp_myport to change, so peer cannot set a * privileged port. */ arg_port_number(pp, end, CGameArg.MplUdpHostPort, false); else if (!d_stricmp(p, "-udp_myport")) { arg_port_number(pp, end, CGameArg.MplUdpMyPort, false); } else if (!d_stricmp(p, "-no-tracker")) { /* Always recognized. No-op if tracker support compiled * out. */ #if DXX_USE_TRACKER CGameArg.MplTrackerAddr.clear(); #endif } #if DXX_USE_TRACKER else if (!d_stricmp(p, "-tracker_hostaddr")) { CGameArg.MplTrackerAddr = arg_string(pp, end); } else if (!d_stricmp(p, "-tracker_hostport")) arg_port_number(pp, end, CGameArg.MplTrackerPort, true); #endif #endif #if defined(DXX_BUILD_DESCENT_I) else if (!d_stricmp(p, "-nobm")) GameArg.EdiNoBm = 1; #elif defined(DXX_BUILD_DESCENT_II) #if DXX_USE_EDITOR // Editor Options else if (!d_stricmp(p, "-autoload")) GameArg.EdiAutoLoad = arg_string(pp, end); else if (!d_stricmp(p, "-macdata")) GameArg.EdiMacData = 1; else if (!d_stricmp(p, "-hoarddata")) GameArg.EdiSaveHoardData = 1; #endif #endif // Debug Options else if (!d_stricmp(p, "-debug")) CGameArg.DbgVerbose = CON_DEBUG; else if (!d_stricmp(p, "-verbose")) CGameArg.DbgVerbose = CON_VERBOSE; else if (!d_stricmp(p, "-no-grab")) CGameArg.DbgForbidConsoleGrab = true; else if (!d_stricmp(p, "-safelog")) CGameArg.DbgSafelog = true; else if (!d_stricmp(p, "-norun")) CGameArg.DbgNoRun = true; else if (!d_stricmp(p, "-renderstats")) CGameArg.DbgRenderStats = true; else if (!d_stricmp(p, "-text")) CGameArg.DbgAltTex = arg_string(pp, end); else if (!d_stricmp(p, "-tmap")) CGameArg.DbgTexMap = arg_string(pp, end); else if (!d_stricmp(p, "-showmeminfo")) CGameArg.DbgShowMemInfo = 1; else if (!d_stricmp(p, "-nodoublebuffer")) CGameArg.DbgNoDoubleBuffer = true; else if (!d_stricmp(p, "-bigpig")) CGameArg.DbgNoCompressPigBitmap = true; else if (!d_stricmp(p, "-16bpp")) CGameArg.DbgBpp = 16; #if DXX_USE_OGL else if (!d_stricmp(p, "-gl_oldtexmerge")) CGameArg.DbgUseOldTextureMerge = true; else if (!d_stricmp(p, "-gl_intensity4_ok")) CGameArg.DbgGlIntensity4Ok = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_luminance4_alpha4_ok")) CGameArg.DbgGlLuminance4Alpha4Ok = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_rgba2_ok")) CGameArg.DbgGlRGBA2Ok = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_readpixels_ok")) CGameArg.DbgGlReadPixelsOk = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_gettexlevelparam_ok")) CGameArg.DbgGlGetTexLevelParamOk = arg_integer(pp, end); #else else if (!d_stricmp(p, "-hwsurface")) CGameArg.DbgSdlHWSurface = true; else if (!d_stricmp(p, "-asyncblit")) CGameArg.DbgSdlASyncBlit = true; #endif else if (!d_stricmp(p, "-ini")) { ini.emplace_back(arg_string(pp, end)); if (ini.size() > 10) throw nesting_depth_exceeded(); ReadIniArgs(ini); } else throw unhandled_argument(std::move(*pp)); } }
//loads a level (.LVL) file from disk //returns 0 if success, else error code int load_level(const char * filename_passed) { #ifdef EDITOR int use_compiled_level=1; #endif PHYSFS_file * LoadFile; char filename[PATH_MAX]; int sig, minedata_offset, gamedata_offset, hostagetext_offset; int mine_err, game_err; #ifdef NETWORK int i; #endif #ifdef NETWORK if (Game_mode & GM_NETWORK) { for (i=0;i<MAX_POWERUP_TYPES;i++) { MaxPowerupsAllowed[i]=0; PowerupsInMine[i]=0; } } #endif #ifdef COMPACT_SEGS ncache_flush(); #endif #ifndef RELEASE Level_being_loaded = filename_passed; #endif strcpy(filename,filename_passed); #ifdef EDITOR //if we have the editor, try the LVL first, no matter what was passed. //if we don't have an LVL, try what was passed or SDL/RDL //if we don't have the editor, we just use what was passed change_filename_extension(filename,filename_passed,".lvl"); use_compiled_level = 0; if (!PHYSFSX_exists(filename,1)) { char *p = strrchr(filename_passed, '.'); if (d_stricmp(p, ".lvl")) strcpy(filename, filename_passed); // set to what was passed else change_filename_extension(filename, filename, ".rdl"); use_compiled_level = 1; } #endif if (!PHYSFSX_exists(filename,1)) sprintf(filename,"%s%s",MISSION_DIR,filename_passed); LoadFile = PHYSFSX_openReadBuffered( filename ); if (!LoadFile) { #ifdef EDITOR return 1; #else Error("Can't open file <%s>\n",filename); #endif } strcpy( Gamesave_current_filename, filename ); sig = PHYSFSX_readInt(LoadFile); Gamesave_current_version = PHYSFSX_readInt(LoadFile); minedata_offset = PHYSFSX_readInt(LoadFile); gamedata_offset = PHYSFSX_readInt(LoadFile); Assert(sig == MAKE_SIG('P','L','V','L')); (void)sig; if (Gamesave_current_version < 5) hostagetext_offset = PHYSFSX_readInt(LoadFile); PHYSFSX_fseek(LoadFile,minedata_offset,SEEK_SET); #ifdef EDITOR if (!use_compiled_level) mine_err = load_mine_data(LoadFile); else #endif //NOTE LINK TO ABOVE!! mine_err = load_mine_data_compiled(LoadFile); /* !!!HACK!!! * Descent 1 - Level 19: OBERON MINE has some ugly overlapping rooms (segment 484). * HACK to make this issue less visible by moving one vertex a little. */ if (Current_mission && !d_stricmp("Descent: First Strike",Current_mission_longname) && !d_stricmp("level19.rdl",filename) && PHYSFS_fileLength(LoadFile) == 136706) Vertices[1905].z =-385*F1_0; if (mine_err == -1) { //error!! PHYSFS_close(LoadFile); return 2; } PHYSFSX_fseek(LoadFile,gamedata_offset,SEEK_SET); game_err = load_game_data(LoadFile); if (game_err == -1) { //error!! PHYSFS_close(LoadFile); return 3; } (void)hostagetext_offset; //======================== CLOSE FILE ============================= PHYSFS_close( LoadFile ); #if 0 //def EDITOR #ifndef RELEASE write_game_text_file(filename); if (Errors_in_mine) { if (is_real_level(filename)) { char ErrorMessage[200]; sprintf( ErrorMessage, "Warning: %i errors in %s!\n", Errors_in_mine, Level_being_loaded ); stop_time(); gr_palette_load(gr_palette); nm_messagebox( NULL, 1, "Continue", ErrorMessage ); start_time(); } } #endif #endif #ifdef EDITOR //If an old version, ask the use if he wants to save as new version if (((LEVEL_FILE_VERSION>1) && Gamesave_current_version<LEVEL_FILE_VERSION) || mine_err==1 || game_err==1) { char ErrorMessage[200]; sprintf( ErrorMessage, "You just loaded a old version level. Would\n" "you like to save it as a current version level?"); gr_palette_load(gr_palette); if (nm_messagebox( NULL, 2, "Don't Save", "Save", ErrorMessage )==1) save_level(filename); } #endif #ifdef EDITOR if (EditorWindow) editor_status_fmt("Loaded NEW mine %s, \"%s\"",filename,Current_level_name); #endif #if !defined(NDEBUG) && !defined(COMPACT_SEGS) if (check_segment_connections()) nm_messagebox( "ERROR", 1, "Ok", "Connectivity errors detected in\n" "mine. See monochrome screen for\n" "details, and contact Matt or Mike." ); #endif return 0; }