Compare commits

..
Author SHA1 Message Date
asarium 131d22c82a Add support for external subtitle files
This allows to use external subtile files (currently only SRT is
configured) for providing subtitles for movie files. This should be more
universal since it also supports container formats with no support for
subtitle streams.

To use this code the srt file needs to be named
"<movie name>-<language code>.srt" where the language code is the file
extension name specified in the localization table. For english the
"-..." part can be omitted.
2018-06-06 19:55:28 +02:00
339 changed files with 4507 additions and 25371 deletions

No files matched your search

-99
View File
@@ -1,99 +0,0 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^(<.*\.(h|hh|hpp)>)$' # Includes of external libraries
Priority: 4
- Regex: '^(<.*>)$' # standard library includes (won't match deprecated C headers)
Priority: 5
- Regex: '^"[^/]*\.(h)"$' # Local includes
Priority: 1
- Regex: '^".*\.(h)"$' # standard engine includes
Priority: 2
- Regex: '.*' # Catch all in case something is unhandled above
Priority: 3
IncludeIsMainRegex: '$'
IndentCaseLabels: false
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: ForIndentation
...
-1
View File
@@ -3,7 +3,6 @@ Checks: "-*,\
modernize-*,\
-modernize-raw-string-literal,\
-modernize-use-using,\
-modernize-make-unique,\
performance-*,\
-performance-type-promotion-in-math-fn,\
misc-*,\
+4 -4
View File
@@ -76,14 +76,14 @@ matrix:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Debug" CC=gcc-8 CXX=g++-8
env: CONFIGURATION="Debug" CC=gcc-7 CXX=g++-7
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- g++-8
- g++-7
- *global_deps
- os: linux
env: CONFIGURATION="Debug" CC=clang-4.0 CXX=clang++-4.0 CMAKE_OPTIONS="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
@@ -115,14 +115,14 @@ matrix:
- *global_deps
- g++-5
- os: linux
env: CONFIGURATION="Release" CC=gcc-8 CXX=g++-8
env: CONFIGURATION="Release" CC=gcc-7 CXX=g++-7
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt571-trusty'
packages:
- g++-8
- g++-7
- *global_deps
- os: linux
env: CONFIGURATION="Release" CC=clang-4.0 CXX=clang++-4.0
+2 -7
View File
@@ -7,13 +7,8 @@ cd build
if [ "$TRAVIS_OS_NAME" = "linux" ]; then
ninja -k 20 all
if [ "$CONFIGURATION" = "Debug" ]; then
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
else
./bin/unittests --gtest_shuffle
fi
valgrind --leak-check=full --error-exitcode=1 --gen-suppressions=all \
--suppressions="$TRAVIS_BUILD_DIR/ci/travis/valgrind.supp" ./bin/unittests --gtest_shuffle
elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
cmake --build . --config "$CONFIGURATION" | tee build.log | xcpretty
XCODE_RET=${PIPESTATUS[0]}
+1 -9
View File
@@ -25,12 +25,4 @@
fun:_dl_init
fun:dl_open_worker
fun:_dl_catch_error
}
{
CLang Lua unitialized value error
Memcheck:Cond
...
fun:luaH_get
fun:lua_rawget
fun:_ZN12_GLOBAL__N_117ade_index_handlerEP9lua_State
}
}
-11
View File
@@ -85,17 +85,6 @@ set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wreturn-type")
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-deprecated -Wno-char-subscripts")
# These two warnings cause a lot of false-positives in the FSO code base
check_cxx_compiler_flag(-Wstringop-truncation SUPPORTS_STRINGOP_TRUNCATION)
if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-truncation")
endif()
check_cxx_compiler_flag(-Wstringop-overflow SUPPORTS_STRINGOP_OVERFLOW)
if(SUPPORTS_STRINGOP_TRUNCATION)
set(COMPILER_FLAGS "${COMPILER_FLAGS} -Wno-stringop-overflow")
endif()
set(COMPILER_FLAGS_RELEASE "-O2 -Wno-unused-variable -Wno-unused-but-set-variable -Wno-array-bounds -Wno-empty-body -Wno-clobbered -Wno-unused-parameter")
set(COMPILER_FLAGS_DEBUG "-O0 -g -Wshadow")
-10
View File
@@ -225,13 +225,3 @@ function(list_target_dependencies _target _out_var)
list(REMOVE_DUPLICATES out_list)
set(${_out_var} ${out_list} PARENT_SCOPE)
endfunction(list_target_dependencies)
macro(add_file_folder FOLDER_NAME)
string(MAKE_C_IDENTIFIER "${FOLDER_NAME}" VARIABLE_NAME)
set(files_${VARIABLE_NAME} ${files_${VARIABLE_NAME}} ${ARGN})
string(REPLACE "/" "\\" FIXED_FOLDER_FILE "${FOLDER_NAME}")
source_group("${FIXED_FOLDER_FILE}" FILES ${ARGN})
set(source_files ${source_files} ${ARGN})
endmacro(add_file_folder)
+1 -3
View File
@@ -3,7 +3,7 @@ INCLUDE(source_groups.cmake)
INCLUDE(voice_rec.cmake)
ADD_LIBRARY(code STATIC ${source_files} ${VOICE_REC_FILES})
ADD_LIBRARY(code STATIC ${file_root} ${VOICE_REC_FILES})
target_compile_features(code PUBLIC ${REQUIRED_CXX_FEATURES})
@@ -37,8 +37,6 @@ TARGET_LINK_LIBRARIES(code PUBLIC compiler)
target_link_libraries(code PUBLIC md5)
target_link_libraries(code PUBLIC discord-rpc)
enable_clang_tidy(code)
IF (FSO_USE_SPEECH)
+4 -4
View File
@@ -567,9 +567,9 @@ extern void ai_dock_with_object(object *docker, int docker_index, object *dockee
extern void ai_stay_still(object *still_objp, vec3d *view_pos);
extern void ai_do_default_behavior(object *obj);
extern void ai_start_waypoints(object *objp, waypoint_list *wp_list, int wp_flags);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = nullptr, int sexp_flags = 0);
extern void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int shield_quadrant, vec3d *hit_normal);
extern void ai_ship_destroy(int shipnum, Ship::Exit_Flags method);
extern void ai_turn_towards_vector(vec3d *dest, object *objp, float frametime, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec = NULL, int sexp_flags = 0);
extern void init_ai_object(int objnum);
extern void ai_init(void); // Call this one to parse ai.tbl.
extern void ai_level_init(void); // Call before each level to reset AI
@@ -622,7 +622,7 @@ extern float ai_path();
extern void evade_weapon();
extern int might_collide_with_ship(object *obj1, object *obj2, float dot_to_enemy, float dist_to_enemy, float duration);
extern int ai_fire_primary_weapon(object *objp); //changed to return weather it fired-Bobboau
extern int ai_fire_secondary_weapon(object *objp);
extern int ai_fire_secondary_weapon(object *objp, int priority1 = -1, int priority2 = -1);
extern float ai_get_weapon_dist(ship_weapon *swp);
extern void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank_override);
extern int ai_maybe_fire_afterburner(object *objp, ai_info *aip);
-1
View File
@@ -110,7 +110,6 @@ namespace AI {
Smart_subsystem_targeting_for_turrets,
Strict_turred_tagged_only_targeting,
Turrets_ignore_target_radius,
Use_actual_primary_range,
Use_additive_weapon_velocity,
Use_newtonian_dampening,
Use_only_single_fov_for_turrets,
-2
View File
@@ -458,8 +458,6 @@ void parse_ai_profiles_tbl(const char *filename)
set_flag(profile, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
set_flag(profile, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
if (optional_string("$bay arrive speed multiplier:")) {
+24 -18
View File
@@ -64,11 +64,10 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
void ai_big_avoid_ship();
int ai_big_maybe_follow_subsys_path(int do_dot_check=1);
void ai_big_strafe_position();
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos);
extern int model_which_octant_distant_many( vec3d *pnt, int model_num,matrix *model_orient, vec3d * model_pos, polymodel **pm, int *octs);
extern void compute_desired_rvec(vec3d *rvec, vec3d *goal_pos, vec3d *cur_pos);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal);
extern void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collide_pos, vec3d *collision_normal);
// Called by ai_big_pick_attack_point.
@@ -632,7 +631,7 @@ void ai_big_chase_attack(ai_info *aip, ship_info *sip, vec3d *enemy_pos, float d
else
rvec = NULL;
ai_turn_towards_vector(enemy_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, 0.0f, 0, rvec);
ai_turn_towards_vector(enemy_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, 0.0f, 0, rvec);
// calc range of primary weapon
weapon_travel_dist = ai_get_weapon_dist(&Ships[Pl_objp->instance].weapons);
@@ -708,14 +707,14 @@ extern float set_secondary_fire_delay(ai_info *aip, ship *shipp, weapon_info *sw
extern void ai_choose_secondary_weapon(object *objp, ai_info *aip, object *en_objp);
extern int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d *goal_point, float delta_time);
extern void maybe_cheat_fire_synaptic(object *objp);
extern void maybe_cheat_fire_synaptic(object *objp, ai_info *aip);
// Determine if Pl_objp should fire weapons at current target, based on input parameters
//
// dist_to_enemy => distance (in m) to attack point on current target
// dot_to_enemy => dot product between fvec of Pl_objp and vector from Pl_objp to attack point
//
static void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy)
void ai_big_maybe_fire_weapons(float dist_to_enemy, float dot_to_enemy, vec3d * /*firing_pos*/, vec3d * /*enemy_pos*/, vec3d * /*enemy_vel*/)
{
ai_info *aip;
ship_weapon *swp;
@@ -846,6 +845,8 @@ void ai_big_switch_to_chase_mode(ai_info *aip)
aip->submode_start_time = Missiontime;
}
extern int ai_big_strafe_maybe_retreat(float dist, vec3d *target_pos);
// Make object Pl_objp chase object En_objp, which is a big ship, not a small ship.
void ai_big_chase()
{
@@ -858,7 +859,7 @@ void ai_big_chase()
Assert(aip->mode == AIM_CHASE);
maybe_cheat_fire_synaptic(Pl_objp);
maybe_cheat_fire_synaptic(Pl_objp, aip);
ai_set_positions(Pl_objp, En_objp, aip, &player_pos, &enemy_pos);
@@ -881,7 +882,7 @@ void ai_big_chase()
dot_to_enemy = vm_vec_dot(&vec_to_enemy, &Pl_objp->orient.vec.fvec);
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
if ( ai_big_strafe_maybe_retreat(&enemy_pos) ) {
if ( ai_big_strafe_maybe_retreat(dist_to_enemy, &enemy_pos) ) {
aip->mode = AIM_STRAFE;
aip->submode_parm0 = Missiontime; // use parm0 as time strafe mode entered (i.e. MODE start time)
aip->submode = AIS_STRAFE_AVOID;
@@ -1044,7 +1045,7 @@ void ai_big_chase()
if ((dist_normal_to_enemy < ATTACK_COLLIDE_AVOID_DIST + speed_dist) || (time_to_enemy < ATTACK_COLLIDE_AVOID_TIME) ) {
// get away, simulate crsh recovery (don't use avoid)
// accelerate_ship(aip, -1.0f);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
// aip->submode = SM_AVOID;
// aip->submode_start_time = Missiontime;
} else if ((dist_normal_to_enemy < ATTACK_COLLIDE_SLOW_DIST) || (time_to_enemy < ATTACK_COLLIDE_SLOW_TIME) ) {
@@ -1143,7 +1144,7 @@ void ai_big_chase()
// TODO: investigate why ships fire (and aren't close to hitting ship) when following a path near
// a big ship
if (aip->mode != AIM_EVADE && aip->path_start == -1 ) {
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy);
ai_big_maybe_fire_weapons(dist_to_enemy, dot_to_enemy, &player_pos, &predicted_enemy_pos, &En_objp->phys_info.vel);
} else {
if (flFrametime < 1.0f)
aip->time_enemy_in_range *= (1.0f - flFrametime);
@@ -1152,6 +1153,11 @@ void ai_big_chase()
}
}
void ai_big_ship(object * /*objp*/)
{
// do nothing
}
// all three parms are output parameters
// Enemy object is En_objp
// pos => world pos of attack point
@@ -1222,7 +1228,7 @@ void ai_big_attack_get_data(vec3d *enemy_pos, float *dist_to_enemy, float *dot_t
// check to see if Pl_objp has gotten too close to attacking point.. if so, break off by entering
// AIS_STRAFE_RETREAT
static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
int ai_big_strafe_maybe_retreat(float /*dist*/, vec3d *target_pos)
{
ai_info *aip;
aip = &Ai_info[Ships[Pl_objp->instance].ai_index];
@@ -1252,7 +1258,7 @@ static int ai_big_strafe_maybe_retreat(const vec3d *target_pos)
if (aip->ai_flags[AI::AI_Flags::Target_collision]) {
// use standard collision resolution
aip->ai_flags.remove(AI::AI_Flags::Target_collision);
big_ship_collide_recover_start(Pl_objp, En_objp, nullptr);
big_ship_collide_recover_start(Pl_objp, En_objp, &Pl_objp->pos, NULL);
} else {
// too close for comfort so fly to box point + 300
aip->submode = AIS_STRAFE_RETREAT1;
@@ -1292,12 +1298,12 @@ void ai_big_strafe_attack()
}
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(&target_pos) )
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
return;
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
if (target_dist < 1200.0f) {
ai_turn_towards_vector(&target_pos, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&target_pos, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((target_dist < 400.0f) && ai_maybe_fire_afterburner(Pl_objp, aip)) {
afterburners_start(Pl_objp);
@@ -1341,7 +1347,7 @@ void ai_big_strafe_attack()
}
// maybe fire weapons at target
ai_big_maybe_fire_weapons(target_dist, target_dot);
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
fix last_hit = Missiontime - aip->last_hit_time;
@@ -1487,7 +1493,7 @@ void ai_big_strafe_glide_attack()
vm_vec_sub2(&target_pos, &En_objp->pos);
turn_towards_point(Pl_objp, &target_pos, NULL, 0.0f);
ai_big_maybe_fire_weapons(target_dist, target_dot);
ai_big_maybe_fire_weapons(target_dist, target_dot, &Pl_objp->pos, &En_objp->pos, &En_objp->phys_info.vel);
}
// if haven't been hit in quite a while, leave strafe mode
@@ -1511,7 +1517,7 @@ void ai_big_strafe_avoid()
mode_time = Missiontime - aip->submode_start_time;
ai_big_attack_get_data(&target_pos, &target_dist, &target_dot);
if ( ai_big_strafe_maybe_retreat(&target_pos) )
if ( ai_big_strafe_maybe_retreat(target_dist, &target_pos) )
return;
if ( mode_time > fl2f(0.5)) {
@@ -1698,7 +1704,7 @@ void ai_big_strafe()
//
// Check if weapon_objnum was fired by Pl_objp's target, and whether Pl_objp's target is a big ship, if
// so, enter AIM_STRAFE
int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
int ai_big_maybe_enter_strafe_mode(object *pl_objp, int weapon_objnum, int /*consider_target_only*/)
{
ai_info *aip;
ship_info *sip;
@@ -1772,7 +1778,7 @@ int ai_big_maybe_enter_strafe_mode(const object *pl_objp, int weapon_objnum)
// Consider attacking a turret, if a turret actually fired the weapon
// input: ship_objp => ship that will attack the turret
// weapon_objp =>
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp)
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp)
{
ai_info *aip;
object *parent_objp;
+3 -2
View File
@@ -17,13 +17,14 @@ struct ai_info;
struct vec3d;
class ship_subsys;
void ai_big_ship(object *objp);
void ai_big_chase();
void ai_big_subsys_path_cleanup(ai_info *aip);
// strafe functions
void ai_big_strafe();
int ai_big_maybe_enter_strafe_mode(const object *objp, int weapon_objnum);
void ai_big_strafe_maybe_attack_turret(const object *ship_objp, const object *weapon_objp);
int ai_big_maybe_enter_strafe_mode(object *objp, int weapon_objnum, int consider_target_only=0);
void ai_big_strafe_maybe_attack_turret(object *ship_objp, object *weapon_objp);
void ai_big_pick_attack_point(object *objp, object *attacker_objp, vec3d *attack_point, float fov=1.0f);
void ai_big_pick_attack_point_turret(object *objp, ship_subsys *ssp, vec3d *gpos, vec3d *gvec, vec3d *attack_point, float weapon_travel_dist, float fov=1.0f);
+97 -69
View File
@@ -764,8 +764,6 @@ void parse_ai_class()
set_aic_flag(aicp, "$all ships manage shields:", AI::Profile_Flags::All_ships_manage_shields);
set_aic_flag(aicp, "$ai can slow down when attacking big ships:", AI::Profile_Flags::Ai_can_slow_down_attacking_big_ships);
set_aic_flag(aicp, "$use actual primary range:", AI::Profile_Flags::Use_actual_primary_range);
}
void reset_ai_class_names()
@@ -1134,7 +1132,7 @@ void ai_update_danger_weapon(int attacked_objnum, int weapon_objnum)
// If rvec != NULL, use it to match bank by calling vm_matrix_interpolate.
// (rvec defaults to NULL)
void ai_turn_towards_vector(vec3d *dest, object *objp, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
void ai_turn_towards_vector(vec3d *dest, object *objp, float /*frametime*/, float turn_time, vec3d *slide_vec, vec3d *rel_pos, float bank_override, int flags, vec3d *rvec, int sexp_flags)
{
matrix curr_orient;
vec3d vel_in, vel_out, desired_fvec, src;
@@ -1502,12 +1500,12 @@ void turn_towards_point(object *objp, vec3d *point, vec3d *slide_vec, float bank
if (aip->ai_flags[AI::AI_Flags::Formation_object, AI::AI_Flags::Formation_wing]) {
if (&Objects[aip->goal_objnum] != objp) {
float rotvel_z = objp->phys_info.rotvel.xyz.z;
ai_turn_towards_vector(point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, nullptr, bank_override, 0);
ai_turn_towards_vector(point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, NULL, bank_override, 0);
objp->phys_info.rotvel.xyz.z = rotvel_z;
}
} else {
// normal turn
ai_turn_towards_vector(point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, nullptr, bank_override, 0);
ai_turn_towards_vector(point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, slide_vec, NULL, bank_override, 0);
}
}
@@ -1522,7 +1520,7 @@ void turn_away_from_point(object *objp, vec3d *point, float bank_override)
vm_vec_sub(&opposite_point, &objp->pos, point);
vm_vec_add2(&opposite_point, &objp->pos);
ai_turn_towards_vector(&opposite_point, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, bank_override, AITTV_FAST);
ai_turn_towards_vector(&opposite_point, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, bank_override, AITTV_FAST);
}
@@ -3450,6 +3448,35 @@ float compute_time_to_enemy(float dist_to_enemy, object *pobjp)
return time_to_enemy + flFrametime;
}
// Stuff *dot and *tts.
// *dot is always computed. If dot is less than zero, the magnitude is
// incorrect, not having been divided by distance.
// If *dot is > 0.0f, then tts is computed. This is the time it will take object
// *objp to get to *pos, assuming it moves right at it.
void fds_aux(float *dot, float *tts, vec3d *pos, float /*dtime*/, object *objp)
{
vec3d v2s;
vm_vec_sub(&v2s, pos, &objp->pos);
*dot = vm_vec_dot(&v2s, &objp->orient.vec.fvec);
if (*dot > 0.0f) {
float dist;
dist = vm_vec_dist(&objp->pos, pos);
if (dist > 0.1f)
*dot /= dist;
else
*dot = 1.0f;
if (objp->phys_info.speed > 0.1f)
*tts = dist / objp->phys_info.speed;
else
*tts = dist * 100.0f;
}
}
// --------------------------------------------------------------------------
void ai_set_positions(object *pl_objp, object *en_objp, ai_info *aip, vec3d *player_pos, vec3d *enemy_pos)
{
@@ -3865,7 +3892,7 @@ float ai_path_0()
}
if (dist_to_goal > 0.1f)
ai_turn_towards_vector(&gcvp, Pl_objp, sip->srotation_time, slop_vec, nullptr, 0.0f, 0);
ai_turn_towards_vector(&gcvp, Pl_objp, flFrametime, sip->srotation_time, slop_vec, NULL, 0.0f, 0);
// Code to control speed is MUCH less forgiving in path following than in waypoint
// following. Must be very close to path or might hit objects.
@@ -4007,10 +4034,10 @@ float ai_path_1()
if (r <= 1.0f) {
vec3d midpoint;
vm_vec_avg3(&midpoint, &gcvp, &closest_point, &closest_point);
ai_turn_towards_vector(&midpoint, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, prvec);
ai_turn_towards_vector(&midpoint, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, prvec);
}
else {
ai_turn_towards_vector(&gcvp, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, prvec);
ai_turn_towards_vector(&gcvp, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, prvec);
}
}
@@ -4355,11 +4382,11 @@ void ai_fly_to_target_position(vec3d* target_pos, bool* pl_done_p=NULL, bool* pl
vm_vector_2_matrix(&Pl_objp->orient, &perp, NULL, NULL);
} else {
vm_vec_scale_add(&perp, &Pl_objp->pos, &Autopilot_flight_leader->phys_info.vel, 1000.0f);
ai_turn_towards_vector(&perp, Pl_objp, sip->srotation_time*3.0f*scale, slop_vec, nullptr, 0.0f, 0);
ai_turn_towards_vector(&perp, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
}
} else {
if (dist_to_goal > 0.1f) {
ai_turn_towards_vector(target_pos, Pl_objp, sip->srotation_time*3.0f*scale, slop_vec, nullptr, 0.0f, 0);
ai_turn_towards_vector(target_pos, Pl_objp, flFrametime, sip->srotation_time*3.0f*scale, slop_vec, NULL, 0.0f, 0);
}
}
@@ -5024,7 +5051,7 @@ void slide_face_ship()
dist = vm_vec_normalized_dir(&vec_from_enemy, &Pl_objp->pos, &En_objp->pos);
ai_turn_towards_vector(&En_objp->pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&En_objp->pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
dot_from_enemy = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
@@ -5207,7 +5234,7 @@ vec3d G_predicted_pos, G_fire_pos;
// Else
// Select Any ol' weapon.
// Returns primary_bank index.
static int ai_select_primary_weapon_OLD(const object *objp, Weapon::Info_Flags flags)
int ai_select_primary_weapon_OLD(object *objp, object * /*other_objp*/, Weapon::Info_Flags flags)
{
ship *shipp = &Ships[objp->instance];
ship_weapon *swp = &shipp->weapons;
@@ -5298,7 +5325,7 @@ int ai_select_primary_weapon(object *objp, object *other_objp, Weapon::Info_Flag
//not using the new AI, use the old version of this function instead.
if (!(Ai_info[shipp->ai_index].ai_profile_flags[AI::Profile_Flags::Smart_primary_weapon_selection]))
{
return ai_select_primary_weapon_OLD(objp, flags);
return ai_select_primary_weapon_OLD(objp, other_objp, flags);
}
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()));
@@ -6024,7 +6051,8 @@ int check_ok_to_fire(int objnum, int target_objnum, weapon_info *wip)
// --------------------------------------------------------------------------
// Fire a secondary weapon.
// Maybe choose to fire a different one.
int ai_fire_secondary_weapon(object *objp)
// priority1 and priority2 are optional parameters with defaults = -1
int ai_fire_secondary_weapon(object *objp, int /*priority1*/, int /*priority2*/)
{
ship_weapon *swp;
ship *shipp;
@@ -6044,7 +6072,7 @@ int ai_fire_secondary_weapon(object *objp)
Assert( shipp->ship_info_index >= 0 && shipp->ship_info_index < static_cast<int>(Ship_info.size()));
// Select secondary weapon.
current_bank = swp->current_secondary_bank;
current_bank = swp->current_secondary_bank; //ai_select_secondary_weapon(objp, swp, priority1, priority2);
if (current_bank == -1) {
return rval;
@@ -6511,14 +6539,14 @@ void ai_chase_ct()
vm_vec_add2(&tvec, &Pl_objp->orient.vec.rvec);
}
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 1.0f);
}
/**
* ATTACK submode handler for chase mode.
*/
static void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos)
void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, float /*dist_to_enemy*/)
{
vec3d _pep;
float dot_to_enemy, dot_from_enemy;
@@ -6530,7 +6558,7 @@ static void ai_chase_eb(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos
if ((dot_to_enemy > dot_from_enemy + 0.1f) || (dot_to_enemy > 0.9f))
vm_vec_scale_add(&_pep, &Pl_objp->pos, &En_objp->orient.vec.fvec, 100.0f);
ai_turn_towards_vector(&_pep, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&_pep, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 0.0f);
}
@@ -6727,7 +6755,7 @@ void attack_set_accel(ai_info *aip, ship_info *sip, float dist_to_enemy, float d
// Pl_objp (aip) tries to get behind En_objp.
// New on 2/21/98: If this ship can move backwards and slide, maybe do that to get behind.
static void get_behind_ship(ai_info *aip, ship_info *sip)
void get_behind_ship(ai_info *aip, ship_info *sip, float /*dist_to_enemy*/)
{
vec3d new_pos;
float dot;
@@ -6736,7 +6764,7 @@ static void get_behind_ship(ai_info *aip, ship_info *sip)
vm_vec_normalized_dir(&vec_from_enemy, &Pl_objp->pos, &En_objp->pos);
vm_vec_scale_add(&new_pos, &En_objp->pos, &En_objp->orient.vec.fvec, -100.0f); // Pick point 100 units behind.
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
dot = vm_vec_dot(&vec_from_enemy, &En_objp->orient.vec.fvec);
@@ -6755,7 +6783,7 @@ int avoid_player(object *objp, vec3d *goal_pos)
if (aip->ai_flags[AI::AI_Flags::Avoiding_small_ship]) {
ship_info *sip = &Ship_info[Ships[objp->instance].ship_info_index];
ai_turn_towards_vector(&aip->avoid_goal_point, objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&aip->avoid_goal_point, objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 0.5f);
return 1;
}
@@ -6953,7 +6981,7 @@ int maybe_avoid_big_ship(object *objp, object *ignore_objp, ai_info *aip, vec3d
vec3d v2g;
ai_turn_towards_vector(&aip->avoid_goal_point, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&aip->avoid_goal_point, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
vm_vec_normalized_dir(&v2g, &aip->avoid_goal_point, &Pl_objp->pos);
float dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
float d2 = (1.0f + dot) * (1.0f + dot);
@@ -7045,7 +7073,7 @@ void ai_stealth_find()
}
}
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
return;
}
@@ -7055,9 +7083,9 @@ void ai_stealth_find()
if (dist_to_enemy > 500.0f) {
vec3d rvec;
compute_desired_rvec(&rvec, &new_pos, &Pl_objp->pos);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0, &rvec);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0, &rvec);
} else {
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
}
dot_from_enemy = -vm_vec_dot(&vec_to_enemy, &En_objp->orient.vec.fvec);
@@ -7185,7 +7213,7 @@ void ai_stealth_sweep()
return;
}
ai_turn_towards_vector(&goal_pt, Pl_objp, sip->srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&goal_pt, Pl_objp, flFrametime, sip->srotation_time, NULL, NULL, 0.0f, 0);
float dot = 1.0f;
if (dist_to_goal < 100) {
@@ -7245,9 +7273,9 @@ void ai_chase_attack(ai_info *aip, ship_info *sip, vec3d *predicted_enemy_pos, f
if (dist_to_enemy > 500.0f) {
vec3d rvec;
compute_desired_rvec(&rvec, predicted_enemy_pos, &Pl_objp->pos);
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, bank_override, 0, &rvec);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, bank_override, 0, &rvec);
} else {
ai_turn_towards_vector(&new_pos, Pl_objp, sip->srotation_time, nullptr, rel_pos, bank_override, 0);
ai_turn_towards_vector(&new_pos, Pl_objp, flFrametime, sip->srotation_time, NULL, rel_pos, bank_override, 0);
}
attack_set_accel(aip, sip, dist_to_enemy, dot_to_enemy, dot_from_enemy);
@@ -7285,7 +7313,7 @@ void ai_chase_es(ai_info *aip, ship_info *sip)
float bank_override = Pl_objp->phys_info.speed;
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, bank_override, 0);
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime/2, sip->srotation_time, NULL, NULL, bank_override, 0);
accelerate_ship(aip, 1.0f);
}
@@ -7311,7 +7339,7 @@ void ai_chase_ga(ai_info *aip, ship_info *sip)
bank_override = Pl_objp->phys_info.speed;
ai_turn_towards_vector(&tvec, Pl_objp, sip->srotation_time, nullptr, nullptr, bank_override, 0);
ai_turn_towards_vector(&tvec, Pl_objp, flFrametime/2, sip->srotation_time, NULL, NULL, bank_override, 0);
accelerate_ship(aip, 2.0f);
@@ -7973,7 +8001,7 @@ void ai_cruiser_chase()
// kamikaze - ram and explode
if (aip->ai_flags[AI::AI_Flags::Kamikaze]) {
ai_turn_towards_vector(&En_objp->pos, Pl_objp, turn_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&En_objp->pos, Pl_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 1.0f);
}
@@ -8013,7 +8041,7 @@ void ai_cruiser_chase()
}
// now move as desired
ai_turn_towards_vector(&goal_pos, Pl_objp, turn_time, nullptr, nullptr, 0.0f, 0, rvecp);
ai_turn_towards_vector(&goal_pos, Pl_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0, rvecp);
accelerate_ship(aip, accel);
// maybe switch to new mode
@@ -8294,7 +8322,7 @@ void ai_chase()
break;
case SM_EVADE_BRAKE:
ai_chase_eb(aip, sip, &predicted_enemy_pos);
ai_chase_eb(aip, sip, &predicted_enemy_pos, dist_to_enemy);
break;
case SM_EVADE:
@@ -8306,7 +8334,7 @@ void ai_chase()
break;
case SM_GET_BEHIND:
get_behind_ship(aip, sip);
get_behind_ship(aip, sip, dist_to_enemy);
break;
case SM_GET_AWAY: // Used to get away from opponent to prevent endless circling.
@@ -8740,11 +8768,7 @@ void ai_chase()
scale = (scale - 0.6f) * 1.5f;
else
scale = 0.0f;
float range = pwip->max_speed * (1.0f + scale);
if (aip->ai_profile_flags[AI::Profile_Flags::Use_actual_primary_range]) {
range = std::min( {range, pwip->max_speed * pwip->lifetime, pwip->weapon_range} );
}
if (dist_to_enemy < range) {
if (dist_to_enemy < pwip->max_speed * (1.0f + scale)) {
if(ai_fire_primary_weapon(Pl_objp) == 1){
has_fired = 1;
}else{
@@ -9305,7 +9329,7 @@ float dock_orient_and_approach(object *docker_objp, int docker_index, object *do
{
float dot, accel;
float turn_time = Ship_info[Ships[docker_objp->instance].ship_info_index].srotation_time;
ai_turn_towards_vector(&goal_point, docker_objp, turn_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&goal_point, docker_objp, flFrametime, turn_time, NULL, NULL, 0.0f, 0);
dot = vm_vec_dot(&docker_objp->orient.vec.fvec, &away_vec);
accel = 0.1f;
@@ -9940,7 +9964,7 @@ void ai_big_guard()
}
// got the point, now let's go there
ai_turn_towards_vector(&goal_pt, Pl_objp, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0);
ai_turn_towards_vector(&goal_pt, Pl_objp, flFrametime, Ship_info[Ships[Pl_objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0);
accelerate_ship(aip, 1.0f);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (cur_guard_rad > 1.1f * max_guard_dist)) {
@@ -10064,7 +10088,7 @@ void ai_guard()
// quite far away, so try to go straight to
compute_desired_rvec(&rvec, &goal_point, &Pl_objp->pos);
ai_turn_towards_vector(&goal_point, Pl_objp, Ship_info[shipp->ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, &rvec);
ai_turn_towards_vector(&goal_point, Pl_objp, flFrametime, Ship_info[shipp->ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, &rvec);
if ((aip->ai_flags[AI::AI_Flags::Free_afterburner_use]) && !(shipp->flags[Ship::Ship_Flags::Afterburner_locked]) && (accel_scale * (0.25f + dist_to_goal_point/700.0f) > 0.8f)) {
if (ai_maybe_fire_afterburner(Pl_objp, aip)) {
@@ -10689,8 +10713,8 @@ void ai_dock()
char *goal_ship_class_name = goal_sip->name;
char *goal_dock_path_name = model_get(goal_sip->model_num)->paths[aip->mp_index].name;
mprintf(("Ship class %s has only %i points on dock path \"%s\". Recommended minimum number of points is 4. "\
"Docking along that path will look strange. You may wish to edit the model.", goal_ship_class_name, aip->path_length, goal_dock_path_name));
Warning(LOCATION, "Ship class %s has only %i points on dock path \"%s\". Recommended minimum number of points is 4. "\
"Docking along that path will look strange. You may wish to edit the model.", goal_ship_class_name, aip->path_length, goal_dock_path_name);
}
aip->submode = AIS_DOCK_1;
@@ -11361,7 +11385,7 @@ float gwlr_1(object *objp, ai_info *aip)
/**
* Compute the largest radius of a ship forming on *objp's wing.
*/
static float gwlr_object_1(object *objp)
float gwlr_object_1(object *objp, ai_info * /*aip*/)
{
float max_radius;
object *o;
@@ -11394,7 +11418,7 @@ float get_wing_largest_radius(object *objp, int formation_object_flag)
aip = &Ai_info[shipp->ai_index];
if (formation_object_flag) {
return gwlr_object_1(objp);
return gwlr_object_1(objp, aip);
} else {
return gwlr_1(objp, aip);
}
@@ -12167,7 +12191,7 @@ void ai_maybe_launch_cmeasure(object *objp, ai_info *aip)
}
// --------------------------------------------------------------------------
static void ai_preprocess_ignore_objnum(ai_info *aip)
void ai_preprocess_ignore_objnum(object * /*objp*/, ai_info *aip)
{
if (aip->ai_flags[AI::AI_Flags::Temporary_ignore])
{
@@ -13040,6 +13064,7 @@ void ai_execute_behavior(ai_info *aip)
case AIM_NONE:
break;
case AIM_BIGSHIP:
ai_big_ship(Pl_objp);
break;
case AIM_PATH: {
int path_num;
@@ -13416,7 +13441,7 @@ void ai_warp_out(object *objp)
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
// Return nearest one.
static int ai_find_shockwave_weapon(const object *objp)
int ai_find_shockwave_weapon(object *objp, ai_info * /*aip*/)
{
missile_obj *mo;
float nearest_dist = 999999.9f;
@@ -13482,7 +13507,7 @@ void ai_announce_ship_dying(object *dying_objp)
// Return object index of weapon that could produce a shockwave that should be known about to *objp.
// Return nearest one.
static int ai_find_shockwave_ship(object *objp)
int ai_find_shockwave_ship(object *objp, ai_info * /*aip*/)
{
ship_obj *so;
float nearest_dist = 999999.9f;
@@ -13525,7 +13550,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
// If we don't currently know of a weapon to avoid, try to find one.
// If we can't find one, then clear the bit so we don't keep coming here.
if (aip->shockwave_object == -1) {
int shockwave_weapon = ai_find_shockwave_weapon(objp);
int shockwave_weapon = ai_find_shockwave_weapon(objp, aip);
if (shockwave_weapon == -1) {
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_weapon);
return 0;
@@ -13614,7 +13639,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos)
}
} else if (aip->ai_flags[AI::AI_Flags::Avoid_shockwave_ship]) {
if (aip->shockwave_object == -1) {
int shockwave_ship = ai_find_shockwave_ship(objp);
int shockwave_ship = ai_find_shockwave_ship(objp, aip);
if (shockwave_ship == -1) {
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_ship);
return 0;
@@ -13844,7 +13869,7 @@ int maybe_big_ship_collide_recover_frame(object *objp, ai_info *aip)
vec3d v2g;
if (aip->ai_flags[AI::AI_Flags::Big_ship_collide_recover_1]) {
ai_turn_towards_vector(&aip->big_recover_pos_1, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, nullptr);
ai_turn_towards_vector(&aip->big_recover_pos_1, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, NULL);
dist = vm_vec_normalized_dir(&v2g, &aip->big_recover_pos_1, &objp->pos);
dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
accelerate_ship(aip, dot);
@@ -13858,7 +13883,7 @@ int maybe_big_ship_collide_recover_frame(object *objp, ai_info *aip)
return 1;
} else if (aip->ai_flags[AI::AI_Flags::Big_ship_collide_recover_2]) {
ai_turn_towards_vector(&aip->big_recover_pos_2, objp, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, nullptr, nullptr, 0.0f, 0, nullptr);
ai_turn_towards_vector(&aip->big_recover_pos_2, objp, flFrametime, Ship_info[Ships[objp->instance].ship_info_index].srotation_time, NULL, NULL, 0.0f, 0, NULL);
dist = vm_vec_normalized_dir(&v2g, &aip->big_recover_pos_2, &objp->pos);
dot = vm_vec_dot(&objp->orient.vec.fvec, &v2g);
accelerate_ship(aip, dot);
@@ -13978,7 +14003,7 @@ void ai_frame(int objnum)
if (maybe_big_ship_collide_recover_frame(Pl_objp, aip))
return;
ai_preprocess_ignore_objnum(aip);
ai_preprocess_ignore_objnum(Pl_objp, aip);
target_objnum = set_target_objnum(aip, aip->target_objnum);
Assert(objnum != target_objnum);
@@ -14133,7 +14158,7 @@ void ai_frame(int objnum)
}
}
static void ai_control_info_check(ai_info *aip)
void ai_control_info_check( object * /*obj*/, ai_info *aip )
{
if(aip->ai_override_flags.none_set())
return;
@@ -14234,7 +14259,7 @@ void ai_process( object * obj, int ai_index, float frametime )
if (rfc == 1) {
// Wanderer - sexp based override goes here - only if rfc is valid though
ai_control_info_check(aip);
ai_control_info_check(obj, aip);
vec3d copy_desired_rotvel = obj->phys_info.rotvel;
physics_read_flying_controls( &obj->orient, &obj->phys_info, &AI_ci, frametime);
// if obj is in formation and not flight leader, don't update rotvel
@@ -14769,10 +14794,10 @@ int firing_aspect_seeking_bomb(object *objp)
return 0;
}
// *objp collided with big ship *big_objp at some global point.
// Make it fly away from the collision point.
// *objp collided with big ship *big_objp at global point *collide_pos
// Make it fly away from the collision point.
// collision_normal is NULL, when a collision is imminent and we just want to bug out.
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d *collision_normal)
void big_ship_collide_recover_start(object *objp, object *big_objp, vec3d * /*collide_pos*/, vec3d *collision_normal)
{
ai_info *aip;
@@ -14861,9 +14886,9 @@ void ai_update_lethality(object *pship_obj, object *other_obj, float damage)
/**
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp
* Object *objp_ship was hit by either weapon *objp_weapon or collided into by ship hit_objp at point *hitpos.
*/
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hitpos, int /*shield_quadrant*/, vec3d *hit_normal)
{
int hitter_objnum = -2;
object *objp_hitter = NULL;
@@ -14905,7 +14930,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
// And the current object is _not_ a big ship
if (!Ship_info[Ships[objp_ship->instance].ship_info_index].is_big_or_huge()) {
// Recover from hitting a big ship. Note, if two big ships collide, they just pound away at each other. Oh well. Recovery looks dumb and it's very late.
big_ship_collide_recover_start(objp_ship, hit_objp, hit_normal);
big_ship_collide_recover_start(objp_ship, hit_objp, hitpos, hit_normal);
}
}
}
@@ -15042,7 +15067,7 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
return;
if ( (hit_objp->type == OBJ_WEAPON) && !(aip->ai_flags[AI::AI_Flags::No_dynamic]) ) {
if ( ai_big_maybe_enter_strafe_mode(objp_ship, OBJ_INDEX(hit_objp)) )
if ( ai_big_maybe_enter_strafe_mode(objp_ship, OBJ_INDEX(hit_objp), 1) )
return;
}
break;
@@ -15162,7 +15187,10 @@ void ai_ship_hit(object *objp_ship, object *hit_objp, vec3d *hit_normal)
// Ship shipnum has been destroyed.
// Cleanup.
void ai_ship_destroy(int shipnum)
// the parameter 'method' is used to tell is this ship was destroyed or it departed normally.
// This function will get called in either case, and there are things that should be done if
// the ship actually gets destroyed which shouldn't get done if it departed.
void ai_ship_destroy(int shipnum, Ship::Exit_Flags /*method*/)
{
int objnum;
object *other_objp;
@@ -15413,7 +15441,7 @@ int ai_issue_rearm_request(object *requester_objp)
// we aren't able to do anything!
else {
Assert(result == 4);
UNREACHABLE("This case should have already been caught by the is_support_allowed precheck!");
Assertion(false, "This case should have already been caught by the is_support_allowed precheck!");
return -1;
}
}
@@ -15482,7 +15510,7 @@ int ai_return_path_num_from_dockbay(object *dockee_objp, int dockbay_index)
/**
* Actually go ahead and fire the synaptics.
*/
static void cheat_fire_synaptic(object *objp, ship *shipp)
void cheat_fire_synaptic(object *objp, ship *shipp, ai_info * /*aip*/)
{
ship_weapon *swp;
swp = &shipp->weapons;
@@ -15504,7 +15532,7 @@ static void cheat_fire_synaptic(object *objp, ship *shipp)
// if they're near one or more enemies
// every so often
// fire a synaptic if they have one.
void maybe_cheat_fire_synaptic(object *objp)
void maybe_cheat_fire_synaptic(object *objp, ai_info *aip)
{
// Only do in subspace missions.
if (!(The_mission.flags[Mission::Mission_Flags::Subspace]))
@@ -15536,7 +15564,7 @@ void maybe_cheat_fire_synaptic(object *objp)
int count = num_nearby_fighters(iff_get_attackee_mask(obj_team(objp)), &objp->pos, 1500.0f);
if (count > 0)
cheat_fire_synaptic(objp, shipp);
cheat_fire_synaptic(objp, shipp, aip);
}
}
}
+1 -1
View File
@@ -125,7 +125,7 @@ const char *Ai_goal_text(int goal)
case AI_GOAL_REARM_REPAIR:
return XSTR( "rearm ", 484);
case AI_GOAL_FLY_TO_SHIP:
return XSTR( "rendezvous with ", 1597);
return XSTR( "rendezvous with ", -1);
}
// Avoid compiler warning
+1 -1
View File
@@ -1387,7 +1387,7 @@ void asteroid_hit( object * pasteroid_obj, object * other_obj, vec3d * hitpos, f
weapon_info *wip;
wip = &Weapon_info[Weapons[other_obj->instance].weapon_info_index];
// If the weapon didn't play any impact animation, play custom asteroid impact animation
if (!wip->impact_weapon_expl_effect.isValid()) {
if ( wip->impact_weapon_expl_effect < 0 ) {
particle::create( hitpos, &vmd_zero_vector, 0.0f, Asteroid_impact_explosion_radius, particle::PARTICLE_BITMAP, Asteroid_impact_explosion_ani );
}
}
+23 -16
View File
@@ -591,7 +591,7 @@ int bm_create(int bpp, int w, int h, void *data, int flags) {
memset(entry, 0, sizeof(bitmap_entry));
sprintf_safe(entry->filename, "TMP%dx%d+%d", w, h, bpp);
sprintf(entry->filename, "TMP%dx%d+%d", w, h, bpp);
entry->type = BM_TYPE_USER;
entry->comp_type = BM_TYPE_NONE;
entry->palette_checksum = 0;
@@ -1155,7 +1155,7 @@ static int bm_load_info(BM_TYPE type, const char *filename, CFILE *img_cfp, int
}
}
else {
UNREACHABLE("Unknown file type specified! This is probably a coding error.");
Assertion(false, "Unknown file type specified! This is probably a coding error.");
return -1;
}
@@ -1253,7 +1253,7 @@ int bm_load(const char *real_filename) {
// Mark the slot as filled, because cf_read might load a new bitmap
// into this slot.
strcpy_s(entry->filename, filename);
strncpy(entry->filename, filename, MAX_FILENAME_LEN - 1);
entry->type = type;
entry->comp_type = c_type;
entry->signature = Bm_next_signature++;
@@ -1681,7 +1681,7 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
if (type == BM_TYPE_EFF) {
entry->info.ani.eff.type = eff_type;
sprintf_safe(entry->info.ani.eff.filename, "%s_%.4d", clean_name, i);
sprintf(entry->info.ani.eff.filename, "%s_%.4d", clean_name, i);
// bm_load_info() returns non-0 on failure
if (bm_load_info(eff_type, entry->info.ani.eff.filename,
@@ -1744,13 +1744,13 @@ int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *ke
entry->load_count++;
if (i == 0) {
sprintf_safe(entry->filename, "%s", filename);
sprintf(entry->filename, "%s", filename);
} else {
if (type == BM_TYPE_PNG) {
sprintf_safe(entry->filename, "%s_%04d", filename, i);
sprintf(entry->filename, "%s_%04d", filename, i);
}
else {
sprintf_safe(entry->filename, "%s[%d]", filename, i);
sprintf(entry->filename, "%s[%d]", filename, i);
}
}
@@ -1876,19 +1876,24 @@ int bm_load_sub_fast(const char *real_filename, int *handle, int dir_type, bool
}
int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **ext_list, CFILE **img_cfp, int dir_type) {
auto res = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, false);
char full_path[MAX_PATH];
size_t size = 0, offset = 0;
int rval = -1;
const void* file_data = nullptr;
rval = cf_find_file_location_ext(real_filename, num_ext, ext_list, dir_type, sizeof(full_path) - 1, full_path, &size, &offset, 0, &file_data);
// could not be found, or is invalid for some reason
if (!res.found)
if ((rval < 0) || (rval >= num_ext))
return -1;
CFILE *test = cfopen_special(res.full_name.c_str(), "rb", res.size, res.offset, res.data_ptr, dir_type);
CFILE *test = cfopen_special(full_path, "rb", size, offset, file_data, dir_type);
if (test != NULL) {
if (img_cfp != NULL)
*img_cfp = test;
return res.extension_index;
return rval;
}
// umm, that's not good...
@@ -2380,7 +2385,7 @@ void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ubyte /*
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags) {
ubyte *data = NULL;
int byte_size;
int d_size, byte_size;
char filename[MAX_FILENAME_LEN];
auto be = &bs->entry;
@@ -2388,8 +2393,6 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
// Unload any existing data
bm_free_data(bs);
bpp = be->bm.true_bpp;
if (Is_standalone) {
Assert(bpp == 8);
} else {
@@ -2406,6 +2409,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
if (data) {
memset(data, 0, be->mem_taken);
d_size = byte_size;
} else {
return;
}
@@ -2425,7 +2429,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ubyte flags)
// this will populate filename[] whether it's EFF or not
EFF_FILENAME_CHECK;
tga_error = targa_read_bitmap(filename, data, nullptr, byte_size, be->dir_type);
tga_error = targa_read_bitmap(filename, data, NULL, d_size, be->dir_type);
if (tga_error != TARGA_ERROR_NONE) {
bm_free_data(bs);
@@ -2522,7 +2526,7 @@ int bm_make_render_target(int width, int height, int flags) {
entry->type = (flags & BMP_FLAG_RENDER_TARGET_STATIC) ? BM_TYPE_RENDER_TARGET_STATIC : BM_TYPE_RENDER_TARGET_DYNAMIC;
entry->signature = Bm_next_signature++;
sprintf_safe(entry->filename, "RT_%dx%d+%d", w, h, bpp);
sprintf(entry->filename, "RT_%dx%d+%d", w, h, bpp);
entry->bm.w = (short)w;
entry->bm.h = (short)h;
entry->bm.rowsize = (short)w;
@@ -2585,6 +2589,9 @@ void bm_page_in_start() {
for (auto& slot : block) {
auto& entry = slot.entry;
if (!Cmdline_cache_bitmaps && (entry.type != BM_TYPE_NONE)) {
bm_unload_fast(entry.handle);
}
entry.preloaded = 0;
entry.preload_count = 0;
#ifdef BMPMAN_NDEBUG
+87 -75
View File
@@ -33,64 +33,70 @@
#include "cfile/cfilesystem.h"
#include "osapi/osapi.h"
#include "parse/encrypt.h"
#include "cfilesystem.h"
#include <limits>
char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN] = "";
#ifdef SCP_UNIX
char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN] = "";
#endif
// During cfile_init, verify that Pathtypes[n].index == n for each item
// Each path must have a valid parent that can be tracable all the way back to the root
// Each path must have a valid parent that can be tracable all the way back to the root
// so that we can create directories when we need to.
//
// Please make sure extensions are all lower-case, or we'll break unix compatibility
//
// clang-format off
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
// What type this is Path Extensions Parent type
{ CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID },
// Root must be index 1!!
{ CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT },
{ CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT },
{ CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA },
{ CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA },
{ CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS },
{ CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA },
{ CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE },
{ CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA },
{ CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt .webm .png",CF_TYPE_DATA },
{ CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA },
{ CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA },
{ CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA },
{ CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA },
{ CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds", CF_TYPE_PLAYERS },
{ CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css", CF_TYPE_PLAYERS },
{ CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS },
{ CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA }, //clr=cached color
{ CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA },
{ CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA },
{ CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA },
{ CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA },
{ CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA },
{ CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA },
{ CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA },
{ CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA },
cf_pathtype Pathtypes[CF_MAX_PATH_TYPES] = {
// What type this is Path Extensions Parent
// type
{CF_TYPE_INVALID, NULL, NULL, CF_TYPE_INVALID},
// Root must be index 1!!
{CF_TYPE_ROOT, "", ".mve .ogg", CF_TYPE_ROOT},
{CF_TYPE_DATA, "data", ".cfg .txt", CF_TYPE_ROOT},
{CF_TYPE_MAPS, "data" DIR_SEPARATOR_STR "maps", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_TEXT, "data" DIR_SEPARATOR_STR "text", ".txt .net", CF_TYPE_DATA},
{CF_TYPE_MODELS, "data" DIR_SEPARATOR_STR "models", ".pof", CF_TYPE_DATA},
{CF_TYPE_TABLES, "data" DIR_SEPARATOR_STR "tables", ".tbl .tbm", CF_TYPE_DATA},
{CF_TYPE_SOUNDS, "data" DIR_SEPARATOR_STR "sounds", ".wav .ogg", CF_TYPE_DATA},
{CF_TYPE_SOUNDS_8B22K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "8b22k", ".wav .ogg", CF_TYPE_SOUNDS},
{CF_TYPE_SOUNDS_16B11K, "data" DIR_SEPARATOR_STR "sounds" DIR_SEPARATOR_STR "16b11k", ".wav .ogg", CF_TYPE_SOUNDS},
{CF_TYPE_VOICE, "data" DIR_SEPARATOR_STR "voice", "", CF_TYPE_DATA},
{CF_TYPE_VOICE_BRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "briefing", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_CMD_BRIEF, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "command_briefings", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_DEBRIEFINGS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "debriefing", ".wav .ogg",
CF_TYPE_VOICE},
{CF_TYPE_VOICE_PERSONAS, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "personas", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_VOICE_SPECIAL, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "special", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_VOICE_TRAINING, "data" DIR_SEPARATOR_STR "voice" DIR_SEPARATOR_STR "training", ".wav .ogg", CF_TYPE_VOICE},
{CF_TYPE_MUSIC, "data" DIR_SEPARATOR_STR "music", ".wav .ogg", CF_TYPE_DATA},
{CF_TYPE_MOVIES, "data" DIR_SEPARATOR_STR "movies", ".mve .msb .ogg .mp4 .srt", CF_TYPE_DATA},
{CF_TYPE_INTERFACE, "data" DIR_SEPARATOR_STR "interface", ".pcx .ani .dds .tga .eff .png .jpg", CF_TYPE_DATA},
{CF_TYPE_FONT, "data" DIR_SEPARATOR_STR "fonts", ".vf .ttf", CF_TYPE_DATA},
{CF_TYPE_EFFECTS, "data" DIR_SEPARATOR_STR "effects", ".ani .eff .pcx .neb .tga .jpg .png .dds .sdr", CF_TYPE_DATA},
{CF_TYPE_HUD, "data" DIR_SEPARATOR_STR "hud", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_PLAYERS, "data" DIR_SEPARATOR_STR "players", ".hcf", CF_TYPE_DATA},
{CF_TYPE_PLAYER_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "images", ".pcx .png .dds",
CF_TYPE_PLAYERS},
{CF_TYPE_SQUAD_IMAGES, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "squads", ".pcx .png .dds",
CF_TYPE_PLAYERS},
{CF_TYPE_SINGLE_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "single", ".pl2 .cs2 .plr .csg .css",
CF_TYPE_PLAYERS},
{CF_TYPE_MULTI_PLAYERS, "data" DIR_SEPARATOR_STR "players" DIR_SEPARATOR_STR "multi", ".plr", CF_TYPE_PLAYERS},
{CF_TYPE_CACHE, "data" DIR_SEPARATOR_STR "cache", ".clr .tmp .bx", CF_TYPE_DATA}, // clr=cached color
{CF_TYPE_MULTI_CACHE, "data" DIR_SEPARATOR_STR "multidata", ".pcx .png .dds .fs2 .txt", CF_TYPE_DATA},
{CF_TYPE_MISSIONS, "data" DIR_SEPARATOR_STR "missions", ".fs2 .fc2 .ntl .ssv", CF_TYPE_DATA},
{CF_TYPE_CONFIG, "data" DIR_SEPARATOR_STR "config", ".cfg .tbl .tbm .xml .csv", CF_TYPE_DATA},
{CF_TYPE_DEMOS, "data" DIR_SEPARATOR_STR "demos", ".fsd", CF_TYPE_DATA},
{CF_TYPE_CBANIMS, "data" DIR_SEPARATOR_STR "cbanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_INTEL_ANIMS, "data" DIR_SEPARATOR_STR "intelanims", ".pcx .ani .eff .tga .jpg .png .dds", CF_TYPE_DATA},
{CF_TYPE_SCRIPTS, "data" DIR_SEPARATOR_STR "scripts", ".lua .lc", CF_TYPE_DATA},
{CF_TYPE_FICTION, "data" DIR_SEPARATOR_STR "fiction", ".txt", CF_TYPE_DATA},
{CF_TYPE_FREDDOCS, "data" DIR_SEPARATOR_STR "freddocs", ".html", CF_TYPE_DATA},
};
// clang-format on
#define CFILE_STACK_MAX 8
@@ -224,8 +230,14 @@ int cfile_init(const char *exe_dir, const char *cdrom_dir)
cfile_chdir(buf);
// set root directory
strcpy_s(Cfile_root_dir, buf);
strcpy_s(Cfile_user_dir, os_get_config_path().c_str());
strncpy(Cfile_root_dir, buf, CFILE_ROOT_DIRECTORY_LEN-1);
strncpy(Cfile_user_dir, os_get_config_path().c_str(), CFILE_ROOT_DIRECTORY_LEN-1);
#ifdef SCP_UNIX
// Initialize path of old pilot files
extern const char* Osreg_user_dir_legacy;
snprintf(Cfile_user_dir_legacy, CFILE_ROOT_DIRECTORY_LEN-1, "%s/%s/", getenv("HOME"), Osreg_user_dir_legacy);
#endif
for (i = 0; i < MAX_CFILE_BLOCKS; i++) {
Cfile_block_list[i].type = CFILE_BLOCK_UNUSED;
@@ -350,7 +362,8 @@ int cfile_push_chdir(int type)
return -1;
}
strcpy_s(Cfile_stack[Cfile_stack_pos++], OriginalDirectory);
strncpy(Cfile_stack[Cfile_stack_pos++], OriginalDirectory,
CFILE_ROOT_DIRECTORY_LEN - 1);
cf_create_default_path_string(dir, sizeof(dir) - 1, type, NULL);
@@ -473,17 +486,17 @@ char *cf_add_ext(const char *filename, const char *ext)
*
* @param filename Name of file to delete
* @param path_type Path type (CF_TYPE_xxx)
* @param location_flags Where to search for the location of the file to delete
*
* @return 0 on failure, 1 on success
*/
int cf_delete(const char *filename, int path_type, uint32_t location_flags)
int cf_delete(const char *filename, int path_type)
{
char longname[MAX_PATH_LEN];
Assert(CF_TYPE_SPECIFIED(path_type));
cf_create_default_path_string(longname, sizeof(longname) - 1, path_type, filename, false, location_flags);
cf_create_default_path_string(longname, sizeof(longname) - 1,
path_type, filename);
return (_unlink(longname) != -1);
}
@@ -509,12 +522,12 @@ int cf_access(const char *filename, int dir_type, int mode)
// If offset equates to boolean true, it was found in a VP and the logic will negate the function return
int cf_exists(const char *filename, int dir_type)
{
size_t offset = 1;
if ( (filename == NULL) || !strlen(filename) )
return 0;
auto find_res = cf_find_file_location(filename, dir_type);
return find_res.found && !find_res.offset;
return (cf_find_file_location(filename, dir_type, 0, NULL, NULL, &offset) && !offset);
}
// Goober5000
@@ -525,7 +538,7 @@ int cf_exists_full(const char *filename, int dir_type)
if ( (filename == NULL) || !strlen(filename) )
return 0;
return cf_find_file_location(filename, dir_type).found;
return cf_find_file_location(filename, dir_type, 0, NULL, NULL, NULL);
}
// same as the above, but with extension check
@@ -537,7 +550,7 @@ int cf_exists_full_ext(const char *filename, int dir_type, const int num_ext, co
if ( (num_ext <= 0) || (ext_list == NULL) )
return 0;
return cf_find_file_location_ext(filename, num_ext, ext_list, dir_type).found;
return (cf_find_file_location_ext(filename, num_ext, ext_list, dir_type, 0, NULL, NULL, NULL) != -1);
}
#ifdef _WIN32
@@ -611,7 +624,7 @@ static void mkdir_recursive(const char *path) {
// Creates the directory path if it doesn't exist. Even creates all its
// parent paths.
void cf_create_directory(int dir_type, uint32_t location_flags)
void cf_create_directory( int dir_type )
{
int num_dirs = 0;
int dir_tree[CF_MAX_PATH_TYPES];
@@ -633,7 +646,7 @@ void cf_create_directory(int dir_type, uint32_t location_flags)
int i;
for (i=num_dirs-1; i>=0; i-- ) {
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_tree[i], nullptr, false, location_flags);
cf_create_default_path_string( longname, sizeof(longname)-1, dir_tree[i], NULL );
if (stat(longname, &statbuf) != 0) {
mprintf(( "CFILE: Creating new directory '%s'\n", longname ));
mkdir_recursive(longname);
@@ -660,13 +673,14 @@ extern int game_cd_changed();
// error ==> NULL
//
CFILE* _cfopen(const char* source, int line, const char* file_path, const char* mode, int type, int dir_type,
bool localize, uint32_t location_flags)
CFILE *_cfopen(const char* source, int line, const char *file_path, const char *mode, int type, int dir_type, bool localize)
{
/* Bobboau, what is this doing here? 31 is way too short... - Goober5000
if( strlen(file_path) > 31 )
Error(LOCATION, "file name %s too long, \nmust be less than 31 charicters", file_path);*/
char longname[_MAX_PATH];
if ( !cfile_inited ) {
Int3();
return NULL;
@@ -688,8 +702,6 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
// the harddisk. No fancy packfile stuff here!
if ( strchr(mode,'w') || strchr(mode,'+') || strchr(mode,'a') ) {
char longname[_MAX_PATH];
// For write-only files, require a full path or a path type
#ifdef SCP_UNIX
if ( strpbrk(file_path, "/") ) {
@@ -703,9 +715,9 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
Assert( dir_type != CF_TYPE_ANY );
// Create the directory if necessary
cf_create_directory(dir_type, location_flags);
cf_create_directory( dir_type );
cf_create_default_path_string(longname, sizeof(longname) - 1, dir_type, file_path, false, location_flags);
cf_create_default_path_string( longname, sizeof(longname)-1, dir_type, file_path );
}
Assert( !(type & CFILE_MEMORY_MAPPED) );
@@ -755,29 +767,30 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
//================================================
// Search for file on disk, on cdrom, or in a packfile
size_t offset, size;
char copy_file_path[MAX_PATH_LEN]; // FIX change in memory from cf_find_file_location
strcpy_s(copy_file_path, file_path);
auto find_res = cf_find_file_location( copy_file_path, dir_type, localize, location_flags );
if ( find_res.found ) {
const void* file_data = nullptr;
if ( cf_find_file_location( copy_file_path, dir_type, sizeof(longname) - 1, longname, &size, &offset, localize, &file_data ) ) {
// Fount it, now create a cfile out of it
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, find_res.full_name.c_str()));
nprintf(("CFileDebug", "Requested file %s found at: %s\n", file_path, longname));
if ( type & CFILE_MEMORY_MAPPED ) {
// Can't open memory mapped files out of pack or memory files
if ( find_res.offset == 0 && find_res.data_ptr != nullptr ) {
if ( offset == 0 && file_data != nullptr ) {
#if defined _WIN32
HANDLE hFile;
hFile = CreateFile(find_res.full_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
hFile = CreateFile(longname, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
return cf_open_mapped_fill_cfblock(source, line, hFile, dir_type);
}
#elif defined SCP_UNIX
FILE* fp = fopen(find_res.full_name.c_str(), "rb");
FILE *fp = fopen( longname, "rb" );
if (fp) {
return cf_open_mapped_fill_cfblock(source, line, fp, dir_type);
}
@@ -786,8 +799,7 @@ CFILE* _cfopen(const char* source, int line, const char* file_path, const char*
} else {
// since cfopen_special already has all the code to handle the opening we can just use that here
return _cfopen_special(source, line, find_res.full_name.c_str(), mode, find_res.size, find_res.offset,
find_res.data_ptr, dir_type);
return _cfopen_special(source, line, longname, mode, size, offset, file_data, dir_type);
}
}
@@ -895,7 +907,7 @@ static int cfget_cfile_block()
mprintf(("Out of cfile blocks! Currently opened files:\n"));
dump_opened_files();
UNREACHABLE("There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
Assertion(false, "There are no more free cfile blocks. This means that there are too many files opened by FSO.\n"
"This is probably caused by a programming or scripting error where a file does not get closed."); // out of free cfile blocks
return -1;
}
+13 -92
View File
@@ -95,64 +95,6 @@ typedef struct {
#define CF_SORT_TIME 2
#define CF_SORT_REVERSE 3
/**
* @brief Contains a collection of flags for specifying from where a CFILE should be opened
*
* There are two types of flags. CF_LOCATION_GAME_ROOT and CF_LOCATION_USER_ROOT specify in which basic root directory
* CFile should search for files.
*
* The remaining flags control what type of location may be used for the operation. It's possible to restrict the
* location to the primary mod, the remaining mods or the top-level root directory.
*/
enum CFileLocationFlags {
CF_LOCATION_ROOT_GAME = 1 << 0, //!< The game root location. This is the location of the game data (e.g. FS2 retail)
/**
* @brief The user directories.
*
* If the engine is in portable mode then using this flag exclusively will result in a failure to open files!
*/
CF_LOCATION_ROOT_USER = 1 << 1,
/**
* @brief The memory root
*
* This contains all the built-in files available to the engine.
*/
CF_LOCATION_ROOT_MEMORY = 1 << 2,
/**
* @brief Mask for extracting root type from a location bit field
*/
CF_LOCATION_ROOT_MASK = 0xFFFF,
CF_LOCATION_TYPE_ROOT = 1 << 16, //!< The basic, top-level root location
/**
* @brief The primary mod location.
*
* This is the mod that appears first on the command line. If there are no mods then the root location is considered
* to be the primary mod
*/
CF_LOCATION_TYPE_PRIMARY_MOD = 1 << 17,
/**
* @brief The remaining mods.
*
* If there are no mods on the command line then this might not include any valid location.
*/
CF_LOCATION_TYPE_SECONDARY_MODS = 1 << 18,
/**
* @brief Bitmask for extracting the type from a location bit field
*/
CF_LOCATION_TYPE_MASK = 0xFFFF0000,
/**
* @brief A combination of all flags
*
* This should be used when the default behavior without any location filtering is desired.
*/
CF_LOCATION_ALL = CF_LOCATION_ROOT_MASK | CF_LOCATION_TYPE_MASK
};
#define cfread_fix(file) (fix)cfread_int(file)
#define cfwrite_fix(i,file) cfwrite_int(i,file)
@@ -169,6 +111,9 @@ extern const char *Get_file_list_child;
#define CFILE_ROOT_DIRECTORY_LEN 256
extern char Cfile_root_dir[CFILE_ROOT_DIRECTORY_LEN];
extern char Cfile_user_dir[CFILE_ROOT_DIRECTORY_LEN];
#ifdef SCP_UNIX
extern char Cfile_user_dir_legacy[CFILE_ROOT_DIRECTORY_LEN];
#endif
//================= LOW-LEVEL FUNCTIONS ==================
int cfile_init(const char *exe_dir, const char *cdrom_dir=NULL);
@@ -185,10 +130,11 @@ char *cf_add_ext(const char *filename, const char *ext);
// return CF_TYPE (directory location type) of a CFILE you called cfopen() successfully on.
int cf_get_dir_type(CFILE *cfile);
// Opens the file. If no path is given, use the extension to look into the
// default path. If mode is NULL, delete the file.
CFILE* _cfopen(const char* source_file, int line, const char* filename, const char* mode, int type = CFILE_NORMAL,
int dir_type = CF_TYPE_ANY, bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
// default path. If mode is NULL, delete the file.
CFILE *_cfopen(const char* source_file, int line, const char *filename, const char *mode,
int type = CFILE_NORMAL, int dir_type = CF_TYPE_ANY, bool localize = false);
#define cfopen(...) _cfopen(LOCATION, __VA_ARGS__) // Pass source location to the function
// like cfopen(), but it accepts a fully qualified path only (ie, the result of a cf_find_file_location() call)
@@ -210,7 +156,7 @@ void cf_set_version( CFILE * cfile, int version );
void cf_set_max_read_len(CFILE *cfile, size_t len);
// Deletes a file. Returns 0 on error, 1 if successful
int cf_delete(const char *filename, int dir_type, uint32_t location_flags = CF_LOCATION_ALL);
int cf_delete(const char *filename, int dir_type);
// Same as _access function to read a file's access bits
int cf_access(const char *filename, int dir_type, int mode);
@@ -365,26 +311,12 @@ int cfwrite_string(const char *buf, CFILE *file);
*/
int cfwrite_string_len(const char *buf, CFILE *file);
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort = CF_SORT_NONE,
SCP_vector<file_list_info>* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list(int max, char** list, int type, const char* filter, int sort = CF_SORT_NONE,
file_list_info* info = nullptr, uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int type, const char* filter,
int sort = CF_SORT_NONE, file_list_info* info = nullptr,
uint32_t location_flags = CF_LOCATION_ALL);
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort = CF_SORT_NONE, SCP_vector<file_list_info> *info = NULL );
int cf_get_file_list( int max, char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int type, const char *filter, int sort = CF_SORT_NONE, file_list_info *info = NULL );
void cf_sort_filenames( int n, char **list, int sort, file_list_info *info = NULL );
void cf_sort_filenames( SCP_vector<SCP_string> &list, int sort, SCP_vector<file_list_info> *info = NULL );
struct CFileLocation {
bool found = false;
SCP_string full_name;
size_t size = 0;
size_t offset = 0;
const void* data_ptr = nullptr;
explicit CFileLocation(bool found_in = false) : found(found_in) {}
};
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files.
// Input: filespace - Filename & extension
@@ -394,17 +326,7 @@ struct CFileLocation {
// size - File size
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns 0.
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize = false,
uint32_t location_flags = CF_LOCATION_ALL);
struct CFileLocationExt : public CFileLocation {
int extension_index = -1;
explicit CFileLocationExt(int extension_index_in = -1)
: CFileLocation(extension_index_in >= 0), extension_index(extension_index_in)
{
}
};
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize = false, const void** data_out = nullptr);
// Searches for a file. Follows all rules and precedence and searches
// CD's and pack files. Searches all locations in order for first filename using ext filter list.
@@ -418,8 +340,7 @@ struct CFileLocationExt : public CFileLocation {
// offset - Offset into pack file. 0 if not a packfile.
// Returns: If not found returns -1, else returns offset into ext_list.
// (NOTE: This function is exponentially slow, so don't use it unless truely needed!!)
CFileLocationExt cf_find_file_location_ext(const char* filename, const int ext_num, const char** ext_list, int pathtype,
bool localize = false);
int cf_find_file_location_ext(const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out = 0, char *pack_filename = NULL, size_t *size = NULL, size_t *offset = NULL, bool localize = false, const void** data_out = nullptr);
// Functions to change directories
int cfile_chdir(const char *dir);
+209 -263
View File
@@ -48,6 +48,9 @@ enum CfileRootType {
CF_ROOTTYPE_MEMORY = 2,
};
// for a defined and specifically set location to get/send pilot/campaign files
SCP_string Pilot_file_path;
// Created by:
// specifying hard drive tree
// searching for pack files on hard drive // Found by searching all known paths
@@ -56,7 +59,6 @@ enum CfileRootType {
typedef struct cf_root {
char path[CF_MAX_PATHNAME_LENGTH]; // Contains something like c:\projects\freespace or c:\projects\freespace\freespace.vp
int roottype; // CF_ROOTTYPE_PATH = Path, CF_ROOTTYPE_PACK =Pack file, CF_ROOTTYPE_MEMORY=In memory
uint32_t location_flags;
} cf_root;
// convenient type for sorting (see cf_build_pack_list())
@@ -345,9 +347,9 @@ void cf_build_pack_list( cf_root *root )
std::sort(temp_roots_sort, temp_roots_sort + temp_root_count, cf_packfile_sort_func);
// now insert them all into the real root list properly
cf_root *new_root;
for (i = 0; i < temp_root_count; i++) {
auto new_root = cf_create_root();
new_root->location_flags = root->location_flags;
new_root = cf_create_root();
strcpy_s( new_root->path, root->path );
#ifndef NDEBUG
@@ -376,11 +378,10 @@ static char normalize_directory_separator(char in)
return in;
}
static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
static void cf_add_mod_roots(const char* rootDirectory)
{
if (Cmdline_mod)
{
bool primary = true;
for (const char* cur_pos=Cmdline_mod; strlen(cur_pos) != 0; cur_pos+= (strlen(cur_pos)+1))
{
SCP_stringstream ss;
@@ -404,16 +405,9 @@ static void cf_add_mod_roots(const char* rootDirectory, uint32_t basic_location)
cf_root* root = cf_create_root();
strncpy(root->path, rootPath.c_str(), CF_MAX_PATHNAME_LENGTH-1);
if (primary) {
root->location_flags = basic_location | CF_LOCATION_TYPE_PRIMARY_MOD;
} else {
root->location_flags = basic_location | CF_LOCATION_TYPE_SECONDARY_MODS;
}
root->roottype = CF_ROOTTYPE_PATH;
cf_build_pack_list(root);
primary = false;
}
}
}
@@ -431,16 +425,10 @@ void cf_build_root_list(const char *cdrom_dir)
#ifdef WIN32
// Nothing to do here, Windows uses the current directory as the base
#else
cf_add_mod_roots(os_get_legacy_user_dir(), CF_LOCATION_ROOT_USER);
cf_add_mod_roots(Cfile_user_dir_legacy);
root = cf_create_root();
strncpy(root->path, os_get_legacy_user_dir(), CF_MAX_PATHNAME_LENGTH - 1);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strncpy(root->path, Cfile_user_dir_legacy, CF_MAX_PATHNAME_LENGTH - 1);
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
@@ -448,6 +436,10 @@ void cf_build_root_list(const char *cdrom_dir)
}
root->roottype = CF_ROOTTYPE_PATH;
// If it wasn't set before, set the pilot path
if (Pilot_file_path.empty())
Pilot_file_path = root->path;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
#endif
@@ -457,19 +449,13 @@ void cf_build_root_list(const char *cdrom_dir)
{
// =========================================================================
// now look for mods under the users HOME directory to use before system ones
cf_add_mod_roots(Cfile_user_dir, CF_LOCATION_ROOT_USER);
cf_add_mod_roots(Cfile_user_dir);
// =========================================================================
// =========================================================================
// set users HOME directory as default for loading and saving files
root = cf_create_root();
strcpy_s(root->path, Cfile_user_dir);
root->location_flags |= CF_LOCATION_ROOT_USER | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strncpy(root->path, Cfile_user_dir, CF_MAX_PATHNAME_LENGTH - 1);
// do we already have a slash? as in the case of a root directory install
if ((strlen(root->path) < (CF_MAX_PATHNAME_LENGTH - 1)) && (root->path[strlen(root->path) - 1] != DIR_SEPARATOR_CHAR)) {
@@ -477,6 +463,10 @@ void cf_build_root_list(const char *cdrom_dir)
}
root->roottype = CF_ROOTTYPE_PATH;
// set the default player location to here
if (Pilot_file_path.empty())
Pilot_file_path = root->path;
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
// =========================================================================
@@ -487,17 +477,11 @@ void cf_build_root_list(const char *cdrom_dir)
if ( !_getcwd(working_directory, CF_MAX_PATHNAME_LENGTH ) ) {
Error(LOCATION, "Can't get current working directory -- %d", errno );
}
cf_add_mod_roots(working_directory, CF_LOCATION_ROOT_GAME);
cf_add_mod_roots(working_directory);
root = cf_create_root();
root->location_flags |= CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT;
if (Cmdline_mod == nullptr || strlen(Cmdline_mod) <= 0) {
// If there are no mods then the root is the primary mod
root->location_flags |= CF_LOCATION_TYPE_PRIMARY_MOD;
}
strcpy_s(root->path, working_directory);
size_t path_len = strlen(root->path);
@@ -509,6 +493,10 @@ void cf_build_root_list(const char *cdrom_dir)
root->roottype = CF_ROOTTYPE_PATH;
// If the path wasn't set before use the working directory
if ( Pilot_file_path.empty() )
Pilot_file_path = root->path;
//======================================================
// Next, check any VP files under the current directory.
cf_build_pack_list(root);
@@ -529,7 +517,6 @@ void cf_build_root_list(const char *cdrom_dir)
// The final root is the in-memory root
root = cf_create_root();
root->location_flags = CF_LOCATION_ROOT_MEMORY | CF_LOCATION_TYPE_ROOT;
memset(root->path, 0, sizeof(root->path));
root->roottype = CF_ROOTTYPE_MEMORY;
@@ -990,12 +977,15 @@ void cf_free_secondary_filelist()
*
* @param filespec Filename & extension
* @param pathtype See CF_TYPE_ defines in CFILE.H
* @param max_out Maximum string length that should be stuffed into pack_filename
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
* @param size OUTPUT: File size
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
* @param localize Undertake localization
* @param location_flags Specifies where to search for the specified flag
*
* @return A structure which describes the found file
* @return If not found returns 0.
*/
CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool localize, uint32_t location_flags)
int cf_find_file_location( const char *filespec, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out )
{
int i;
uint ui;
@@ -1003,6 +993,7 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
char longname[MAX_PATH_LEN];
Assert( (filespec != NULL) && (strlen(filespec) > 0) ); //-V805
Assert( (pack_filename == NULL) || (max_out > 1) );
// see if we have something other than just a filename
// our current rules say that any file that specifies a direct
@@ -1018,15 +1009,16 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
#endif
FILE *fp = fopen(filespec, "rb" );
if (fp) {
CFileLocation res(true);
res.size = static_cast<size_t>(filelength(fileno(fp)));
res.offset = 0;
res.full_name = filespec;
if ( size ) *size = filelength(fileno(fp));
if ( offset ) *offset = 0;
if ( pack_filename ) {
strncpy( pack_filename, filespec, max_out );
}
fclose(fp);
return res;
return 1;
}
return CFileLocation(); // If they give a full path, fail if not found.
return 0; // If they give a full path, fail if not found.
}
// Search the hard drive for files first.
@@ -1065,39 +1057,43 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
}
if (cfs_slow_search) {
cf_create_default_path_string(longname, sizeof(longname) - 1, search_order[ui], filespec, localize,
location_flags);
cf_create_default_path_string( longname, sizeof(longname)-1, search_order[ui], filespec, localize );
#if defined _WIN32
_finddata_t findstruct;
intptr_t findhandle = _findfirst(longname, &findstruct);
if (findhandle != -1) {
CFileLocation res;
res.found = true;
res.size = static_cast<size_t>(findstruct.size);
if (size)
*size = findstruct.size;
_findclose(findhandle);
res.offset = 0;
res.full_name = longname;
if (offset)
*offset = 0;
return res;
if (pack_filename)
strncpy( pack_filename, longname, max_out );
return 1;
}
#endif
{
FILE *fp = fopen(longname, "rb" );
if (fp) {
CFileLocation res(true);
res.size = static_cast<size_t>(filelength( fileno(fp) ));
if (size)
*size = filelength( fileno(fp) );
fclose(fp);
res.offset = 0;
res.full_name = longname;
if (offset)
*offset = 0;
return res;
if (pack_filename)
strncpy(pack_filename, longname, max_out);
return 1;
}
}
}
@@ -1111,15 +1107,6 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
if ( (pathtype != CF_TYPE_ANY) && (pathtype != f->pathtype_index) )
continue;
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if (localize) {
// create localized filespec
@@ -1127,58 +1114,70 @@ CFileLocation cf_find_file_location(const char* filespec, int pathtype, bool loc
if ( lcl_add_dir_to_path_with_filename(longname, MAX_PATH_LEN - 1) ) {
if ( !stricmp(longname, f->name_ext) ) {
CFileLocation res(true);
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (size)
*size = f->size;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (offset)
*offset = (size_t)f->pack_offset;
res.full_name = r->path;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
}
}
return res;
return 1;
}
}
}
// file either not localized or localized version not found
if ( !stricmp(filespec, f->name_ext) ) {
CFileLocation res(true);
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (size)
*size = f->size;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (offset)
*offset = (size_t)f->pack_offset;
res.full_name = r->path;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy( pack_filename, f->real_name, max_out );
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy( pack_filename, r->path, max_out );
}
}
return res;
return 1;
}
}
return CFileLocation();
return 0;
}
// -- from parselo.cpp --
@@ -1195,11 +1194,14 @@ extern char *stristr(char *str, const char *substr);
* @param ext_list Extension filter list
* @param pathtype See CF_TYPE_ defines in CFILE.H
* @param max_out Maximum string length that should be stuffed into pack_filename
* @param pack_filename OUTPUT: Absolute path and filename of this file. Could be a packfile or the actual file.
* @param size OUTPUT: File size
* @param offset OUTPUT: Offset into pack file. 0 if not a packfile.
* @param localize Undertake localization
*
* @return A structure containing information about the found file
* @return If not found returns -1, else returns offset into ext_list.
*/
CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, bool localize)
int cf_find_file_location_ext( const char *filename, const int ext_num, const char **ext_list, int pathtype, int max_out, char *pack_filename, size_t *size, size_t *offset, bool localize, const void** data_out)
{
int cur_ext, i;
uint ui;
@@ -1211,6 +1213,7 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
Assert( (filename != NULL) && (strlen(filename) < MAX_FILENAME_LEN) );
Assert( (ext_list != NULL) && (ext_num > 1) ); // if we are searching for just one ext
// then this is the wrong function to use
Assert( (pack_filename == NULL) || (max_out > 1) );
// if we have a full path already then fail. this function if for searching via filter only!
@@ -1220,7 +1223,7 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
if ( strpbrk(filename,"/\\:") ) { // do we have a full path already?
#endif
Int3();
return CFileLocationExt();
return 0;
}
// Search the hard drive for files first.
@@ -1278,35 +1281,44 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
#if defined _WIN32
_finddata_t findstruct;
intptr_t findhandle = _findfirst(longname, &findstruct);
if (findhandle != -1) {
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(findstruct.size);
if (size)
*size = findstruct.size;
if (data_out)
*data_out = nullptr;
_findclose(findhandle);
res.offset = 0;
res.full_name = longname;
if (offset)
*offset = 0;
return res;
if (pack_filename)
strncpy( pack_filename, longname, max_out );
return cur_ext;
}
#endif
{
FILE *fp = fopen(longname, "rb" );
if (fp) {
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(filelength( fileno(fp) ));
if (size)
*size = filelength( fileno(fp) );
if (data_out)
*data_out = nullptr;
fclose(fp);
res.offset = 0;
res.full_name = longname;
if (offset)
*offset = 0;
return res;
if (pack_filename)
strncpy(pack_filename, longname, max_out);
return cur_ext;
}
}
}
@@ -1391,62 +1403,76 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
if ( lcl_add_dir_to_path_with_filename(longname, MAX_PATH_LEN - 1) ) {
if ( !stricmp(longname, f->name_ext) ) {
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (size)
*size = f->size;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (offset)
*offset = f->pack_offset;
res.full_name = r->path;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
}
else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy(pack_filename, f->real_name, max_out);
}
else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy(pack_filename, r->path, max_out);
}
}
// found it, so cleanup and return
file_list_index.clear();
return res;
return cur_ext;
}
}
}
// file either not localized or localized version not found
if ( !stricmp(filespec, f->name_ext) ) {
CFileLocationExt res(cur_ext);
res.found = true;
res.size = static_cast<size_t>(f->size);
res.offset = (size_t)f->pack_offset;
res.data_ptr = f->data;
if (size)
*size = f->size;
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
res.full_name = Pathtypes[f->pathtype_index].path;
res.full_name += DIR_SEPARATOR_STR;
res.full_name += f->name_ext;
} else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
res.full_name = f->real_name;
} else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
if (offset)
*offset = f->pack_offset;
res.full_name = r->path;
if (data_out)
*data_out = f->data;
if (pack_filename) {
if (f->data != nullptr) {
// This is an in-memory file so we just copy the pathtype name + file name
strncpy(pack_filename, Pathtypes[f->pathtype_index].path, max_out);
strncat(pack_filename, DIR_SEPARATOR_STR, max_out);
strncat(pack_filename, f->name_ext, max_out);
}
else if (f->pack_offset < 1) {
// This is a real file, return the actual file path
strncpy(pack_filename, f->real_name, max_out);
}
else {
// File is in a pack file
cf_root *r = cf_get_root(f->root_index);
strncpy(pack_filename, r->path, max_out);
}
}
// found it, so cleanup and return
file_list_index.clear();
return res;
return cur_ext;
}
// ok, we're still here, so strip off the extension again in order to
@@ -1457,7 +1483,7 @@ CFileLocationExt cf_find_file_location_ext( const char *filename, const int ext_
}
}
return CFileLocationExt();
return -1;
}
@@ -1556,8 +1582,7 @@ static int cf_file_already_in_list( SCP_vector<SCP_string> &list, const char *fi
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
// location, 'filter' only needs to be the filter itself, with no path information.
// See above descriptions of cf_get_file_list() for more information about how it all works.
int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* filter, int sort,
SCP_vector<file_list_info>* info, uint32_t location_flags)
int cf_get_file_list( SCP_vector<SCP_string> &list, int pathtype, const char *filter, int sort, SCP_vector<file_list_info> *info )
{
char *ptr;
uint i;
@@ -1585,8 +1610,7 @@ int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* fil
}
#if defined _WIN32
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, (char*)Get_file_list_child, false,
location_flags);
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, (char*)Get_file_list_child );
strcat_s(filespec, DIR_SEPARATOR_STR);
strcat_s(filespec, filter);
@@ -1626,8 +1650,7 @@ int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* fil
}
#elif defined SCP_UNIX
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, (char*)Get_file_list_child, false,
location_flags);
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, (char*)Get_file_list_child );
DIR *dirp;
struct dirent *dir;
@@ -1695,16 +1718,6 @@ int cf_get_file_list(SCP_vector<SCP_string>& list, int pathtype, const char* fil
continue;
}
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if ( !cf_matches_spec( filter,f->name_ext)) {
continue;
}
@@ -1782,8 +1795,7 @@ int cf_file_already_in_list( int num_files, char **list, const char *filename )
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
// location, 'filter' only needs to be the filter itself, with no path information.
// See above descriptions of cf_get_file_list() for more information about how it all works.
int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int sort, file_list_info* info,
uint32_t location_flags)
int cf_get_file_list( int max, char **list, int pathtype, const char *filter, int sort, file_list_info *info )
{
char *ptr;
uint i;
@@ -1806,7 +1818,7 @@ int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int
char filespec[MAX_PATH_LEN];
#if defined _WIN32
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, filter, false, location_flags);
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, filter );
_finddata_t find;
intptr_t find_handle;
@@ -1847,7 +1859,7 @@ int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int
}
#elif defined SCP_UNIX
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, nullptr, false, location_flags);
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, NULL );
DIR *dirp;
struct dirent *dir;
@@ -1920,16 +1932,6 @@ int cf_get_file_list(int max, char** list, int pathtype, const char* filter, int
continue;
}
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if (num_files >= max)
break;
@@ -2013,8 +2015,7 @@ int cf_file_already_in_list_preallocated( int num_files, char arr[][MAX_FILENAME
// This one has a 'type', which is a CF_TYPE_* value. Because this specifies the directory
// location, 'filter' only needs to be the filter itself, with no path information.
// See above descriptions of cf_get_file_list() for more information about how it all works.
int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char** list, int pathtype, const char* filter,
int sort, file_list_info* info, uint32_t location_flags)
int cf_get_file_list_preallocated( int max, char arr[][MAX_FILENAME_LEN], char **list, int pathtype, const char *filter, int sort, file_list_info *info )
{
int num_files = 0, own_flag = 0;
@@ -2043,7 +2044,7 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
// Search the default directories
#if defined _WIN32
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, filter, false, location_flags);
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, filter );
intptr_t find_handle;
_finddata_t find;
@@ -2084,7 +2085,7 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
}
#elif defined SCP_UNIX
cf_create_default_path_string(filespec, sizeof(filespec) - 1, pathtype, nullptr, false, location_flags);
cf_create_default_path_string( filespec, sizeof(filespec)-1, pathtype, NULL );
DIR *dirp;
struct dirent *dir;
@@ -2120,7 +2121,7 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
if ( !Get_file_list_filter || (*Get_file_list_filter)(dir->d_name) ) {
strcpy_s(arr[num_files], dir->d_name );
strncpy(arr[num_files], dir->d_name, MAX_FILENAME_LEN - 1 );
char *ptr = strrchr(arr[num_files], '.');
if ( ptr ) {
*ptr = 0;
@@ -2155,16 +2156,6 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
continue;
}
if (location_flags != CF_LOCATION_ALL) {
// If a location flag was specified we need to check if the root of this file satisfies the request
auto root = cf_get_root(f->root_index);
if (!cf_check_location_flags(root->location_flags, location_flags)) {
// Root does not satisfy location flags
continue;
}
}
if (num_files >= max)
break;
@@ -2231,8 +2222,7 @@ int cf_get_file_list_preallocated(int max, char arr[][MAX_FILENAME_LEN], char**
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if the result would be too long (invalid result)
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename, bool localize,
uint32_t location_flags)
int cf_create_default_path_string(char *path, uint path_max, int pathtype, const char *filename, bool localize )
{
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
@@ -2243,22 +2233,7 @@ int cf_create_default_path_string(char* path, uint path_max, int pathtype, const
strncpy( path, filename, path_max );
} else {
cf_root* root = nullptr;
for (auto i = 0; i < Num_roots; ++i) {
auto current_root = cf_get_root(i);
if (current_root->roottype != CF_ROOTTYPE_PATH) {
// We want a "real" path here so only path roots are valid
continue;
}
if (cf_check_location_flags(current_root->location_flags, location_flags)) {
// We found a valid root
root = current_root;
break;
}
}
cf_root *root = cf_get_root(0);
if (!root) {
Assert( filename != NULL );
@@ -2268,7 +2243,12 @@ int cf_create_default_path_string(char* path, uint path_max, int pathtype, const
Assert(CF_TYPE_SPECIFIED(pathtype));
strncpy(path, root->path, path_max);
// force a specific directory to search for player files
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
strncpy(path, Pilot_file_path.c_str(), path_max);
} else {
strncpy(path, root->path, path_max);
}
strcat_s(path, path_max, Pathtypes[pathtype].path);
@@ -2314,8 +2294,7 @@ int cf_create_default_path_string(char* path, uint path_max, int pathtype, const
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if the result would be too long (invalid result)
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename, bool /*localize*/,
uint32_t location_flags)
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename, bool /*localize*/ )
{
#ifdef SCP_UNIX
if ( filename && strpbrk(filename,"/") ) {
@@ -2326,22 +2305,7 @@ int cf_create_default_path_string(SCP_string& path, int pathtype, const char* fi
path.assign(filename);
} else {
cf_root* root = nullptr;
for (auto i = 0; i < Num_roots; ++i) {
auto current_root = cf_get_root(i);
if (current_root->roottype != CF_ROOTTYPE_PATH) {
// We want a "real" path here so only path roots are valid
continue;
}
if (cf_check_location_flags(current_root->location_flags, location_flags)) {
// We found a valid root
root = current_root;
break;
}
}
cf_root *root = cf_get_root(0);
if (!root) {
Assert( filename != NULL );
@@ -2352,7 +2316,12 @@ int cf_create_default_path_string(SCP_string& path, int pathtype, const char* fi
Assert(CF_TYPE_SPECIFIED(pathtype));
std::ostringstream s_path;
s_path << root->path;
// force a specific directory to search for player files
if ( (pathtype == CF_TYPE_PLAYERS) || (pathtype == CF_TYPE_SINGLE_PLAYERS) || (pathtype == CF_TYPE_MULTI_PLAYERS) ) {
s_path << Pilot_file_path;
} else {
s_path << root->path;
}
s_path << Pathtypes[pathtype].path;
@@ -2417,26 +2386,3 @@ void cfile_spew_pack_file_crcs()
fclose(out);
}
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags)
{
Assertion((check_flags & CF_LOCATION_ROOT_MASK) != 0, "check_flags must have a valid root value");
Assertion((check_flags & CF_LOCATION_TYPE_MASK) != 0, "check_flags must have a valid type value");
auto check_root = check_flags & CF_LOCATION_ROOT_MASK;
auto desired_root_flags = desired_flags & CF_LOCATION_ROOT_MASK;
// If the root part is not set then assume that every root matches
if (desired_root_flags != 0 && (check_root & desired_root_flags) == 0) {
return false;
}
auto check_type = check_flags & CF_LOCATION_TYPE_MASK;
auto desired_type_flags = desired_flags & CF_LOCATION_TYPE_MASK;
if (desired_type_flags != 0 && (check_type & desired_type_flags) == 0) {
return false;
}
return true;
}
+2 -6
View File
@@ -29,8 +29,6 @@ typedef struct cf_pathtype {
// During cfile_init, verify that Pathtypes[n].index == n for each item
extern cf_pathtype Pathtypes[CF_MAX_PATH_TYPES];
bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
// Returns the default storage path for files given a
// particular pathtype. In other words, the path to
// the unpacked, non-cd'd, stored on hard drive path.
@@ -41,9 +39,7 @@ bool cf_check_location_flags(uint32_t check_flags, uint32_t desired_flags);
// filename - optional, if set, tacks the filename onto end of path.
// Output: path - Fully qualified pathname.
//Returns 0 if result would be too long (invalid result)
int cf_create_default_path_string(char* path, uint path_max, int pathtype, const char* filename = nullptr,
bool localize = false, uint32_t location_flags = CF_LOCATION_ALL);
int cf_create_default_path_string(SCP_string& path, int pathtype, const char* filename = nullptr, bool localize = false,
uint32_t location_flags = CF_LOCATION_ALL);
int cf_create_default_path_string( char *path, uint path_max, int pathtype, const char *filename=NULL, bool localize = false);
int cf_create_default_path_string( SCP_string &path, int pathtype, const char *filename=NULL, bool localize = false );
#endif //_CFILESYSTEM_H
+7 -10
View File
@@ -173,6 +173,7 @@ Flag exe_params[] =
{ "-no_deferred", "Disable Deferred Lighting", true, EASY_DEFAULT_MEM, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_deferred"},
{ "-enable_shadows", "Enable Shadows", true, EASY_MEM_ALL_ON, EASY_DEFAULT, "Graphics", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_shadows"},
{ "-no_vsync", "Disable vertical sync", true, 0, EASY_DEFAULT, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-no_vsync", },
{ "-cache_bitmaps", "Cache bitmaps between missions", true, 0, EASY_DEFAULT_MEM, "Game Speed", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-cache_bitmaps", },
{ "-dualscanlines", "Add another pair of scanning lines", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-dualscanlines", },
{ "-targetinfo", "Enable info next to target", true, 0, EASY_DEFAULT, "HUD", "http://www.hard-light.net/wiki/index.php/Command-Line_Reference#-targetinfo", },
@@ -362,9 +363,11 @@ int Cmdline_no_deferred_lighting = 0;
int Cmdline_aniso_level = 0;
// Game Speed related
cmdline_parm cache_bitmaps_arg("-cache_bitmaps", NULL, AT_NONE); // Cmdline_cache_bitmaps
cmdline_parm no_fpscap("-no_fps_capping", "Don't limit frames-per-second", AT_NONE); // Cmdline_NoFPSCap
cmdline_parm no_vsync_arg("-no_vsync", NULL, AT_NONE); // Cmdline_no_vsync
int Cmdline_cache_bitmaps = 0; // caching of bitmaps between missions (faster loads, can hit swap on reload with <512 Meg RAM though) - taylor
int Cmdline_NoFPSCap = 0; // Disable FPS capping - kazan
int Cmdline_no_vsync = 0;
@@ -543,7 +546,6 @@ cmdline_parm deprecated_htl_arg("-nohtl", "Deprecated", AT_NONE);
cmdline_parm deprecated_brieflighting_arg("-brief_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_sndpreload_arg("-snd_preload", "Deprecated", AT_NONE);
cmdline_parm deprecated_missile_lighting_arg("-missile_lighting", "Deprecated", AT_NONE);
cmdline_parm deprecated_cache_bitmaps_arg("-cache_bitmaps", "Deprecated", AT_NONE);
int Cmdline_deprecated_spec = 0;
int Cmdline_deprecated_glow = 0;
@@ -554,7 +556,6 @@ int Cmdline_deprecated_jpgtga = 0;
int Cmdline_deprecated_nohtl = 0;
bool Cmdline_deprecated_brief_lighting = 0;
bool Cmdline_deprecated_missile_lighting = false;
bool Cmdline_deprecated_cache_bitmaps = false;
#ifndef NDEBUG
// NOTE: this assumes that os_init() has already been called but isn't a fatal error if it hasn't
@@ -625,10 +626,6 @@ void cmdline_debug_print_cmdline()
{
mprintf(("Deprecated flag '-missile_lighting' found. Please remove from your cmdline.\n"));
}
if (Cmdline_deprecated_cache_bitmaps) {
mprintf(("Deprecated flag '-cache_bitmaps' found. Please remove from your cmdline.\n"));
}
}
#endif
@@ -1968,6 +1965,10 @@ bool SetCmdlineParams()
Cmdline_ballistic_gauge = 1;
}
if ( cache_bitmaps_arg.found() ) {
Cmdline_cache_bitmaps = 1;
}
if(old_collision_system.found())
Cmdline_old_collision_sys = 1;
@@ -2158,10 +2159,6 @@ bool SetCmdlineParams()
Cmdline_deprecated_missile_lighting = true;
}
if (deprecated_cache_bitmaps_arg.found()) {
Cmdline_deprecated_cache_bitmaps = true;
}
return true;
}
+1
View File
@@ -82,6 +82,7 @@ extern int Cmdline_no_emissive;
extern int Cmdline_aniso_level;
// Game Speed related
extern int Cmdline_cache_bitmaps;
extern int Cmdline_NoFPSCap;
extern int Cmdline_no_vsync;
-6
View File
@@ -3,12 +3,6 @@
#include <memory>
namespace cutscene {
FrameSize::FrameSize(size_t in_width, size_t in_height, size_t in_stride)
: width(in_width), height(in_height), stride(in_stride)
{
}
FrameSize::FrameSize() = default;
Decoder::Decoder() : m_decoding(true) {
}
+11 -18
View File
@@ -10,26 +10,28 @@ struct FrameSize {
size_t width = 0;
size_t height = 0;
size_t stride = 0;
FrameSize(size_t width, size_t in_height, size_t in_stride);
FrameSize();
};
class VideoFrame {
protected:
VideoFrame() = default;
VideoFrame() {}
public:
virtual ~VideoFrame() = default;
public:
virtual ~VideoFrame() {}
double frameTime = -1.0;
int id = -1;
virtual size_t getPlaneNumber() = 0;
FrameSize ySize;
FrameSize uvSize;
virtual FrameSize getPlaneSize(size_t plane) = 0;
struct DataPointers {
ubyte* y;
ubyte* u;
ubyte* v;
};
virtual void* getPlaneData(size_t plane) = 0;
virtual DataPointers getDataPointers() = 0;
};
/**
@@ -41,19 +43,10 @@ using FramePtr = std::unique_ptr<T>;
typedef std::unique_ptr<VideoFrame> VideoFramePtr;
enum class FramePixelFormat {
Invalid,
YUV420,
BGR,
BGRA
};
struct MovieProperties {
FrameSize size;
float fps = -1.0f;
FramePixelFormat pixelFormat = FramePixelFormat::Invalid;
};
struct AudioFrame {
+24 -67
View File
@@ -14,85 +14,46 @@ struct movie_vertex {
namespace cutscene {
namespace player {
VideoPresenter::VideoPresenter(const MovieProperties& props) : _properties(props)
{
VideoPresenter::VideoPresenter(const MovieProperties& props) {
GR_DEBUG_SCOPE("Init video");
_planeTextureHandles.fill(-1);
auto w = static_cast<int>(props.size.width);
auto h = static_cast<int>(props.size.height);
switch (props.pixelFormat) {
case FramePixelFormat::YUV420:
_planeTextureBuffers[0].reset(new uint8_t[w * h]);
_planeTextureHandles[0] = bm_create(8, w, h, _planeTextureBuffers[0].get(), BMP_AABITMAP);
// Create buffer textures
_yTexBuffer.reset(new uint8_t[w * h]);
_ytex = bm_create(8, w, h, _yTexBuffer.get(), BMP_AABITMAP);
_planeTextureBuffers[1].reset(new uint8_t[w / 2 * h / 2]);
_planeTextureHandles[1] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[1].get(), BMP_AABITMAP);
_uTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_utex = bm_create(8, w / 2, h / 2, _uTexBuffer.get(), BMP_AABITMAP);
_planeTextureBuffers[2].reset(new uint8_t[w / 2 * h / 2]);
_planeTextureHandles[2] = bm_create(8, w / 2, h / 2, _planeTextureBuffers[2].get(), BMP_AABITMAP);
_vTexBuffer.reset(new uint8_t[w / 2 * h / 2]);
_vtex = bm_create(8, w / 2, h / 2, _vTexBuffer.get(), BMP_AABITMAP);
material_set_movie(&_movie_material, _planeTextureHandles[0], _planeTextureHandles[1], _planeTextureHandles[2]);
break;
case FramePixelFormat::BGR:
_planeTextureBuffers[0].reset(new uint8_t[w * h * 3]);
_planeTextureHandles[0] = bm_create(24, w, h, _planeTextureBuffers[0].get(), 0);
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, false, false);
break;
case FramePixelFormat::BGRA:
_planeTextureBuffers[0].reset(new uint8_t[w * h * 4]);
_planeTextureHandles[0] = bm_create(32, w, h, _planeTextureBuffers[0].get(), 0);
material_set_unlit(&_rgb_material, _planeTextureHandles[0], 1.0f, true, false);
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
material_set_movie(&_render_material, _ytex, _utex, _vtex);
}
VideoPresenter::~VideoPresenter() {
GR_DEBUG_SCOPE("Deinit video");
for (auto& handle : _planeTextureHandles) {
if (handle > 0) {
bm_release(handle);
handle = -1;
}
}
bm_release(_ytex);
bm_release(_utex);
bm_release(_vtex);
_ytex = _utex = _vtex = -1;
}
void VideoPresenter::uploadVideoFrame(const VideoFramePtr& frame) {
GR_DEBUG_SCOPE("Update video frame");
auto ptrs = frame->getDataPointers();
for (size_t i = 0; i < frame->getPlaneNumber(); ++i) {
auto size = frame->getPlaneSize(i);
auto data = frame->getPlaneData(i);
memcpy(_yTexBuffer.get(), ptrs.y, frame->ySize.stride * frame->ySize.height);
memcpy(_uTexBuffer.get(), ptrs.u, frame->uvSize.stride * frame->uvSize.height);
memcpy(_vTexBuffer.get(), ptrs.v, frame->uvSize.stride * frame->uvSize.height);
memcpy(_planeTextureBuffers[i].get(), data, size.stride * size.height);
int bpp = 0;
switch (_properties.pixelFormat) {
case FramePixelFormat::YUV420:
bpp = 8;
break;
case FramePixelFormat::BGR:
bpp = 24;
break;
case FramePixelFormat::BGRA:
bpp = 32;
break;
default:
UNREACHABLE("Unhandled enum value!");
break;
}
gr_update_texture(_planeTextureHandles[i], bpp, _planeTextureBuffers[i].get(), static_cast<int>(size.width),
static_cast<int>(size.height));
}
gr_update_texture(_ytex, 8, _yTexBuffer.get(), (int) frame->ySize.width, (int) frame->ySize.height);
gr_update_texture(_utex, 8, _uTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
gr_update_texture(_vtex, 8, _vTexBuffer.get(), (int) frame->uvSize.width, (int) frame->uvSize.height);
}
void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
@@ -124,14 +85,10 @@ void VideoPresenter::displayFrame(float x1, float y1, float x2, float y2) {
auto offset = gr_add_to_immediate_buffer(sizeof(vertex_data), vertex_data);
vertex_layout layout;
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offsetof(movie_vertex, uv));
layout.add_vertex_component(vertex_format_data::POSITION2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, pos));
layout.add_vertex_component(vertex_format_data::TEX_COORD2, sizeof(vertex_data[0]), offset + offsetof(movie_vertex, uv));
if (_properties.pixelFormat == FramePixelFormat::YUV420) {
gr_render_movie(&_movie_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle, offset);
} else {
gr_render_primitives(&_rgb_material, PRIM_TYPE_TRISTRIP, &layout, 0, 4, gr_immediate_buffer_handle, offset);
}
gr_render_movie(&_render_material, PRIM_TYPE_TRISTRIP, &layout, 4, gr_immediate_buffer_handle);
}
}
+8 -5
View File
@@ -12,13 +12,16 @@ namespace cutscene {
namespace player {
class VideoPresenter {
MovieProperties _properties;
int _ytex = -1;
std::unique_ptr<uint8_t[]> _yTexBuffer;
std::array<int, 3> _planeTextureHandles;
std::array<std::unique_ptr<uint8_t[]>, 3> _planeTextureBuffers;
int _utex = -1;
std::unique_ptr<uint8_t[]> _uTexBuffer;
movie_material _movie_material;
material _rgb_material; // Material used when a RGB/RGBA movie is played
int _vtex = -1;
std::unique_ptr<uint8_t[]> _vTexBuffer;
movie_material _render_material;
public:
explicit VideoPresenter(const MovieProperties& props);
+19 -92
View File
@@ -33,18 +33,17 @@ class AVPacketScope
}
};
const char* CHECKED_EXTENSIONS[] = {"webm", "mp4", "ogg",
"png", // This is designed to be used with APNG animations
"mve"};
const char* CHECKED_EXTENSIONS[] = {
"webm",
"mp4",
"ogg",
"mve"
};
const char* CHECKED_SUBT_EXTENSIONS[] = {"srt"};
const char *CHECKED_SUBT_EXTENSIONS[] = {"srt"};
double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
auto fps = av_q2d(stream->r_frame_rate);
#else
auto fps = av_q2d(av_stream_get_r_frame_rate(stream));
#endif
if (fps < 0.000001)
{
@@ -59,7 +58,7 @@ double getFrameRate(AVStream* stream, AVCodecContext* codecCtx) {
return fps;
}
CodecContextParameters getCodecParameters(AVStream* stream) {
CodecContextParameters getCodecParameters(AVStream *stream) {
CodecContextParameters paras;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
paras.width = stream->codecpar->width;
@@ -85,7 +84,7 @@ CodecContextParameters getCodecParameters(AVStream* stream) {
return paras;
}
SCP_string normalizeLanguage(const char* langauge_name) {
SCP_string normalizeLanguage(const char *langauge_name) {
if (!stricmp(langauge_name, "eng")) {
return "English";
}
@@ -102,72 +101,6 @@ SCP_string normalizeLanguage(const char* langauge_name) {
// Default to english for everything else
return "English";
}
/**
* @brief Given a FFmpeg pixel format returns the format it should be converted to
* @param in_fmt The input format
* @return The output format
*/
AVPixelFormat getConversionFormat(AVPixelFormat in_fmt)
{
switch (in_fmt) {
case AV_PIX_FMT_RGB24:
case AV_PIX_FMT_BGR24:
case AV_PIX_FMT_BGR8:
case AV_PIX_FMT_BGR4:
case AV_PIX_FMT_BGR4_BYTE:
case AV_PIX_FMT_RGB8:
case AV_PIX_FMT_RGB4:
case AV_PIX_FMT_RGB4_BYTE:
case AV_PIX_FMT_RGB48BE:
case AV_PIX_FMT_RGB48LE:
case AV_PIX_FMT_RGB565BE:
case AV_PIX_FMT_RGB565LE:
case AV_PIX_FMT_RGB555BE:
case AV_PIX_FMT_RGB555LE:
case AV_PIX_FMT_BGR565BE:
case AV_PIX_FMT_BGR565LE:
case AV_PIX_FMT_BGR555BE:
case AV_PIX_FMT_BGR555LE:
case AV_PIX_FMT_RGB444LE:
case AV_PIX_FMT_RGB444BE:
case AV_PIX_FMT_BGR444LE:
case AV_PIX_FMT_BGR444BE:
case AV_PIX_FMT_BGR48BE:
case AV_PIX_FMT_BGR48LE:
case AV_PIX_FMT_0RGB:
case AV_PIX_FMT_RGB0:
case AV_PIX_FMT_0BGR:
case AV_PIX_FMT_BGR0:
return AV_PIX_FMT_BGR24;
case AV_PIX_FMT_RGBA64BE:
case AV_PIX_FMT_RGBA64LE:
case AV_PIX_FMT_BGRA64BE:
case AV_PIX_FMT_BGRA64LE:
case AV_PIX_FMT_ARGB:
case AV_PIX_FMT_RGBA:
case AV_PIX_FMT_ABGR:
case AV_PIX_FMT_BGRA:
return AV_PIX_FMT_BGRA;
default:
// Assume that everything else is converted to YUV 420
return AV_PIX_FMT_YUV420P;
}
}
FramePixelFormat getPixelFormat(AVPixelFormat fmt)
{
switch (fmt) {
case AV_PIX_FMT_BGR24:
return FramePixelFormat::BGR;
case AV_PIX_FMT_BGRA:
return FramePixelFormat::BGRA;
default:
return FramePixelFormat::YUV420;
}
}
}
namespace cutscene {
@@ -213,9 +146,8 @@ std::unique_ptr<InputStream> openStream(const SCP_string& name) {
return input;
}
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& stream,
std::unique_ptr<InputStream>& subt)
{
std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream> &stream,
std::unique_ptr<InputStream> &subt) {
std::unique_ptr<DecoderStatus> status(new DecoderStatus());
auto ctx = stream->m_ctx->ctx();
@@ -273,18 +205,18 @@ std::unique_ptr<DecoderStatus> initializeStatus(std::unique_ptr<InputStream>& st
if (status->subtitleStream == nullptr) {
// We don't have an external subtitle stream or loading from that file has failed
auto& current_language = Lcl_languages[Lcl_current_lang];
auto &current_language = Lcl_languages[Lcl_current_lang];
for (uint32_t i = 0; i < ctx->nb_streams; ++i) {
auto test_stream = ctx->streams[i];
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(57, 24, 255)
auto& pars = test_stream->codecpar;
auto &pars = test_stream->codecpar;
if (!(pars->codec_type == AVMEDIA_TYPE_SUBTITLE)) {
continue;
}
#endif
AVDictionaryEntry* tag = nullptr;
AVDictionaryEntry *tag = nullptr;
if ((tag = av_dict_get(test_stream->metadata, "language", nullptr, 0)) == nullptr) {
continue;
}
@@ -408,9 +340,8 @@ std::unique_ptr<InputStream> openInputStream(const SCP_string& name) {
return nullptr;
}
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string& name)
{
auto& current_language = Lcl_languages[Lcl_current_lang];
std::unique_ptr<InputStream> openSubtitleStream(const SCP_string &name) {
auto &current_language = Lcl_languages[Lcl_current_lang];
for (auto ext : CHECKED_SUBT_EXTENSIONS) {
SCP_string fileName;
@@ -466,21 +397,18 @@ bool FFMPEGDecoder::initialize(const SCP_string& fileName) {
return true;
}
MovieProperties FFMPEGDecoder::getProperties() const
{
MovieProperties FFMPEGDecoder::getProperties() const {
MovieProperties props;
props.size.width = static_cast<size_t>(m_status->videoCodecPars.width);
props.size.height = static_cast<size_t>(m_status->videoCodecPars.height);
props.fps = static_cast<float>(getFrameRate(m_status->videoStream, m_status->videoCodecCtx));
props.pixelFormat = getPixelFormat(getConversionFormat(m_status->videoCodecPars.pixel_format));
return props;
}
void FFMPEGDecoder::startDecoding() {
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get(), getConversionFormat(m_status->videoCodecPars.pixel_format)));
std::unique_ptr<VideoDecoder> videoDecoder(new VideoDecoder(m_status.get()));
std::unique_ptr<AudioDecoder> audioDecoder;
std::unique_ptr<SubtitleDecoder> subtitleDecoder;
@@ -592,8 +520,7 @@ void FFMPEGDecoder::close() {
m_subtitleInput = nullptr;
}
}
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder* decoder)
{
void FFMPEGDecoder::runSubtitleDecoder(SubtitleDecoder *decoder) {
auto ctx = m_subtitleInput->m_ctx->ctx();
AVPacket packet;
+1 -1
View File
@@ -20,7 +20,7 @@ class FFMPEGDecoder: public Decoder {
bool hasExternalSubtitle() const;
void runSubtitleDecoder(SubtitleDecoder* decoder);
void runSubtitleDecoder(SubtitleDecoder *decoder);
public:
FFMPEGDecoder();
+62 -58
View File
@@ -3,9 +3,11 @@
#include "tracing/tracing.h"
namespace {
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt, AVPixelFormat destination_fmt)
{
return sws_getContext(width, height, fmt, width, height, destination_fmt, SWS_BILINEAR, nullptr, nullptr, nullptr);
const AVPixelFormat DESTINATION_FORMAT = AV_PIX_FMT_YUV420P;
SwsContext* getSWSContext(int width, int height, AVPixelFormat fmt) {
return sws_getContext(width, height, fmt, width, height, DESTINATION_FORMAT,
SWS_BILINEAR, nullptr, nullptr, nullptr);
}
double getFrameTime(int64_t pts, AVRational time_base) {
@@ -16,53 +18,34 @@ double getFrameTime(int64_t pts, AVRational time_base) {
namespace cutscene {
namespace ffmpeg {
class FFMPEGVideoFrame: public VideoFrame {
size_t _width;
size_t _height;
AVFrame* _frame;
public:
FFMPEGVideoFrame(size_t width, size_t height, AVFrame* frame) : _width(width), _height(height), _frame(frame) {}
public:
FFMPEGVideoFrame() : frame(nullptr) {
}
~FFMPEGVideoFrame() override {
if (_frame != nullptr) {
av_freep(&_frame->data[0]);
av_frame_free(&_frame);
if (frame != nullptr) {
av_freep(&frame->data[0]);
av_frame_free(&frame);
}
}
size_t getPlaneNumber() override
{
switch (_frame->format) {
case AV_PIX_FMT_YUV420P:
// YUV data is planar
return 3;
default:
// Everything else is packed
return 1;
}
}
FrameSize getPlaneSize(size_t plane) override
{
switch (_frame->format) {
case AV_PIX_FMT_YUV420P: {
// YUV data is planar
auto width = plane > 0 ? _width / 2 : _width;
auto height = plane > 0 ? _height / 2 : _height;
return {width, height, (size_t)_frame->linesize[plane]};
}
default:
// Everything else is packed
return {_width, _height, (size_t)_frame->linesize[plane]};
}
DataPointers getDataPointers() override {
DataPointers ptrs;
ptrs.y = frame->data[0];
ptrs.u = frame->data[1];
ptrs.v = frame->data[2];
return ptrs;
}
void* getPlaneData(size_t plane) override { return _frame->data[plane]; }
AVFrame* frame;
};
VideoDecoder::VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt)
: FFMPEGStreamDecoder(status), m_frameId(0), m_destinationFormat(destination_fmt)
{
VideoDecoder::VideoDecoder(DecoderStatus* status)
: FFMPEGStreamDecoder(status),
m_frameId(0) {
m_swsCtx = getSWSContext(m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_status->videoCodecPars.pixel_format, destination_fmt);
m_status->videoCodecPars.pixel_format);
}
VideoDecoder::~VideoDecoder() {
@@ -70,32 +53,53 @@ VideoDecoder::~VideoDecoder() {
}
void VideoDecoder::convertAndPushPicture(const AVFrame* frame) {
// Allocate a picture to hold the destination data
// Allocate a picture to hold the YUV data
AVFrame* yuvFrame = av_frame_alloc();
av_frame_copy(yuvFrame, frame);
yuvFrame->format = m_destinationFormat;
yuvFrame->format = DESTINATION_FORMAT;
av_image_alloc(yuvFrame->data, yuvFrame->linesize, m_status->videoCodecPars.width, m_status->videoCodecPars.height,
m_destinationFormat, 1);
av_image_alloc(yuvFrame->data,
yuvFrame->linesize,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height,
DESTINATION_FORMAT,
1);
if (m_status->videoCodecPars.pixel_format == m_destinationFormat) {
av_image_copy(yuvFrame->data, yuvFrame->linesize, (const uint8_t**)(frame->data), frame->linesize,
m_destinationFormat, m_status->videoCodecPars.width, m_status->videoCodecPars.height);
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(new FFMPEGVideoFrame());
if (m_status->videoCodecPars.pixel_format == DESTINATION_FORMAT) {
av_image_copy(yuvFrame->data,
yuvFrame->linesize,
(const uint8_t**) (frame->data),
frame->linesize,
DESTINATION_FORMAT,
m_status->videoCodecPars.width,
m_status->videoCodecPars.height);
} else {
// Convert frame to destination format
sws_scale(m_swsCtx, (uint8_t const* const*)frame->data, frame->linesize, 0, m_status->videoCodecPars.height,
yuvFrame->data, yuvFrame->linesize);
// Convert frame to YUV
sws_scale(
m_swsCtx,
(uint8_t const* const*) frame->data,
frame->linesize,
0,
m_status->videoCodecPars.height,
yuvFrame->data,
yuvFrame->linesize
);
}
std::unique_ptr<FFMPEGVideoFrame> videoFramePtr(
new FFMPEGVideoFrame(static_cast<size_t>(m_status->videoCodecPars.width),
static_cast<size_t>(m_status->videoCodecPars.height), yuvFrame));
videoFramePtr->id = ++m_frameId;
#if LIBAVCODEC_VERSION_INT > AV_VERSION_INT(58, 3, 102)
videoFramePtr->frameTime = getFrameTime(frame->best_effort_timestamp, m_status->videoStream->time_base);
#else
videoFramePtr->frameTime = getFrameTime(av_frame_get_best_effort_timestamp(frame), m_status->videoStream->time_base);
#endif
videoFramePtr->frame = yuvFrame;
videoFramePtr->ySize.height = static_cast<size_t>(m_status->videoCodecPars.height);
videoFramePtr->ySize.width = static_cast<size_t>(m_status->videoCodecPars.width);
videoFramePtr->ySize.stride = static_cast<size_t>(yuvFrame->linesize[0]);
// 420P means that the UV channels have half the width and height
videoFramePtr->uvSize.height = static_cast<size_t>(m_status->videoCodecPars.height / 2);
videoFramePtr->uvSize.width = static_cast<size_t>(m_status->videoCodecPars.width / 2);
videoFramePtr->uvSize.stride = static_cast<size_t>(yuvFrame->linesize[1]);
pushFrame(VideoFramePtr(videoFramePtr.release()));
}
+1 -2
View File
@@ -9,12 +9,11 @@ class VideoDecoder: public FFMPEGStreamDecoder<VideoFrame> {
private:
int m_frameId;
SwsContext* m_swsCtx;
AVPixelFormat m_destinationFormat;
void convertAndPushPicture(const AVFrame* frame);
public:
explicit VideoDecoder(DecoderStatus* status, AVPixelFormat destination_fmt);
explicit VideoDecoder(DecoderStatus* status);
~VideoDecoder() override;
+3 -5
View File
@@ -202,12 +202,10 @@ void movie_display_loop(Player* player, PlaybackState* state) {
auto passed = timestamp - lastDisplayTimestamp;
lastDisplayTimestamp = timestamp;
if (player->isPlaybackReady()) {
// Play as long as the player reports that there is more to display
state->playing = player->update(passed);
// Play as long as the player reports that there is more to display
state->playing = player->update(passed);
displayVideo(player, state);
}
displayVideo(player, state);
processEvents(state);
+18 -21
View File
@@ -17,7 +17,6 @@
#include "io/key.h"
#include "io/timer.h"
#include "player.h"
#include "parse/parselo.h"
using namespace cutscene::player;
@@ -29,7 +28,7 @@ const int MAX_AUDIO_BUFFERS = 15;
std::unique_ptr<Decoder> findDecoder(const SCP_string& name) {
{
std::unique_ptr<Decoder> ffmpeg(new ::cutscene::ffmpeg::FFMPEGDecoder());
std::unique_ptr<Decoder> ffmpeg(new ffmpeg::FFMPEGDecoder());
if (ffmpeg->initialize(name)) {
return ffmpeg;
}
@@ -273,21 +272,8 @@ bool shouldBeginPlayback(Decoder* decoder) {
}
namespace cutscene {
Player::Player(std::unique_ptr<Decoder>&& decoder, bool enable_audio) : m_decoder(std::move(decoder))
{
Assertion(!m_state.videoInited,
"Internal State has been initialized before! Create a new player for replaying a movie.");
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
m_state.props = m_decoder->getProperties();
m_state.decoder = m_decoder.get();
videoPlaybackInit(&m_state);
if (enable_audio) {
audioPlaybackInit(&m_state);
}
Player::Player(std::unique_ptr<Decoder>&& decoder) : m_decoder(std::move(decoder)) {
initPlayback();
}
Player::~Player() {
@@ -329,6 +315,19 @@ bool Player::processDecoderData() {
return decoding || pendingAudio || pendingVideo;
}
void Player::initPlayback() {
Assertion(!m_state.videoInited, "Internal State has been initialized before! Create a new player for replaying a movie.");
m_decoderThread.reset(new std::thread(std::bind(&Player::decoderThread, this)));
m_state.props = m_decoder->getProperties();
m_state.decoder = m_decoder.get();
videoPlaybackInit(&m_state);
audioPlaybackInit(&m_state);
}
bool Player::update(uint64_t diff_time_micro) {
if (m_state.playbackHasBegun) {
m_state.playback_time += diff_time_micro;
@@ -355,8 +354,7 @@ void Player::decoderThread() {
}
}
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name, bool enable_audio)
{
std::unique_ptr<Player> Player::newPlayer(const SCP_string& name) {
mprintf(("Creating player for movie '%s'.\n", name.c_str()));
auto decoder = findDecoder(name);
@@ -364,7 +362,7 @@ std::unique_ptr<Player> Player::newPlayer(const SCP_string& name, bool enable_au
if (decoder == nullptr) {
return nullptr;
}
return std::unique_ptr<Player>(new Player(std::move(decoder), enable_audio));
return std::unique_ptr<Player>(new Player(std::move(decoder)));
}
const PlayerState& Player::getInternalState() const {
return m_state;
@@ -388,5 +386,4 @@ SCP_string Player::getCurrentSubtitle() {
return m_state.currentSubtitle->text;
}
}
bool Player::isPlaybackReady() const { return m_state.playbackHasBegun || shouldBeginPlayback(m_decoder.get()); }
}
+12 -21
View File
@@ -52,7 +52,7 @@ struct PlayerState {
* @brief A movie player
*/
class Player {
private:
private:
std::unique_ptr<Decoder> m_decoder;
std::unique_ptr<std::thread> m_decoderThread;
@@ -61,11 +61,13 @@ class Player {
bool processDecoderData();
private:
private:
void decoderThread();
public:
explicit Player(std::unique_ptr<Decoder>&& decoder, bool enable_audio = true);
void initPlayback();
public:
explicit Player(std::unique_ptr<Decoder>&& decoder);
~Player();
@@ -95,12 +97,6 @@ class Player {
*/
const MovieProperties& getMovieProperties() const;
/**
* @brief Determines if this player can start displaying video.
* @return true if the cutscene is ready, false otherwise
*/
bool isPlaybackReady() const;
/**
* @brief Draws the current movie frame at the specified coordinates.
*
@@ -113,10 +109,6 @@ class Player {
*/
void draw(float x1, float y1, float x2, float y2);
/**
* @brief Gets the subtitle text that should be displayed now
* @return The text, encoded in UTF-8
*/
SCP_string getCurrentSubtitle();
/**
@@ -127,12 +119,11 @@ class Player {
void stopPlayback();
/**
* @brief Creates a player
* The player is configured to play the movie with the specified name
* @param name The movie to play
* @param enable_audio Enable audio for this player instance
* @return @c nullptr if the specified movie could not be opened, a valid Player pointer otherwise
*/
static std::unique_ptr<Player> newPlayer(const SCP_string& name, bool enable_audio = true);
* @brief Creates a player
* The player is configured to play the movie with the specified name
* @param name The movie to play
* @return @c nullptr if the specified movie could not be opened, a valid Player pointer otherwise
*/
static std::unique_ptr<Player> newPlayer(const SCP_string& name);
};
}
+11 -2
View File
@@ -33,7 +33,7 @@ layout (std140) uniform modelData {
model_light lights[MAX_LIGHTS];
float outlineWidth;
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
@@ -105,6 +105,11 @@ in VertexOutput {
#endif
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
vec4 position;
vec3 normal;
@@ -210,6 +215,11 @@ vec3 CalculateLighting(vec3 normal, vec3 diffuseMaterial, vec3 specularMaterial,
void main()
{
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
if(vertIn.notVisible >= 0.9) { discard; }
#endif
#endif
#ifdef FLAG_SHADOW_MAP
// need depth and depth squared for variance shadow maps
fragOut0 = vec4(vertIn.position.z, vertIn.position.z * vertIn.position.z * VARIANCE_SHADOW_SCALE_INV, 0.0, 1.0);
@@ -416,7 +426,6 @@ void main()
// emissive colors won't be added later when we are using forward rendering so we need to do that here
baseColor.rgb += emissiveColor.rgb;
#endif
fragOut0 = baseColor;
#ifdef FLAG_DEFERRED
fragOut1 = vec4(vertIn.position.xyz, 1.0);
+22 -83
View File
@@ -1,18 +1,9 @@
#extension GL_ARB_gpu_shader5: enable
#ifdef FLAG_THICK_OUTLINE
layout (triangles) in;
// For every triangle line we generate 2 triangles which can be done with 4 vertices so in total we will need 12 vertices
layout (triangle_strip, max_vertices = 12) out;
#else
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
#endif
#ifdef FLAG_SHADOW_MAP
#ifdef GL_ARB_gpu_shader5
#ifdef GL_ARB_gpu_shader5
layout(invocations = 4) in;
#endif
#endif
#define MAX_LIGHTS 8
@@ -42,7 +33,7 @@ layout (std140) uniform modelData {
model_light lights[MAX_LIGHTS];
float outlineWidth;
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
@@ -115,13 +106,15 @@ in VertexOutput {
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
#ifdef FLAG_TRANSFORM
float clipModel;
#endif
#else
vec4 position;
#endif
@@ -142,6 +135,11 @@ out VertexOutput {
#endif
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
vec4 position;
vec3 normal;
@@ -152,7 +150,6 @@ out VertexOutput {
#endif
} vertOut;
#ifdef FLAG_SHADOW_MAP
void main(void)
{
#ifdef GL_ARB_gpu_shader5
@@ -162,25 +159,14 @@ void main(void)
#endif
for(int vert = 0; vert < gl_in.length(); vert++)
{
#ifdef FLAG_TRANSFORM
if (vertIn[vert].clipModel > 0.9) {
// If the model was clipped in the vertex shader then we do not apply the shadow projection matrix here
gl_Position = gl_in[vert].gl_Position;
} else {
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
}
#else
gl_Position = shadow_proj_matrix[instanceID] * gl_in[vert].gl_Position;
#endif
if(gl_Position.z < -1.0)
gl_Position.z = -1.0;
vertOut.position = gl_in[vert].gl_Position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
gl_Layer = instanceID;
#ifdef FLAG_ENV_MAP
vertOut.envReflect = vertIn[vert].envReflect;
#endif
@@ -197,66 +183,19 @@ void main(void)
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#endif
#if defined(FLAG_CLIP)
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
vertOut.notVisible = vertIn[vert].notVisible;
#endif
#ifdef FLAG_CLIP
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
#else
#if defined(FLAG_CLIP) || defined(FLAG_TRANSFORM)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
#endif
EmitVertex();
}
EndPrimitive();
}
#elif defined(FLAG_THICK_OUTLINE)
const vec2 pixelOffsetDir[4] = vec2[](
vec2(0.0, 1.0),
vec2(1.0, 1.0),
vec2(1.0, -1.0),
vec2(0.0, -1.0)
);
void main(void)
{
for(int vert = 0; vert < gl_in.length(); vert++)
{
int nextVert = (vert + 1) % gl_in.length();
vec4 clip = gl_in[vert].gl_Position;
vec4 diff = gl_in[nextVert].gl_Position - clip; // vector from vert to the next vertex in the list
vec2 normal = normalize(vec2(diff.y, -diff.x)); // Computing the normal of a 2D vector is actually rather simple...
for (int lineVert = 0; lineVert < 4; ++lineVert)
{
// This is the pixel offset along the normal axis
vec2 yOffPixel = pixelOffsetDir[lineVert].y * normal * (outlineWidth / 2.0);
// This is the offset of the vertex along the vector between this vertex and the next one in the triangle
vec2 xOff = pixelOffsetDir[lineVert].x * diff.xy;
// This is the final offset in clip space
vec2 finalOffset = xOff + yOffPixel * vec2(vpwidth, vpheight) * clip.w;
gl_Position = vec4(clip.xyz + vec3(finalOffset, 0.0), clip.w);
vertOut.position = vertIn[vert].position;
vertOut.normal = vertIn[vert].normal;
vertOut.texCoord = vertIn[vert].texCoord;
#ifdef FLAG_ENV_MAP
vertOut.envReflect = vertIn[vert].envReflect;
#endif
#ifdef FLAG_NORMAL_MAP
vertOut.tangentMatrix = vertIn[vert].tangentMatrix;
#endif
#ifdef FLAG_FOG
vertOut.fogDist = vertIn[vert].fogDist;
#endif
#ifdef FLAG_SHADOWS
vertOut.shadowUV[0] = vertIn[vert].shadowUV[0];
vertOut.shadowUV[1] = vertIn[vert].shadowUV[1];
vertOut.shadowUV[2] = vertIn[vert].shadowUV[2];
vertOut.shadowUV[3] = vertIn[vert].shadowUV[3];
vertOut.shadowPos = vertIn[vert].shadowPos;
#endif
#if defined(FLAG_CLIP)
gl_ClipDistance[0] = gl_in[vert].gl_ClipDistance[0];
#endif
EmitVertex();
}
EndPrimitive();
}
}
#endif
+36 -20
View File
@@ -36,7 +36,7 @@ layout (std140) uniform modelData {
model_light lights[MAX_LIGHTS];
float outlineWidth;
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
@@ -113,15 +113,15 @@ out VertexOutput {
#ifdef FLAG_FOG
float fogDist;
#endif
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
float notVisible;
#endif
#endif
#ifdef FLAG_SHADOW_MAP
#if !defined(GL_ARB_gpu_shader5)
float instance;
#endif
#ifdef FLAG_TRANSFORM
// This flag is needed to let the geometry shader know that it doesn't need to apply the
// shadow projection to gl_Position
float clipModel;
#endif
#else
vec4 position;
#endif
@@ -152,9 +152,19 @@ void main()
vec4 texCoord;
mat4 orient = mat4(1.0);
mat4 scale = mat4(1.0);
#ifdef FLAG_TRANSFORM
#ifdef WORKAROUND_CLIPPING_PLANES
#ifdef FLAG_TRANSFORM
bool clipModel;
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
vertOut.notVisible = clipModel ? 1.0 : 0.0;
#endif
#else
#ifdef FLAG_TRANSFORM
bool clipModel;
getModelTransform(orient, clipModel, int(vertModelID), buffer_matrix_offset);
#else
bool clipModel = false;
#endif
#endif
texCoord = textureMatrix * vertTexCoord;
vec4 vertex = vertPosition;
@@ -178,6 +188,9 @@ void main()
#else
gl_Position = projMatrix * position;
#endif
#ifdef FLAG_NORMAL_EXTRUDE
gl_Position.xy += (mat3(projMatrix) * normal.xyz).xy * gl_Position.z * extrudeWidth;
#endif
#ifdef FLAG_SHADOWS
vec4 shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
vertOut.shadowPos = shadow_mv_matrix * modelMatrix * orient * vertPosition;
@@ -200,28 +213,31 @@ void main()
#ifdef FLAG_FOG
vertOut.fogDist = clamp((gl_Position.z - fogStart) * 0.75 * fogScale, 0.0, 1.0);
#endif
#ifdef FLAG_TRANSFORM
if (clipModel) {
// Clip this model by moving all vertices outside the clip volume
gl_Position = vec4(vec3(-2.0), 1.0);
}
#ifdef FLAG_SHADOW_MAP
vertOut.clipModel = clipModel ? 1.0 : 0.0;
#endif
#endif
#ifdef FLAG_CLIP
#ifdef WORKAROUND_CLIPPING_PLANES
if(use_clip_plane) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#else
#ifdef FLAG_CLIP
if (clipModel) {
gl_ClipDistance[0] = -1.0;
} else if(use_clip_plane) {
gl_ClipDistance[0] = dot(clip_equation, modelMatrix * orient * vertex);
} else {
gl_ClipDistance[0] = 1.0;
}
#elif defined(FLAG_TRANSFORM)
gl_ClipDistance[0] = clipModel ? -1.0 : 1.0;
#endif
#endif
#ifndef FLAG_SHADOW_MAP
#ifndef FLAG_SHADOW_MAP
vertOut.position = position;
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#else
#else
vertOut.normal = normal;
vertOut.texCoord = texCoord;
#endif
#endif
}
@@ -1,36 +0,0 @@
local exts = {
"",
".lua",
".lc"
}
local function cfileLoader(name)
local file = nil
for i,v in ipairs(exts) do
local real_name = name .. v
file = cf.openFile(real_name, "r", "data/scripts")
if (file:isValid()) then
name = real_name
break;
end
end
if (file == nil or not file:isValid()) then
return "Module '" .. name .. "' is not known by the CFile system"
end
local content = file:read("*a")
file:close()
local func, err = loadstring(content, name)
if err then
return err
end
return func
end
table.insert(package.loaders, 2, cfileLoader)
+2 -2
View File
@@ -5,7 +5,7 @@ IF(MSVC)
set(RES_CONTENT)
set(ARRAY_ELEMENTS)
FOREACH(file ${default_files_files})
FOREACH(file ${file_root_def_files_files})
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
@@ -39,7 +39,7 @@ else()
set(INCLUDE_LIST)
set(ARRAY_ELEMENTS)
FOREACH(file ${default_files_files})
FOREACH(file ${file_root_def_files_files})
set(INPUT_NAME "${CMAKE_CURRENT_SOURCE_DIR}/${file}")
SET(OUTPUT "${GENERATED_SOURCE_DIR}/code/${file}")
file(RELATIVE_PATH RELATIVE_FILE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/def_files" "${INPUT_NAME}")
-15
View File
@@ -1,15 +0,0 @@
#include "events.h"
namespace events {
util::event<void> EngineUpdate;
util::event<void> EngineShutdown;
util::event<void, int, int> GameLeaveState;
util::event<void, int, int> GameEnterState;
util::event<void, const char*> GameMissionLoad;
}
-16
View File
@@ -1,16 +0,0 @@
#pragma once
#include "utils/event.h"
namespace events {
extern util::event<void> EngineUpdate;
extern util::event<void> EngineShutdown;
extern util::event<void, int, int> GameLeaveState;
extern util::event<void, int, int> GameEnterState;
extern util::event<void, const char*> GameMissionLoad;
}
+1 -1
View File
@@ -1101,7 +1101,7 @@ void fs2netd_store_stats()
if (Duplicate_login_detected) {
Duplicate_login_detected = false;
multi_display_chat_msg( XSTR("<Duplicate login detected - stats have been tossed>", 1582), 0, 0 );
ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1582) );
ml_string( XSTR("<Duplicate login detected - stats have been tossed>", 1583) );
fs2netd_store_stats_results();
return;
}
+1 -1
View File
@@ -483,7 +483,7 @@ void parse_helptbl(const char *filename)
break;
case 4: // $end
default:
UNREACHABLE("This should never happen.\n");
Assertion(false, "This should never happen.\n");
break;
}
} // end while
+14 -14
View File
@@ -19,7 +19,7 @@
SCP_vector<game_snd> Snds;
SCP_vector<game_snd> Snds_iface;
SCP_vector<sound_handle> Snds_iface_handle;
SCP_vector<int> Snds_iface_handle;
// jg18 - default priorities and limits for retail gameplay sounds
static const int NUM_RETAIL_GAMEPLAY_SOUNDS = 192; // indices 0-191, from retail sounds.tbl
@@ -260,7 +260,7 @@ void gamesnd_add_retail_default_enhanced_sound_data()
void gamesnd_play_iface(interface_snd_id n)
{
if (Snds_iface_handle[n.value()].isValid())
if (Snds_iface_handle[n.value()] >= 0)
snd_stop(Snds_iface_handle[n.value()]);
Snds_iface_handle[n.value()] = snd_play(gamesnd_get_interface_sound(n));
@@ -565,9 +565,9 @@ void gamesnd_unload_gameplay_sounds()
Assert( Snds.size() <= INT_MAX );
for (SCP_vector<game_snd>::iterator gs = Snds.begin(); gs != Snds.end(); ++gs) {
for (auto& entry : gs->sound_entries) {
if (entry.id.isValid()) {
if (entry.id != -1) {
snd_unload(entry.id);
entry.id = sound_load_id::invalid();
entry.id = -1;
}
}
}
@@ -599,9 +599,9 @@ void gamesnd_unload_interface_sounds()
Assert( Snds_iface.size() < INT_MAX );
for (SCP_vector<game_snd>::iterator si = Snds_iface.begin(); si != Snds_iface.end(); ++si) {
for (auto& entry : si->sound_entries) {
if (entry.id.isValid()) {
if ( entry.id != -1 ) {
snd_unload( entry.id );
entry.id = sound_load_id::invalid();
entry.id = -1;
entry.id_sig = -1;
}
}
@@ -617,9 +617,6 @@ void parse_gamesnd_old(game_snd* gs)
gs->sound_entries.resize(1);
auto& entry = gs->sound_entries.back();
// Default pitch is 1.0. This is set here in case we don't have a valid file name
gs->pitch_range = util::UniformFloatRange(1.0f);
stuff_string(entry.filename, F_NAME, MAX_FILENAME_LEN, ",");
if (!stricmp(entry.filename, NOX("empty")))
@@ -676,6 +673,9 @@ void parse_gamesnd_old(game_snd* gs)
}
}
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
// check for extra values per Mantis #2408
ignore_gray_space();
if (stuff_int_optional(&temp, true) == 2)
@@ -840,9 +840,6 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
// New extended format found
stuff_string(name, F_NAME, MAX_FILENAME_LEN);
// Default pitch is 1.0. This is set here in case we don't have a valid file name
gs->pitch_range = util::UniformFloatRange(1.0f);
if (!stricmp(name, NOX("empty")))
{
entry->filename[0] = 0;
@@ -917,6 +914,9 @@ void parse_gamesnd_new(game_snd* gs, bool no_create)
error_display(1, "Invalid enhanced sound limit: %d\n", temp_limit);
}
}
// Default pitch is 1.0
gs->pitch_range = util::UniformFloatRange(1.0f);
}
void gamesnd_parse_entry(game_snd *gs, bool no_create, SCP_vector<game_snd> *lookupVector)
@@ -1197,7 +1197,7 @@ void parse_sound_table(const char* filename)
if (gamesnd_parse_line(&tempSound, "$Name:", &Snds_iface))
{
Snds_iface.push_back(game_snd(tempSound));
Snds_iface_handle.push_back(sound_handle::invalid());
Snds_iface_handle.push_back(-1);
}
}
@@ -1322,7 +1322,7 @@ float gamesnd_get_max_duration(game_snd* gs) {
int max_length = 0;
for (auto& entry : gs->sound_entries) {
if (!entry.id.isValid()) {
if (entry.id < 0) {
// Lazily load unloaded sound entries when required
entry.id = snd_load(&entry, gs->flags);
}
+1 -1
View File
@@ -578,7 +578,7 @@ void parse_everything_else(const char *filename)
}
break;
default:
UNREACHABLE("MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n");
Assertion(false, "MageKing17 made a coding error somewhere, and you should laugh at him (and report this error).\n");
break;
}
}
-9
View File
@@ -81,12 +81,3 @@
#define CLANG_ANALYZER_NORETURN
#endif
#endif
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __builtin_unreachable()
#endif
-7
View File
@@ -63,10 +63,3 @@
* @brief Specifies that an analyzer should consider this function as no-return
*/
#define CLANG_ANALYZER_NORETURN
/**
* @brief Specifies that the code at which point this macro appears at is unreachable
* @param msg The message to display in debug mode
* @param ... Format arguments for the message
*/
#define UNREACHABLE(msg, ...)
-9
View File
@@ -72,12 +72,3 @@
#endif
#define CLANG_ANALYZER_NORETURN
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __builtin_unreachable()
#endif
-9
View File
@@ -69,12 +69,3 @@
#endif
#define CLANG_ANALYZER_NORETURN
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __builtin_unreachable()
#endif
-10
View File
@@ -82,13 +82,3 @@
#define FALLTHROUGH
#define CLANG_ANALYZER_NORETURN
#ifndef NDEBUG
#define UNREACHABLE(msg, ...) \
do { \
os::dialogs::Error(__FILE__, __LINE__, msg, ##__VA_ARGS__); \
} while (false)
#else
#define UNREACHABLE(msg, ...) __assume(false)
#endif
+8 -8
View File
@@ -19,17 +19,17 @@
#include "cmdline/cmdline.h"
#include "debugconsole/console.h"
#include "gamesequence/gamesequence.h" //WMC - for scripting hooks in gr_flip()
#include "gamesequence/gamesequence.h" //WMC - for scripting hooks in gr_flip()
#include "globalincs/systemvars.h"
#include "graphics/2d.h"
#include "graphics/matrix.h"
#include "graphics/light.h"
#include "graphics/font.h"
#include "graphics/grbatch.h"
#include "graphics/grinternal.h"
#include "graphics/grstub.h"
#include "graphics/light.h"
#include "graphics/matrix.h"
#include "graphics/opengl/gropengl.h"
#include "graphics/opengl/gropengldraw.h"
#include "graphics/grstub.h"
#include "graphics/paths/PathRenderer.h"
#include "graphics/util/GPUMemoryHeap.h"
#include "graphics/util/UniformBuffer.h"
@@ -37,10 +37,9 @@
#include "io/keycontrol.h" // m!m
#include "io/timer.h"
#include "osapi/osapi.h"
#include "parse/parselo.h"
#include "popup/popup.h"
#include "render/3d.h"
#include "scripting/scripting.h"
#include "parse/parselo.h"
#include "render/3d.h"
#include "tracing/tracing.h"
#include "utils/boost/hash_combine.h"
@@ -2153,7 +2152,8 @@ void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float a
void gr_flip(bool execute_scripting)
{
// m!m avoid running CHA_ONFRAME when the "Quit mission" popup is shown. See mantis 2446 for reference
if (execute_scripting && !popup_active()) {
if (execute_scripting && !quit_mission_popup_shown)
{
TRACE_SCOPE(tracing::LuaOnFrame);
//WMC - Do conditional hooks. Yippee!
+39 -39
View File
@@ -186,7 +186,7 @@ enum shader_type {
#define SDR_FLAG_MODEL_HDR (1<<18)
#define SDR_FLAG_MODEL_AMBIENT_MAP (1<<19)
#define SDR_FLAG_MODEL_NORMAL_ALPHA (1<<20)
#define SDR_FLAG_MODEL_THICK_OUTLINES (1<<21) // Renders the model geometry as an outline with configurable line width
#define SDR_FLAG_MODEL_NORMAL_EXTRUDE (1<<21)
#define SDR_FLAG_PARTICLE_POINT_GEN (1<<0)
@@ -776,7 +776,7 @@ typedef struct screen {
void (*gf_render_primitives)(material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle, size_t buffer_offset);
void (*gf_render_primitives_particle)(particle_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_primitives_distortion)(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_movie)(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer, size_t buffer_offset);
void (*gf_render_movie)(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer);
void (*gf_render_primitives_batched)(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_nanovg)(nanovg_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void (*gf_render_decals)(decal_material* material_info, primitive_type prim_type, vertex_layout* layout, int num_elements, const indexed_vertex_source& buffers);
@@ -942,67 +942,67 @@ void gr_shield_icon(coord2d coords[6], const int resize_mode = GR_RESIZE_FULL);
// Here be the bitmap functions
#define gr_bm_free_data GR_CALL(gr_screen.gf_bm_free_data)
#define gr_bm_create GR_CALL(gr_screen.gf_bm_create)
#define gr_bm_init GR_CALL(gr_screen.gf_bm_init)
#define gr_bm_page_in_start GR_CALL(gr_screen.gf_bm_page_in_start)
#define gr_bm_data GR_CALL(gr_screen.gf_bm_data)
#define gr_bm_free_data GR_CALL(*gr_screen.gf_bm_free_data)
#define gr_bm_create GR_CALL(*gr_screen.gf_bm_create)
#define gr_bm_init GR_CALL(*gr_screen.gf_bm_init)
#define gr_bm_page_in_start GR_CALL(*gr_screen.gf_bm_page_in_start)
#define gr_bm_data GR_CALL(*gr_screen.gf_bm_data)
#define gr_bm_make_render_target GR_CALL(gr_screen.gf_bm_make_render_target)
#define gr_bm_make_render_target GR_CALL(*gr_screen.gf_bm_make_render_target)
__inline int gr_bm_set_render_target(int n, int face = -1)
{
return (*gr_screen.gf_bm_set_render_target)(n, face);
}
#define gr_set_texture_addressing GR_CALL(gr_screen.gf_set_texture_addressing)
#define gr_set_texture_addressing GR_CALL(*gr_screen.gf_set_texture_addressing)
inline int gr_create_buffer(BufferType type, BufferUsageHint usage)
{
return (*gr_screen.gf_create_buffer)(type, usage);
}
#define gr_delete_buffer GR_CALL(gr_screen.gf_delete_buffer)
#define gr_update_buffer_data GR_CALL(gr_screen.gf_update_buffer_data)
#define gr_update_buffer_data_offset GR_CALL(gr_screen.gf_update_buffer_data_offset)
#define gr_update_transform_buffer GR_CALL(gr_screen.gf_update_transform_buffer)
#define gr_delete_buffer GR_CALL(*gr_screen.gf_delete_buffer)
#define gr_update_buffer_data GR_CALL(*gr_screen.gf_update_buffer_data)
#define gr_update_buffer_data_offset GR_CALL(*gr_screen.gf_update_buffer_data_offset)
#define gr_update_transform_buffer GR_CALL(*gr_screen.gf_update_transform_buffer)
#define gr_scene_texture_begin GR_CALL(gr_screen.gf_scene_texture_begin)
#define gr_scene_texture_end GR_CALL(gr_screen.gf_scene_texture_end)
#define gr_copy_effect_texture GR_CALL(gr_screen.gf_copy_effect_texture)
#define gr_scene_texture_begin GR_CALL(*gr_screen.gf_scene_texture_begin)
#define gr_scene_texture_end GR_CALL(*gr_screen.gf_scene_texture_end)
#define gr_copy_effect_texture GR_CALL(*gr_screen.gf_copy_effect_texture)
#define gr_post_process_set_effect GR_CALL(gr_screen.gf_post_process_set_effect)
#define gr_post_process_set_defaults GR_CALL(gr_screen.gf_post_process_set_defaults)
#define gr_post_process_begin GR_CALL(gr_screen.gf_post_process_begin)
#define gr_post_process_end GR_CALL(gr_screen.gf_post_process_end)
#define gr_post_process_save_zbuffer GR_CALL(gr_screen.gf_post_process_save_zbuffer)
#define gr_post_process_set_effect GR_CALL(*gr_screen.gf_post_process_set_effect)
#define gr_post_process_set_defaults GR_CALL(*gr_screen.gf_post_process_set_defaults)
#define gr_post_process_begin GR_CALL(*gr_screen.gf_post_process_begin)
#define gr_post_process_end GR_CALL(*gr_screen.gf_post_process_end)
#define gr_post_process_save_zbuffer GR_CALL(*gr_screen.gf_post_process_save_zbuffer)
inline void gr_post_process_restore_zbuffer() {
gr_screen.gf_post_process_restore_zbuffer();
}
#define gr_deferred_lighting_begin GR_CALL(gr_screen.gf_deferred_lighting_begin)
#define gr_deferred_lighting_end GR_CALL(gr_screen.gf_deferred_lighting_end)
#define gr_deferred_lighting_finish GR_CALL(gr_screen.gf_deferred_lighting_finish)
#define gr_deferred_lighting_begin GR_CALL(*gr_screen.gf_deferred_lighting_begin)
#define gr_deferred_lighting_end GR_CALL(*gr_screen.gf_deferred_lighting_end)
#define gr_deferred_lighting_finish GR_CALL(*gr_screen.gf_deferred_lighting_finish)
#define gr_zbias GR_CALL(gr_screen.gf_zbias)
#define gr_set_fill_mode GR_CALL(gr_screen.gf_set_fill_mode)
#define gr_zbias GR_CALL(*gr_screen.gf_zbias)
#define gr_set_fill_mode GR_CALL(*gr_screen.gf_set_fill_mode)
#define gr_set_line_width GR_CALL(gr_screen.gf_set_line_width)
#define gr_set_line_width GR_CALL(*gr_screen.gf_set_line_width)
#define gr_sphere GR_CALL(gr_screen.gf_sphere)
#define gr_sphere GR_CALL(*gr_screen.gf_sphere)
#define gr_maybe_create_shader GR_CALL(gr_screen.gf_maybe_create_shader)
#define gr_recompile_all_shaders GR_CALL(gr_screen.gf_recompile_all_shaders)
#define gr_set_animated_effect GR_CALL(gr_screen.gf_set_animated_effect)
#define gr_maybe_create_shader GR_CALL(*gr_screen.gf_maybe_create_shader)
#define gr_recompile_all_shaders GR_CALL(*gr_screen.gf_recompile_all_shaders)
#define gr_set_animated_effect GR_CALL(*gr_screen.gf_set_animated_effect)
#define gr_clear_states GR_CALL(gr_screen.gf_clear_states)
#define gr_clear_states GR_CALL(*gr_screen.gf_clear_states)
#define gr_update_texture GR_CALL(gr_screen.gf_update_texture)
#define gr_get_bitmap_from_texture GR_CALL(gr_screen.gf_get_bitmap_from_texture)
#define gr_update_texture GR_CALL(*gr_screen.gf_update_texture)
#define gr_get_bitmap_from_texture GR_CALL(*gr_screen.gf_get_bitmap_from_texture)
#define gr_shadow_map_start GR_CALL(gr_screen.gf_shadow_map_start)
#define gr_shadow_map_end GR_CALL(gr_screen.gf_shadow_map_end)
#define gr_render_shield_impact GR_CALL(gr_screen.gf_render_shield_impact)
#define gr_shadow_map_start GR_CALL(*gr_screen.gf_shadow_map_start)
#define gr_shadow_map_end GR_CALL(*gr_screen.gf_shadow_map_end)
#define gr_render_shield_impact GR_CALL(*gr_screen.gf_render_shield_impact)
__inline void gr_render_primitives(material* material_info, primitive_type prim_type, vertex_layout* layout, int vert_offset, int n_verts, int buffer_handle = -1, size_t buffer_offset = 0)
{
@@ -1029,9 +1029,9 @@ __inline void gr_render_primitives_distortion(distortion_material* material_info
(*gr_screen.gf_render_primitives_distortion)(material_info, prim_type, layout, offset, n_verts, buffer_handle);
}
inline void gr_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer, size_t buffer_offset = 0)
inline void gr_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer)
{
(*gr_screen.gf_render_movie)(material_info, prim_type, layout, n_verts, buffer, buffer_offset);
(*gr_screen.gf_render_movie)(material_info, prim_type, layout, n_verts, buffer);
}
__inline void gr_render_model(model_material* material_info, indexed_vertex_source *vert_source, vertex_buffer* bufferp, size_t texi)
+9 -5
View File
@@ -158,28 +158,32 @@ int generic_anim_stream(generic_anim *ga, const bool cache)
{
CFILE *img_cfp = NULL;
int anim_fps = 0;
char full_path[MAX_PATH];
size_t size = 0, offset = 0;
const void* file_data = nullptr;
const int NUM_TYPES = 3;
const ubyte type_list[NUM_TYPES] = {BM_TYPE_EFF, BM_TYPE_ANI, BM_TYPE_PNG};
const char *ext_list[NUM_TYPES] = {".eff", ".ani", ".png"};
int rval = -1;
int bpp;
ga->type = BM_TYPE_NONE;
auto res = cf_find_file_location_ext(ga->filename, NUM_TYPES, ext_list, CF_TYPE_ANY, false);
rval = cf_find_file_location_ext(ga->filename, NUM_TYPES, ext_list, CF_TYPE_ANY, sizeof(full_path) - 1, full_path, &size, &offset, 0, &file_data);
// could not be found, or is invalid for some reason
if ( !res.found )
if ( (rval < 0) || (rval >= NUM_TYPES) )
return -1;
//make sure we can open it
img_cfp = cfopen_special(res.full_name.c_str(), "rb", res.size, res.offset, res.data_ptr, CF_TYPE_ANY);
img_cfp = cfopen_special(full_path, "rb", size, offset, file_data, CF_TYPE_ANY);
if (img_cfp == NULL) {
return -1;
}
strcat_s(ga->filename, ext_list[res.extension_index]);
ga->type = type_list[res.extension_index];
strcat_s(ga->filename, ext_list[rval]);
ga->type = type_list[rval];
//seek to the end
cfseek(img_cfp, 0, CF_SEEK_END);
+1 -1
View File
@@ -335,7 +335,7 @@ void gr_stub_render_primitives_distortion(distortion_material* /*material_info*
{
}
void gr_stub_render_movie(movie_material* /*material_info*/, primitive_type /*prim_type*/, vertex_layout* /*layout*/, int /*n_verts*/, int /*buffer*/, size_t /*buffer_offset*/)
void gr_stub_render_movie(movie_material* /*material_info*/, primitive_type /*prim_type*/, vertex_layout* /*layout*/, int /*n_verts*/, int /*buffer*/)
{
}
+23 -12
View File
@@ -635,6 +635,27 @@ float model_material::get_normal_alpha_max() const
return Normal_alpha_max;
}
void model_material::set_normal_extrude(float width)
{
Normal_extrude = true;
Normal_extrude_width = width;
}
void model_material::set_normal_extrude()
{
Normal_extrude = false;
}
bool model_material::is_normal_extrude_active() const
{
return Normal_extrude;
}
float model_material::get_normal_extrude_width() const
{
return Normal_extrude_width;
}
void model_material::set_fog(int r, int g, int b, float _near, float _far)
{
Fog_params.enabled = true;
@@ -660,16 +681,6 @@ const model_material::fog& model_material::get_fog() const
return Fog_params;
}
void model_material::set_outline_thickness(float thickness) {
Outline_thickness = thickness;
}
float model_material::get_outline_thickness() const {
return Outline_thickness;
}
bool model_material::uses_thick_outlines() const {
return Outline_thickness > 0.0f;
}
uint model_material::get_shader_flags() const
{
uint Shader_flags = 0;
@@ -757,8 +768,8 @@ uint model_material::get_shader_flags() const
Shader_flags |= SDR_FLAG_MODEL_NORMAL_ALPHA;
}
if ( uses_thick_outlines() ) {
Shader_flags |= SDR_FLAG_MODEL_THICK_OUTLINES;
if ( Normal_extrude ) {
Shader_flags |= SDR_FLAG_MODEL_NORMAL_EXTRUDE;
}
return Shader_flags;
+7 -6
View File
@@ -200,10 +200,10 @@ class model_material : public material
float Normal_alpha_min = 0.0f;
float Normal_alpha_max = 1.0f;
bool Normal_extrude = false;
float Normal_extrude_width = -1.0f;
fog Fog_params;
float Outline_thickness = -1.0f;
public:
model_material();
@@ -246,9 +246,10 @@ public:
float get_normal_alpha_min() const;
float get_normal_alpha_max() const;
void set_outline_thickness(float thickness = -1.0f);
float get_outline_thickness() const;
bool uses_thick_outlines() const;
void set_normal_extrude(float width);
void set_normal_extrude();
bool is_normal_extrude_active() const;
float get_normal_extrude_width() const;
void set_batching(bool enabled);
bool is_batched() const;
+1 -1
View File
@@ -137,7 +137,7 @@ GLenum get_gl_shader_stage(opengl::ShaderStage stage) {
case opengl::STAGE_FRAGMENT:
return GL_FRAGMENT_SHADER;
default:
UNREACHABLE("Unhandled shader type found!");
Assertion(false, "Unhandled shader type found!");
return GL_NONE;
}
}
+15 -20
View File
@@ -29,7 +29,6 @@
#include "math/floating.h"
#include "model/model.h"
#include "nebula/neb.h"
#include "libs/renderdoc/renderdoc.h"
#include "osapi/osapi.h"
#include "osapi/osregistry.h"
#include "render/3d.h"
@@ -91,8 +90,7 @@ static GLenum GL_read_format = GL_BGRA;
GLuint GL_vao = 0;
SCP_string GL_implementation_id;
SCP_vector<GLint> GL_binary_formats;
bool GL_workaround_clipping_planes = false;
static std::unique_ptr<os::OpenGLContext> GL_context = nullptr;
@@ -1367,6 +1365,19 @@ static void init_extensions() {
}
}
static void opengl_do_workaround_checks() {
auto vendor = glGetString(GL_VENDOR);
if (strstr((const char*) vendor, "NVIDIA")) {
// Nvidia has some weird issues with clipping planes. Check #1579 for more information.
GL_workaround_clipping_planes = true;
mprintf((" Applying clipping plane workaround for NVIDIA hardware.\n"));
} else {
// Assume everone else has proper support for this
GL_workaround_clipping_planes = false;
}
}
bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
{
if (GL_initted) {
@@ -1379,9 +1390,6 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
gr_screen.max_h,
gr_screen.bits_per_pixel ));
// Load the RenderDoc API if available before doing anything with OpenGL
renderdoc::loadApi();
graphic_operations = std::move(graphicsOps);
if ( opengl_init_display_device() ) {
@@ -1438,20 +1446,7 @@ bool gr_opengl_init(std::unique_ptr<os::GraphicsOperations>&& graphicsOps)
mprintf(( " OpenGL Version : %s\n", glGetString(GL_VERSION) ));
mprintf(( "\n" ));
// Build a string identifier for this OpenGL implementation
GL_implementation_id.clear();
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_VENDOR));
GL_implementation_id += "\n";
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_RENDERER));
GL_implementation_id += "\n";
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_VERSION));
GL_implementation_id += "\n";
GL_implementation_id += reinterpret_cast<const char*>(glGetString(GL_SHADING_LANGUAGE_VERSION));
GLint formats = 0;
glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &formats);
GL_binary_formats.resize(formats);
glGetIntegerv(GL_PROGRAM_BINARY_FORMATS, GL_binary_formats.data());
opengl_do_workaround_checks();
if (Cmdline_fullscreen_window || Cmdline_window) {
opengl_go_windowed();
+1 -2
View File
@@ -58,7 +58,6 @@ extern GLuint GL_vao;
extern float GL_alpha_threshold;
extern SCP_string GL_implementation_id;
extern SCP_vector<GLint> GL_binary_formats;
extern bool GL_workaround_clipping_planes; //!< If set then clipping planes can not be used for batched model rendering
#endif
-11
View File
@@ -188,9 +188,6 @@ void gr_opengl_deferred_lighting_finish()
light_data->lightDir.xyz.x = view_dir.xyzw.x;
light_data->lightDir.xyz.y = view_dir.xyzw.y;
light_data->lightDir.xyz.z = view_dir.xyzw.z;
vm_vec_scale(&light_data->specLightColor, static_light_factor);
first_directional = false;
break;
case Light_Type::Cone:
@@ -202,9 +199,6 @@ void gr_opengl_deferred_lighting_finish()
case Light_Type::Point:
light_data->diffuseLightColor = diffuse;
light_data->specLightColor = spec;
vm_vec_scale(&light_data->specLightColor, static_point_factor);
light_data->lightRadius = MAX(l.rada, l.radb) * 1.25f;
light_data->scale.xyz.x = MAX(l.rada, l.radb) * 1.28f;
light_data->scale.xyz.y = MAX(l.rada, l.radb) * 1.28f;
@@ -223,15 +217,10 @@ void gr_opengl_deferred_lighting_finish()
light_data->scale.xyz.y = l.radb * 1.53f;
light_data->scale.xyz.z = length;
vm_vec_scale(&light_data->specLightColor, static_tube_factor);
// Tube lights consist of two different types of lights with almost the same properties
light_data = uniformAligner.addTypedElement<deferred_light_data>();
light_data->diffuseLightColor = diffuse;
light_data->specLightColor = spec;
vm_vec_scale(&light_data->specLightColor, static_tube_factor);
light_data->lightRadius = l.radb * 1.5f;
light_data->lightType = LT_POINT;
+6 -4
View File
@@ -786,16 +786,18 @@ void gr_opengl_render_primitives_distortion(distortion_material* material_info,
GL_CHECK_FOR_ERRORS("start of gr_opengl_render_primitives_distortion()");
}
void gr_opengl_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts,
int buffer, size_t buffer_offset)
{
void gr_opengl_render_movie(movie_material* material_info,
primitive_type prim_type,
vertex_layout* layout,
int n_verts,
int buffer) {
GR_DEBUG_SCOPE("Render movie frame");
gr_set_2d_matrix();
opengl_tnl_set_material_movie(material_info);
opengl_render_primitives(prim_type, layout, n_verts, buffer, 0, buffer_offset);
opengl_render_primitives(prim_type, layout, n_verts, buffer, 0, 0);
gr_end_2d_matrix();
}
+1 -1
View File
@@ -55,7 +55,7 @@ void gr_opengl_render_primitives(material* material_info, primitive_type prim_ty
void gr_opengl_render_primitives_particle(particle_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_primitives_batched(batched_bitmap_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_primitives_distortion(distortion_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer, size_t buffer_offset);
void gr_opengl_render_movie(movie_material* material_info, primitive_type prim_type, vertex_layout* layout, int n_verts, int buffer);
void gr_opengl_render_nanovg(nanovg_material* material_info, primitive_type prim_type, vertex_layout* layout, int offset, int n_verts, int buffer_handle);
void gr_opengl_render_decals(decal_material* material_info, primitive_type prim_type, vertex_layout* layout, int num_elements, const indexed_vertex_source& binding);
+1 -1
View File
@@ -50,7 +50,7 @@ void gr_opengl_query_value(int obj, QueryType type) {
glQueryCounter(slot.name, GL_TIMESTAMP);
break;
default:
UNREACHABLE("Unhandled enum value!");
Assertion(false, "Unhandled enum value!");
break;
}
}
+16 -97
View File
@@ -8,7 +8,6 @@
*/
#include "cfile/cfile.h"
#include "cmdline/cmdline.h"
#include "def_files/def_files.h"
#include "graphics/2d.h"
@@ -214,9 +213,9 @@ static opengl_shader_variant_t GL_shader_variants[] = {
{ },
"Normal Alpha" },
{ SDR_TYPE_MODEL, true, SDR_FLAG_MODEL_THICK_OUTLINES, "FLAG_THICK_OUTLINE",
{ SDR_TYPE_MODEL, false, SDR_FLAG_MODEL_NORMAL_EXTRUDE, "FLAG_NORMAL_EXTRUDE",
{ },
"Thick outlines" },
"Normal Extrusion" },
{ SDR_TYPE_EFFECT_PARTICLE, true, SDR_FLAG_PARTICLE_POINT_GEN, "FLAG_EFFECT_GEOMETRY",
{ opengl_vert_attrib::UVEC },
@@ -338,18 +337,17 @@ void opengl_shader_shutdown()
GL_shader.clear();
}
static SCP_string opengl_shader_get_header(shader_type type_id, int flags, bool has_geo_shader) {
static SCP_string opengl_shader_get_header(shader_type type_id, int flags) {
SCP_stringstream sflags;
sflags << "#version " << GLSL_version << " core\n";
if (Detail.lighting < 3) {
sflags << "#define FLAG_LIGHT_MODEL_BLINN_PHONG\n";
if (GL_workaround_clipping_planes) {
sflags << "#define WORKAROUND_CLIPPING_PLANES\n";
}
if (has_geo_shader) {
// If there is a geometry shader then we define a special preprocessor symbol to make writing shaders easier
sflags << "#define HAS_GEOMETRY_SHADER\n";
if (Detail.lighting < 3) {
sflags << "#define FLAG_LIGHT_MODEL_BLINN_PHONG\n";
}
if (type_id == SDR_TYPE_POST_PROCESS_MAIN || type_id == SDR_TYPE_POST_PROCESS_LIGHTSHAFTS || type_id == SDR_TYPE_POST_PROCESS_FXAA) {
@@ -478,9 +476,9 @@ static SCP_string handle_includes(const char* filename, const SCP_string& origin
return output.str();
}
static SCP_vector<SCP_string> opengl_get_shader_content(shader_type type_id, const char* filename, int flags, bool has_geo_shader) {
static SCP_vector<SCP_string> opengl_get_shader_content(shader_type type_id, const char* filename, int flags, shader_stage) {
SCP_vector<SCP_string> parts;
parts.push_back(opengl_shader_get_header(type_id, flags, has_geo_shader));
parts.push_back(opengl_shader_get_header(type_id, flags));
parts.push_back(handle_includes(filename, opengl_load_shader(filename)));
@@ -507,9 +505,6 @@ static SCP_string get_shader_hash(const SCP_vector<SCP_string>& vert,
md5.update(reinterpret_cast<const char*>(&i), sizeof(i));
}
md5.update(GL_implementation_id.data(),
(MD5::size_type)GL_implementation_id.size() * sizeof(SCP_string::value_type));
md5.finalize();
return md5.hexdigest();
@@ -537,8 +532,7 @@ static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_
auto metadata = base_filename + ".json";
auto binary = base_filename + ".bin";
auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
auto metadata_fp = cfopen(metadata.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE);
if (!metadata_fp) {
nprintf(("ShaderCache", "Metadata file does not exist.\n"));
return false;
@@ -565,22 +559,7 @@ static bool load_cached_shader_binary(opengl::ShaderProgram* program, const SCP_
auto binary_format = (GLenum) format;
json_decref(metadata_root);
bool supported = false;
for (auto supported_fmt : GL_binary_formats) {
if ((GLenum)supported_fmt == binary_format) {
supported = true;
break;
}
}
if (!supported) {
// This can happen in case an implementation stops supporting a particular binary format
nprintf(("ShaderCache", "Unsupported binary format %d encountered in shader cache.\n", binary_format));
return false;
}
auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
auto binary_fp = cfopen(binary.c_str(), "rb", CFILE_NORMAL, CF_TYPE_CACHE);
if (!binary_fp) {
nprintf(("ShaderCache", "Binary file does not exist.\n"));
return false;
@@ -643,8 +622,7 @@ static void cache_program_binary(GLuint program, const SCP_string& hash) {
auto metadata_name = base_filename + ".json";
auto binary_name = base_filename + ".bin";
auto metadata_fp = cfopen(metadata_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
auto metadata_fp = cfopen(metadata_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE);
if (!metadata_fp) {
mprintf(("Could not open shader cache metadata file!\n"));
return;
@@ -659,8 +637,7 @@ static void cache_program_binary(GLuint program, const SCP_string& hash) {
cfclose(metadata_fp);
json_decref(metadata);
auto binary_fp = cfopen(binary_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
auto binary_fp = cfopen(binary_name.c_str(), "wb", CFILE_NORMAL, CF_TYPE_CACHE);
if (!binary_fp) {
mprintf(("Could not open shader cache binary file!\n"));
return;
@@ -713,13 +690,13 @@ void opengl_compile_shader_actual(shader_type sdr, const uint &flags, opengl_sha
}
}
auto vert_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags, use_geo_sdr);
auto frag_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags, use_geo_sdr);
auto vert_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->vert, flags, SDR_STAGE_VERTEX);
auto frag_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->frag, flags, SDR_STAGE_FRAGMENT);
SCP_vector<SCP_string> geom_content;
if (use_geo_sdr) {
// read geometry shader
geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags, use_geo_sdr);
geom_content = opengl_get_shader_content(sdr_info->type_id, sdr_info->geo, flags, SDR_STAGE_GEOMETRY);
}
auto shader_hash = get_shader_hash(vert_content, geom_content, frag_content);
@@ -858,62 +835,6 @@ void gr_opengl_recompile_all_shaders(const std::function<void(size_t, size_t)>&
}
}
static void opengl_purge_shader_cache_type(const char* ext) {
SCP_string filter("*.");
filter += ext;
// Previously the cache files were stored in the mod directory. Since we have a better system now, those files
// should be cleaned out. This is only needed if we have a mod directory since otherwise we would delete the actual
// cache files
if (Cmdline_mod != nullptr && strlen(Cmdline_mod) > 0) {
SCP_vector<SCP_string> cache_files;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, nullptr,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
for (auto& file : cache_files) {
cf_delete((file + "." + ext).c_str(), CF_TYPE_CACHE,
CF_LOCATION_TYPE_PRIMARY_MOD | CF_LOCATION_TYPE_SECONDARY_MODS);
}
}
SCP_vector<SCP_string> cache_files;
SCP_vector<file_list_info> file_info;
cf_get_file_list(cache_files, CF_TYPE_CACHE, filter.c_str(), CF_SORT_NONE, &file_info,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
Assertion(cache_files.size() == file_info.size(),
"cf_get_file_list returned different sizes for file names and file informations!");
const auto TIMEOUT = 2.0 * 30.0 * 24.0 * 60.0 * 60.0; // purge timeout in seconds which is ~2 months
const SCP_string PREFIX = "ogl_shader-";
auto now = std::time(nullptr);
for (size_t i = 0; i < cache_files.size(); ++i) {
auto& name = cache_files[i];
auto write_time = file_info[i].write_time;
if (name.compare(0, PREFIX.size(), PREFIX) != 0) {
// Not an OpenGL cache file
continue;
}
auto diff = std::difftime(now, write_time);
if (diff > TIMEOUT) {
auto full_name = name + "." + ext;
cf_delete(full_name.c_str(), CF_TYPE_CACHE);
}
}
}
static void opengl_purge_old_shader_cache()
{
opengl_purge_shader_cache_type("json");
opengl_purge_shader_cache_type("bin");
}
/**
* Initializes the shader system. Creates a 1x1 texture that can be used as a fallback texture when framebuffer support is missing.
* Also compiles the shaders used for particle rendering.
@@ -938,8 +859,6 @@ void opengl_shader_init()
// Reserve 32 shader slots. This should cover most use cases in real life.
GL_shader.reserve(32);
opengl_purge_old_shader_cache();
// compile effect shaders
gr_opengl_maybe_create_shader(SDR_TYPE_EFFECT_PARTICLE, 0);
gr_opengl_maybe_create_shader(SDR_TYPE_EFFECT_PARTICLE, SDR_FLAG_PARTICLE_POINT_GEN);
+15 -7
View File
@@ -106,7 +106,7 @@ static GLenum convertBufferType(BufferType type) {
case BufferType::Uniform:
return GL_UNIFORM_BUFFER;
default:
UNREACHABLE("Unhandled enum value!");
Assertion(false, "Unhandled enum value!");
return GL_INVALID_ENUM;
}
}
@@ -120,7 +120,7 @@ static GLenum convertUsageHint(BufferUsageHint usage) {
case BufferUsageHint::Streaming:
return GL_STREAM_DRAW;
default:
UNREACHABLE("Unhandled enum value!");
Assertion(false, "Unhandled enum value!");
return GL_INVALID_ENUM;
}
}
@@ -144,7 +144,7 @@ static GLenum convertStencilOp(const StencilOperation stencil_op) {
case StencilOperation::Invert:
return GL_INVERT;
default:
UNREACHABLE("Unhandled enum value encountered!");
Assertion(false, "Unhandled enum value encountered!");
return GL_NONE;
}
}
@@ -177,7 +177,7 @@ static GLenum convertComparisionFunction(ComparisionFunction func) {
mode = GL_NOTEQUAL;
break;
default:
UNREACHABLE("Unhandled comparision function value!");
Assertion(false, "Unhandled comparision function value!");
mode = GL_ALWAYS;
break;
}
@@ -758,10 +758,18 @@ void opengl_tnl_set_model_material(model_material *material_info)
GL_state.Texture.SetShaderMode(GL_TRUE);
if (Current_shader->flags & SDR_FLAG_MODEL_CLIP) {
GL_state.ClipDistance(0, true);
if (GL_workaround_clipping_planes) {
if (Current_shader->flags & SDR_FLAG_MODEL_CLIP) {
GL_state.ClipDistance(0, true);
} else {
GL_state.ClipDistance(0, false);
}
} else {
GL_state.ClipDistance(0, false);
if (Current_shader->flags & SDR_FLAG_MODEL_CLIP || Current_shader->flags & SDR_FLAG_MODEL_TRANSFORM) {
GL_state.ClipDistance(0, true);
} else {
GL_state.ClipDistance(0, false);
}
}
uint32_t array_index;
-18
View File
@@ -270,12 +270,6 @@ void NanoVGRenderer::renderFill(NVGpaint* paint,
const float* bounds,
const NVGpath* paths,
int npaths) {
if (npaths <= 0) {
// Ignore irrelevant render calls
mprintf(("NanoVG asked us to render filled triangles but no paths were supplied!\n"));
return;
}
auto call = addDrawCall();
call->type = CallType::Fill;
@@ -337,12 +331,6 @@ void NanoVGRenderer::renderFill(NVGpaint* paint,
}
}
void NanoVGRenderer::renderTriangles(NVGpaint* paint, NVGscissor* scissor, const NVGvertex* verts, int nverts) {
if (nverts <= 0) {
// Ignore irrelevant render calls
mprintf(("NanoVG asked us to render triangles but no vertices were supplied!\n"));
return;
}
_vertices.insert(_vertices.end(), verts, verts + nverts);
auto call = addDrawCall();
@@ -366,12 +354,6 @@ void NanoVGRenderer::renderStroke(NVGpaint* paint,
float strokeWidth,
const NVGpath* paths,
int npaths) {
if (npaths <= 0) {
// Ignore irrelevant render calls
mprintf(("NanoVG asked us to render stroke triangles but no paths were supplied!\n"));
return;
}
auto call = addDrawCall();
call->type = CallType::Stroke;
+1 -9
View File
@@ -1333,15 +1333,13 @@ int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)
{
FONSglyph* glyph = NULL;
const char* str = iter->next;
unsigned int last_dec_status = FONS_UTF8_ACCEPT;
iter->str = iter->next;
if (str == iter->end)
return 0;
for (; str != iter->end; str++) {
last_dec_status = fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str);
if (last_dec_status)
if (fons__decutf8(&iter->utf8state, &iter->codepoint, *(const unsigned char*)str))
continue;
str++;
// Get glyph and quad
@@ -1355,12 +1353,6 @@ int fonsTextIterNext(FONScontext* stash, FONStextIter* iter, FONSquad* quad)
}
iter->next = str;
if (last_dec_status) {
// If we are here then the iterator reached the end of the string and UTF-8 encoding failed
// In this case we do not have a valid code point so we need to return false
return 0;
}
return 1;
}
+2 -2
View File
@@ -2316,12 +2316,12 @@ float nvgText(NVGcontext* ctx, float x, float y, const char* string, const char*
while (fonsTextIterNext(ctx->fs, &iter, &q)) {
float c[4*2];
if (iter.prevGlyphIndex == -1) { // can not retrieve glyph?
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
if (nverts != 0) {
nvg__renderText(ctx, verts, nverts);
nverts = 0;
}
if (!nvg__allocTextAtlas(ctx))
break; // no memory :(
iter = prevIter;
fonsTextIterNext(ctx->fs, &iter, &q); // try again
if (iter.prevGlyphIndex == -1) // still can not find glyph?
+4 -4
View File
@@ -47,11 +47,11 @@ void convert_model_material(model_uniform_data* data_out,
data_out->color = material.get_color();
data_out->vpwidth = 1.0f / i2fl(gr_screen.max_w);
data_out->vpheight = 1.0f / i2fl(gr_screen.max_h);
if (shader_flags & SDR_FLAG_MODEL_ANIMATED) {
data_out->anim_timer = material.get_animated_effect_time();
data_out->effect_num = material.get_animated_effect();
data_out->vpwidth = 1.0f / i2fl(gr_screen.max_w);
data_out->vpheight = 1.0f / i2fl(gr_screen.max_h);
}
if (shader_flags & SDR_FLAG_MODEL_CLIP) {
@@ -267,8 +267,8 @@ void convert_model_material(model_uniform_data* data_out,
data_out->normalAlphaMinMax.y = material.get_normal_alpha_max();
}
if ( shader_flags & SDR_FLAG_MODEL_THICK_OUTLINES ) {
data_out->outlineWidth = material.get_outline_thickness();
if (shader_flags & SDR_FLAG_MODEL_NORMAL_EXTRUDE) {
data_out->extrudeWidth = material.get_normal_extrude_width();
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ BufferType getBufferType(GpuHeap heap_type) {
return BufferType::Index;
case GpuHeap::NUM_VALUES:
default:
UNREACHABLE("Invalid heap type detected!");
Assertion(false, "Invalid heap type detected!");
return BufferType::Vertex;
}
}
+2 -2
View File
@@ -17,7 +17,7 @@ size_t getElementSize(uniform_block_type type) {
return sizeof(graphics::decal_info);
case uniform_block_type::NUM_BLOCK_TYPES:
default:
UNREACHABLE("Invalid block type encountered!");
Assertion(false, "Invalid block type encountered!");
return 0;
}
}
@@ -33,7 +33,7 @@ size_t getHeaderSize(uniform_block_type type) {
return 0;
case uniform_block_type::NUM_BLOCK_TYPES:
default:
UNREACHABLE("Invalid block type encountered!");
Assertion(false, "Invalid block type encountered!");
return 0;
}
}
+1 -1
View File
@@ -80,7 +80,7 @@ struct model_uniform_data {
model_light lights[MAX_UNIFORM_LIGHTS];
float outlineWidth;
float extrudeWidth;
float fogStart;
float fogScale;
int buffer_matrix_offset;
+12 -12
View File
@@ -85,7 +85,7 @@ int HUD_disable_except_messages = 0;
color HUD_color_defaults[HUD_NUM_COLOR_LEVELS]; // array of colors with different alpha blending
color HUD_color_debug; // grey debug text shown on HUD
static sound_handle Player_engine_snd_loop = sound_handle::invalid();
static int Player_engine_snd_loop = -1;
// HUD render frame offsets
float HUD_offset_x = 0.0f;
@@ -1420,7 +1420,7 @@ void hud_update_frame(float /*frametime*/)
}
if (Player_ai->target_objnum == -1) {
if (Target_static_looping.isValid()) {
if ( Target_static_looping != -1 ) {
snd_stop(Target_static_looping);
}
return;
@@ -1810,9 +1810,9 @@ void hud_render_gauges(int cockpit_display_num)
*/
void hud_stop_looped_engine_sounds()
{
if (Player_engine_snd_loop.isValid()) {
if ( Player_engine_snd_loop > -1 ) {
snd_stop(Player_engine_snd_loop);
Player_engine_snd_loop = sound_handle::invalid();
Player_engine_snd_loop = -1;
}
}
@@ -1831,9 +1831,9 @@ void update_throttle_sound()
float percent_throttle;
if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
if (Player_engine_snd_loop.isValid()) {
if(Player_engine_snd_loop != -1){
snd_stop(Player_engine_snd_loop);
Player_engine_snd_loop = sound_handle::invalid();
Player_engine_snd_loop = -1;
}
return;
@@ -1851,16 +1851,16 @@ void update_throttle_sound()
percent_throttle = Player_obj->phys_info.fspeed / Ships[Player_obj->instance].current_max_speed;
}
if (percent_throttle != last_percent_throttle || !Player_engine_snd_loop.isValid()) {
if ( percent_throttle != last_percent_throttle || Player_engine_snd_loop == -1 ) {
if ( percent_throttle < ZERO_PERCENT ) {
if (Player_engine_snd_loop.isValid()) {
if ( Player_engine_snd_loop > -1 ) {
snd_stop(Player_engine_snd_loop); // Backslash - otherwise, long engine loops keep playing
Player_engine_snd_loop = sound_handle::invalid();
Player_engine_snd_loop = -1;
}
}
else {
if (!Player_engine_snd_loop.isValid()) {
if ( Player_engine_snd_loop == -1 ){
Player_engine_snd_loop = snd_play_looping( gamesnd_get_game_sound(ship_get_sound(Player_obj, GameSounds::ENGINE)), 0.0f , -1, -1, percent_throttle * ENGINE_MAX_VOL, FALSE);
} else {
// The sound may have been trashed at the low-level if sound channel overflow.
@@ -1869,7 +1869,7 @@ void update_throttle_sound()
snd_set_volume(Player_engine_snd_loop, percent_throttle * ENGINE_MAX_VOL);
}
else {
Player_engine_snd_loop = sound_handle::invalid();
Player_engine_snd_loop = -1;
}
}
}
@@ -2895,7 +2895,7 @@ void HudGaugeSupport::render(float /*frametime*/)
}
else
{
strcpy_s(outstr, XSTR("Waiting...", 1603));
sprintf(outstr, "Waiting...");
}
}
renderStringAlignCenter(position[0], position[1] + text_val_offset_y, w, outstr);
+3 -3
View File
@@ -153,7 +153,7 @@ void parse_ssm(const char *filename)
s.shape = SSM_SHAPE_SPHERE;
break;
default:
UNREACHABLE("Impossible return value from required_string_one_of(); get a coder!\n");
Assertion(false, "Impossible return value from required_string_one_of(); get a coder!\n");
}
} else {
s.shape = SSM_SHAPE_CIRCLE;
@@ -224,7 +224,7 @@ void ssm_get_random_start_pos(vec3d *out, vec3d *start, matrix *orient, size_t s
switch (s->shape) {
case SSM_SHAPE_SPHERE:
// get a random vector in a sphere around the target
vm_vec_random_in_sphere(&temp, start, radius, 1);
vm_vec_random_in_sphere(&temp, start, orient, radius, 1);
break;
case SSM_SHAPE_CIRCLE:
// get a random vector in the circle of the firing plane
@@ -235,7 +235,7 @@ void ssm_get_random_start_pos(vec3d *out, vec3d *start, matrix *orient, size_t s
vm_vec_scale_add(&temp, start, &orient->vec.fvec, radius);
break;
default:
UNREACHABLE("Unknown shape '%d' in SSM type #" SIZE_T_ARG " ('%s'). This should not be possible; get a coder!\n", s->shape, ssm_index, s->name);
Assertion(false, "Unknown shape '%d' in SSM type #" SIZE_T_ARG " ('%s'). This should not be possible; get a coder!\n", s->shape, ssm_index, s->name);
break;
}
+1 -1
View File
@@ -1013,7 +1013,7 @@ void HudGaugeBrackets::renderBoundingBrackets(int x1, int y1, int x2, int y2, in
tinfo_name = XSTR("Debris", 348);
break;
case OBJ_WEAPON:
strcpy_s(temp_name, Weapon_info[Weapons[t_objp->instance].weapon_info_index].get_display_string());
strcpy_s(temp_name, Weapon_info[Weapons[t_objp->instance].weapon_info_index].name);
end_string_at_first_hash_symbol(temp_name);
tinfo_name = temp_name;
break;
+2 -4
View File
@@ -1642,8 +1642,7 @@ void hud_config_as_player()
void hud_config_color_save(char *name)
{
int idx;
CFILE* out = cfopen(name, "wt", CFILE_NORMAL, CF_TYPE_PLAYERS, false,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
CFILE *out = cfopen(name, "wt", CFILE_NORMAL, CF_TYPE_PLAYERS);
char vals[255] = "";
// bad
@@ -1844,8 +1843,7 @@ void hud_config_color_init()
// get a list of all hcf files
memset(HC_filenames, 0, sizeof(char*) * MAX_HCF_FILES);
HC_num_files = cf_get_file_list(MAX_HCF_FILES, HC_filenames, CF_TYPE_PLAYERS, "*.hcf", CF_SORT_NAME, nullptr,
CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
HC_num_files = cf_get_file_list(MAX_HCF_FILES, HC_filenames, CF_TYPE_PLAYERS, "*.hcf", CF_SORT_NAME);
}
void hud_config_color_close()
+1 -1
View File
@@ -372,7 +372,7 @@ void HudGaugeEscort::renderIcon(int x, int y, int index)
}
// print out ship name
strcpy_s(buf, sp->get_display_string());
strcpy_s(buf, sp->ship_name);
font::force_fit_string(buf, 255, ship_name_max_width);
end_string_at_first_hash_symbol(buf);
+11 -11
View File
@@ -36,8 +36,8 @@ vec3d lock_world_pos;
static float Lock_start_dist;
sound_handle Missile_track_loop = sound_handle::invalid();
sound_handle Missile_lock_loop = sound_handle::invalid();
int Missile_track_loop = -1;
int Missile_lock_loop = -1;
int Lock_target_box_width[GR_NUM_RESOLUTIONS] = {
19,
@@ -606,9 +606,9 @@ void hud_do_lock_indicator(float frametime)
return;
if (Player_ai->current_target_is_locked) {
if (Missile_track_loop.isValid()) {
if ( Missile_track_loop > -1 ) {
snd_stop(Missile_track_loop);
Missile_track_loop = sound_handle::invalid();
Missile_track_loop = -1;
if (wip->hud_locked_snd.isValid())
{
@@ -622,9 +622,9 @@ void hud_do_lock_indicator(float frametime)
}
else {
Player_ai->ai_flags.set(AI::AI_Flags::Seek_lock); // set this flag so multiplayer's properly track lock on other ships
if (Missile_lock_loop.isValid() && snd_is_playing(Missile_lock_loop)) {
if ( Missile_lock_loop != -1 && snd_is_playing(Missile_lock_loop) ) {
snd_stop(Missile_lock_loop);
Missile_lock_loop = sound_handle::invalid();
Missile_lock_loop = -1;
}
}
}
@@ -840,7 +840,7 @@ void hud_calculate_lock_position(float frametime)
accumulated_y_pixels -= int_portion;
}
if (!Missile_track_loop.isValid()) {
if ( Missile_track_loop == -1 ) {
if (wip->hud_tracking_snd.isValid())
{
Missile_track_loop = snd_play_looping( gamesnd_get_game_sound(wip->hud_tracking_snd), 0.0f , -1, -1);
@@ -863,9 +863,9 @@ void hud_calculate_lock_position(float frametime)
} else {
if (Missile_track_loop.isValid()) {
if ( Missile_track_loop > -1 ) {
snd_stop(Missile_track_loop);
Missile_track_loop = sound_handle::invalid();
Missile_track_loop = -1;
}
Player_ai->current_target_is_locked = 0;
@@ -977,9 +977,9 @@ void hud_calculate_lock_start_pos()
// hud_stop_looped_locking_sounds() will terminate any hud related looping sounds that are playing
void hud_stop_looped_locking_sounds()
{
if (Missile_track_loop.isValid()) {
if ( Missile_track_loop > -1 ) {
snd_stop(Missile_track_loop);
Missile_track_loop = sound_handle::invalid();
Missile_track_loop = -1;
}
}
+1 -1
View File
@@ -558,7 +558,7 @@ void HUD_ship_sent_printf(int sh, const char *format, ...)
tmp[sizeof(tmp)-1] = '\0';
size_t len;
snprintf(tmp, sizeof(tmp)-1, NOX("%s: "), Ships[sh].get_display_string());
snprintf(tmp, sizeof(tmp)-1, NOX("%s: "), Ships[sh].ship_name);
len = strlen(tmp);
va_start(args, format);
-1
View File
@@ -30,7 +30,6 @@ void hud_observer_init(ship *shipp, ai_info *aip)
// (we used to do a memcpy here, but that doesn't work any longer, so let's just assign the values we need)
Hud_obs_ship.clear();
strcpy_s(Hud_obs_ship.ship_name, shipp->ship_name);
Hud_obs_ship.display_name = shipp->display_name;
Hud_obs_ship.team = shipp->team;
Hud_obs_ship.ai_index = shipp->ai_index;
Hud_obs_ship.flags = shipp->flags;
+1 -1
View File
@@ -404,7 +404,7 @@ int hud_squadmsg_count_ships(int add_to_menu)
if (add_to_menu)
{
Assert ( Num_menu_items < MAX_MENU_ITEMS );
strcpy_s( MsgItems[Num_menu_items].text, shipp->get_display_string() );
strcpy_s( MsgItems[Num_menu_items].text, shipp->ship_name );
end_string_at_first_hash_symbol(MsgItems[Num_menu_items].text); // truncate the name if it has a # in it
MsgItems[Num_menu_items].instance = SHIP_INDEX(shipp);
MsgItems[Num_menu_items].active = 1;
+34 -48
View File
@@ -37,7 +37,6 @@
#include "network/multi.h"
#include "network/multiutil.h"
#include "object/object.h"
#include "libs/renderdoc/renderdoc.h"
#include "parse/parselo.h"
#include "playerman/player.h"
#include "render/3dinternal.h"
@@ -438,7 +437,7 @@ weapon_flash Weapon_flash_info;
// Data used for the proximity warning
typedef struct homing_beep_info
{
sound_handle snd_handle; // sound handle for last played beep
int snd_handle; // sound handle for last played beep
fix last_time_played; // time beep was last played
int min_cycle_time; // time (in ms) for fastest cycling of the sound
int max_cycle_time; // time (in ms) for slowest cycling of the sound
@@ -447,7 +446,7 @@ typedef struct homing_beep_info
float precalced_interp; // a precalculated value used in a linear interpretation
} homing_beep_info;
homing_beep_info Homing_beep = {sound_handle::invalid(), 0, 150, 1000, 30.0f, 1500.0f, 1.729412f};
homing_beep_info Homing_beep = { -1, 0, 150, 1000, 30.0f, 1500.0f, 1.729412f };
// Set at the start of a mission, used to decide how to draw the separation for the warning missile indicators
float Min_warning_missile_dist;
@@ -1010,7 +1009,7 @@ void hud_weapons_init()
// init data used to play the homing "proximity warning" sound
void hud_init_homing_beep()
{
Homing_beep.snd_handle = sound_handle::invalid();
Homing_beep.snd_handle = -1;
Homing_beep.last_time_played = 0;
Homing_beep.precalced_interp = (Homing_beep.max_cycle_dist-Homing_beep.min_cycle_dist) / (Homing_beep.max_cycle_time - Homing_beep.min_cycle_time );
}
@@ -5293,18 +5292,16 @@ void hud_stuff_ship_name(char *ship_name_text, ship *shipp)
if ( ((Iff_info[shipp->team].flags & IFFF_WING_NAME_HIDDEN) && (shipp->wingnum != -1)) || (shipp->flags[Ship::Ship_Flags::Hide_ship_name]) ) {
*ship_name_text = 0;
} else {
strcpy(ship_name_text, shipp->get_display_string());
strcpy(ship_name_text, shipp->ship_name);
// handle hash symbol
end_string_at_first_hash_symbol(ship_name_text);
if (!Disable_built_in_translations) {
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_name_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_name_text);
}
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_name_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_name_text);
}
}
}
@@ -5336,13 +5333,11 @@ void hud_stuff_ship_callsign(char *ship_callsign_text, ship *shipp)
// handle hash symbol
end_string_at_first_hash_symbol(ship_callsign_text);
if (!Disable_built_in_translations) {
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_callsign_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_callsign_text);
}
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_callsign_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_callsign_text);
}
}
@@ -5367,13 +5362,11 @@ void hud_stuff_ship_class(char *ship_class_text, ship *shipp)
// handle hash symbol
end_string_at_first_hash_symbol(ship_class_text);
if (!Disable_built_in_translations) {
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_class_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_class_text);
}
// handle translation
if (Lcl_gr) {
lcl_translate_targetbox_name_gr(ship_class_text);
} else if (Lcl_pl) {
lcl_translate_targetbox_name_pl(ship_class_text);
}
}
@@ -5599,7 +5592,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
setGaugeColor(HUD_C_BRIGHT);
//Draw name
renderString(currentx, currenty, XSTR("Energy", 1616));
renderString(currentx, currenty, "Energy");
currenty += line_height;
//Draw background
@@ -5633,11 +5626,10 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
setGaugeColor(HUD_C_NORMAL);
}
if(gr_screen.max_w_unscaled == 640) {
strcpy_s(shortened_name, Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].get_display_string());
font::force_fit_string(shortened_name, NAME_LENGTH, 55);
renderString(currentx, currenty, shortened_name);
} else {
renderString(currentx, currenty, Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].get_display_string());
renderString(currentx, currenty, Weapon_info[Player_ship->weapons.primary_bank_weapons[x]].name);
}
//Next 'line'
@@ -5755,7 +5747,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
// show all primary banks
for ( i = 0; i < Player_ship->weapons.num_primary_banks; i++ ) {
wip = &Weapon_info[sw->primary_bank_weapons[i]];
strcpy_s(buf, wip->get_display_string());
strcpy_s(buf, (wip->alt_name[0]) ? wip->alt_name : wip->name);
if ( Armed_alignment ) {
gr_get_string_size(&w, &h, buf);
@@ -5769,7 +5761,7 @@ void HudGaugeWeaponEnergy::render(float /*frametime*/)
// just show the current armed bank
i = Player_ship->weapons.current_primary_bank;
wip = &Weapon_info[sw->primary_bank_weapons[i]];
strcpy_s(buf, wip->get_display_string());
strcpy_s(buf, (wip->alt_name[0]) ? wip->alt_name : wip->name);
if ( Armed_alignment ) {
gr_get_string_size(&w, &h, buf);
@@ -6059,8 +6051,8 @@ void HudGaugeWeapons::render(float /*frametime*/)
renderBitmap(primary_last[ballistic_hud_index].first_frame, position[0] + frame_offset_x[ballistic_hud_index], y);
}
strcpy_s(name, Weapon_info[sw->primary_bank_weapons[i]].get_display_string());
if (Lcl_gr && !Disable_built_in_translations) {
strcpy_s(name, (Weapon_info[sw->primary_bank_weapons[i]].alt_name[0]) ? Weapon_info[sw->primary_bank_weapons[i]].alt_name : Weapon_info[sw->primary_bank_weapons[i]].name);
if (Lcl_gr) {
lcl_translate_wep_name_gr(name);
}
@@ -6127,16 +6119,11 @@ void HudGaugeWeapons::render(float /*frametime*/)
maybeFlashWeapon(np+i);
if (wip->has_alternate_name()) {
// Do not apply the cluster bomb hack if we have an alternate name to make translating that name possible
strcpy_s(weapon_name, wip->get_display_string());
// HACK - make Cluster Bomb fit on the HUD.
if(!stricmp(wip->name,"cluster bomb")){
strcpy_s(weapon_name, NOX("Cluster"));
} else {
// HACK - make Cluster Bomb fit on the HUD.
if(!stricmp(wip->name,"cluster bomb")){
strcpy_s(weapon_name, NOX("Cluster"));
} else {
strcpy_s(weapon_name, wip->get_display_string());
}
strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
}
// get rid of #
@@ -6697,7 +6684,7 @@ void HudGaugeWarheadCount::render(float /*frametime*/)
}
char weapon_name[NAME_LENGTH + 10];
strcpy_s(weapon_name, wip->get_display_string());
strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
end_string_at_first_hash_symbol(weapon_name);
setGaugeColor();
@@ -6934,9 +6921,9 @@ void HudGaugePrimaryWeapons::render(float /*frametime*/)
renderBitmap(_background_entry.first_frame, position[0], position[1] + bg_y_offset);
strcpy_s(name, Weapon_info[sw->primary_bank_weapons[i]].get_display_string());
strcpy_s(name, (Weapon_info[sw->primary_bank_weapons[i]].alt_name[0]) ? Weapon_info[sw->primary_bank_weapons[i]].alt_name : Weapon_info[sw->primary_bank_weapons[i]].name);
if (Lcl_gr && !Disable_built_in_translations) {
if (Lcl_gr) {
lcl_translate_wep_name_gr(name);
}
@@ -7053,7 +7040,7 @@ void HudGaugeSecondaryWeapons::render(float /*frametime*/)
maybeFlashWeapon(num_primaries+i);
strcpy_s(weapon_name, wip->get_display_string());
strcpy_s(weapon_name, (wip->alt_name[0]) ? wip->alt_name : wip->name);
end_string_at_first_hash_symbol(weapon_name);
if ( sw->current_secondary_bank == i ) {
@@ -7195,8 +7182,7 @@ void HudGaugeHardpoints::render(float /*frametime*/)
render_info.set_color(gauge_color);
render_info.set_flags(MR_NO_LIGHTING | MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_TEXTURING | MR_NO_ZBUFFER | MR_NO_CULL | MR_STENCIL_READ);
// Factor was chosen pretty arbitrarily to make outline feature work with existing data
render_info.set_outline_thickness(15.f * _line_width);
render_info.set_normal_extrude_width(_line_width * 0.01f);
model_render_immediate(
&render_info,
+17 -23
View File
@@ -55,7 +55,7 @@ object *Enemy_attacker = NULL;
static int Target_static_next;
static int Target_static_playing;
sound_handle Target_static_looping = sound_handle::invalid();
int Target_static_looping;
int Target_display_cargo;
char Cargo_string[256] = "";
@@ -1008,7 +1008,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp)
setGaugeColor();
// print out the weapon class name
sprintf( outstr,"%s", target_wip->get_display_string() );
sprintf( outstr,"%s", target_wip->name );
gr_get_string_size(&w,&h,outstr);
// drop name past the # sign
@@ -1034,7 +1034,7 @@ void HudGaugeTargetBox::renderTargetWeapon(object *target_objp)
dist = vm_vec_dist(&target_objp->pos, &wp->homing_pos);
if ( speed > 0 ) {
sprintf(outstr, XSTR("impact: %.1f sec", 1596), dist/speed);
sprintf(outstr, NOX("impact: %.1f sec"), dist/speed);
} else {
strcpy_s(outstr, XSTR( "unknown", 349));
}
@@ -1405,7 +1405,7 @@ void HudGaugeExtraTargetData::pageIn()
*/
void HudGaugeExtraTargetData::render(float /*frametime*/)
{
char tmpbuf[256];
char outstr[256], tmpbuf[256];
int has_orders = 0;
int not_training;
int extra_data_shown=0;
@@ -1440,22 +1440,17 @@ void HudGaugeExtraTargetData::render(float /*frametime*/)
!(Iff_info[target_shipp->team].flags & IFFF_ORDERS_HIDDEN)))
&& Ship_info[target_shipp->ship_info_index].is_flyable()) {
extra_data_shown = 1;
auto orders = ship_return_orders(target_shipp);
if (!orders.empty()) {
char outstr[256];
strcpy_s(outstr, orders.c_str());
if (ship_return_orders(outstr, target_shipp)) {
font::force_fit_string(outstr, 255, order_max_w);
orders = outstr;
has_orders = 1;
} else {
orders = XSTR("no orders", 337);
strcpy_s(outstr, XSTR("no orders", 337));
}
renderString(position[0] + order_offsets[0], position[1] + order_offsets[1], EG_TBOX_EXTRA1, orders.c_str());
renderString(position[0] + order_offsets[0], position[1] + order_offsets[1], EG_TBOX_EXTRA1, outstr);
}
if ( has_orders ) {
char outstr[256];
strcpy_s(outstr, XSTR( "time to: ", 338));
if ( ship_return_time_to_goal(tmpbuf, target_shipp) ) {
strcat_s(outstr, tmpbuf);
@@ -1476,11 +1471,10 @@ void HudGaugeExtraTargetData::render(float /*frametime*/)
// count the objects directly docked to me
int dock_count = dock_count_direct_docked_objects(target_objp);
char outstr[256];
// docked to only one object
if (dock_count == 1)
{
sprintf(outstr, XSTR("Docked: %s", 339), Ships[dock_get_first_docked_object(target_objp)->instance].get_display_string());
sprintf(outstr, XSTR("Docked: %s", 339), Ships[dock_get_first_docked_object(target_objp)->instance].ship_name);
end_string_at_first_hash_symbol(outstr);
}
// docked to multiple objects
@@ -2046,10 +2040,10 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
float dot, dist;
vec3d v2t;
if (aip->target_objnum == OBJ_INDEX(Player_obj))
if (aip->target_objnum == Player_obj-Objects)
strcpy_s(target_str, "Player!");
else
sprintf(target_str, "%s", Ships[Objects[aip->target_objnum].instance].get_display_string());
sprintf(target_str, "%s", Ships[Objects[aip->target_objnum].instance].ship_name);
gr_printf_no_resize(sx, sy, "Targ: %s", target_str);
sy += dy;
@@ -2097,14 +2091,14 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
eshipp = &Ships[Enemy_attacker->instance];
eaip = &Ai_info[eshipp->ai_index];
if (eaip->target_objnum == OBJ_INDEX(Player_obj)) {
if (eaip->target_objnum == Player_obj-Objects) {
found = 1;
dist = vm_vec_dist_quick(&Enemy_attacker->pos, &Player_obj->pos);
vm_vec_normalized_dir(&v2t,&Objects[eaip->target_objnum].pos, &Enemy_attacker->pos);
dot = vm_vec_dot(&v2t, &Enemy_attacker->orient.vec.fvec);
gr_printf_no_resize(sx, sy, "#%i: %s", OBJ_INDEX(Enemy_attacker), Ships[Enemy_attacker->instance].get_display_string());
gr_printf_no_resize(sx, sy, "#%i: %s", OBJ_INDEX(Enemy_attacker), Ships[Enemy_attacker->instance].ship_name);
sy += dy;
gr_printf_no_resize(sx, sy, "Targ dist: %5.1f", dist);
sy += dy;
@@ -2164,7 +2158,7 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
for ( i = 0; i < swp->num_primary_banks; i++ ) {
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->primary_bank_weapons[i]].get_display_string());
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->primary_bank_weapons[i]].name);
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
}
@@ -2174,7 +2168,7 @@ void HudGaugeTargetBox::showTargetData(float /*frametime*/)
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
for ( i = 0; i < swp->num_secondary_banks; i++ ) {
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->secondary_bank_weapons[i]].get_display_string());
sprintf(outstr,"%d. %s", i+1, Weapon_info[swp->secondary_bank_weapons[i]].name);
gr_printf_no_resize(sx,sy,"%s", outstr);
sy += dy;
}
@@ -2228,13 +2222,13 @@ void hud_update_target_static()
}
if ( Target_static_playing ) {
if (!Target_static_looping.isValid()) {
if ( Target_static_looping == -1 ) {
Target_static_looping = snd_play_looping(gamesnd_get_game_sound(GameSounds::STATIC));
}
} else {
if (Target_static_looping.isValid()) {
if ( Target_static_looping != -1 ) {
snd_stop(Target_static_looping);
Target_static_looping = sound_handle::invalid();
Target_static_looping = -1;
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ class object;
#define TBOX_FLASH_STATUS 3
#define TBOX_FLASH_SUBSYS 4
extern sound_handle Target_static_looping;
extern int Target_static_looping;
extern int Target_display_cargo;
extern char Cargo_string[256];
+15 -12
View File
@@ -140,7 +140,7 @@ size_t factor_table::getNext(size_t n, size_t current)
}
}
UNREACHABLE("For some reason, factor_table::getNext() was unable to locate the current factor. This should never happen; get a coder!\n");
Assertion(false, "For some reason, factor_table::getNext() was unable to locate the current factor. This should never happen; get a coder!\n");
return 1;
}
@@ -211,6 +211,7 @@ static struct Cheat cheatsTable[] = {
int Tool_enabled = 0;
bool Perspective_locked=false;
bool quit_mission_popup_shown = false;
extern int AI_watch_object;
extern int Countermeasures_enabled;
@@ -896,7 +897,7 @@ void process_debug_keys(int k)
object *objp = &Objects[Player_ai->target_objnum];
objp->flags.toggle(Object::Object_Flags::Invulnerable);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Player's target [%s] is %s", 13), Ships[objp->instance].get_display_string(), objp->flags[Object::Object_Flags::Invulnerable] ? XSTR( "now INVULNERABLE!", 11) : XSTR( "no longer invulnerable...", 12));
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Player's target [%s] is %s", 13), Ships[objp->instance].ship_name, objp->flags[Object::Object_Flags::Invulnerable] ? XSTR( "now INVULNERABLE!", 11) : XSTR( "no longer invulnerable...", 12));
}
break;
@@ -976,7 +977,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank];
*weap = get_next_weapon_looped(*weap, WP_MISSILE);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].get_display_string());
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].name);
break;
}
@@ -989,7 +990,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.secondary_bank_weapons[shipp->weapons.current_secondary_bank];
*weap = get_prev_weapon_looped(*weap, WP_MISSILE);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].get_display_string());
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Secondary Weapon forced to %s", 18), Weapon_info[*weap].name);
break;
}
@@ -1018,7 +1019,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank];
*weap = get_next_weapon_looped(*weap, WP_LASER);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].get_display_string());
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].name);
break;
}
@@ -1030,7 +1031,7 @@ void process_debug_keys(int k)
int *weap = &shipp->weapons.primary_bank_weapons[shipp->weapons.current_primary_bank];
*weap = get_prev_weapon_looped(*weap, WP_LASER);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].get_display_string());
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Primary Weapon forced to %s", 19), Weapon_info[*weap].name);
break;
}
@@ -1066,12 +1067,12 @@ void process_debug_keys(int k)
if (is_support_allowed(obj_to_rearm))
{
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Issuing rearm request for %s", 1610), Ships[obj_to_rearm->instance].get_display_string());
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Issuing rearm request for %s", -1), Ships[obj_to_rearm->instance].ship_name);
ai_issue_rearm_request(obj_to_rearm);
}
else
{
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Cannot issue rearm request for %s", 1611), Ships[obj_to_rearm->instance].get_display_string());
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR("Cannot issue rearm request for %s", -1), Ships[obj_to_rearm->instance].ship_name);
}
break;
@@ -1325,7 +1326,7 @@ void ppsk_hotkeys(int k)
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "No target to add/remove from set %d.", 26), hotkey_set+1);
else {
hud_target_hotkey_add_remove( hotkey_set, &Objects[Player_ai->target_objnum], HOTKEY_USER_ADDED);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "%s added to set %d. (F%d)", 27), Ships[Objects[Player_ai->target_objnum].instance].get_display_string(), hotkey_set, 4+hotkey_set+1);
HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "%s added to set %d. (F%d)", 27), Ships[Objects[Player_ai->target_objnum].instance].ship_name, hotkey_set, 4+hotkey_set+1);
}
break;
@@ -1441,6 +1442,8 @@ void game_do_end_mission_popup()
game_stop_looped_sounds();
snd_stop_all();
quit_mission_popup_shown = true;
pf_flags = PF_BODY_BIG | PF_USE_AFFIRMATIVE_ICON | PF_USE_NEGATIVE_ICON;
choice = popup(pf_flags, 3, POPUP_NO, XSTR( "&Yes, Quit", 28), XSTR( "Yes, &Restart", 29), XSTR( "Do you really want to end the mission?", 30));
@@ -1456,6 +1459,7 @@ void game_do_end_mission_popup()
default:
break; // do nothing
}
quit_mission_popup_shown = false;
game_start_time();
game_flush();
@@ -1569,7 +1573,6 @@ void game_process_cheats(int k)
ship *shipp = &Ships[Objects[objnum].instance];
shipp->ship_name[0] = '\0';
shipp->display_name.clear();
shipp->orders_accepted = (1<<NUM_COMM_ORDER_ITEMS)-1;
// Goober5000 - stolen from support ship creation
@@ -2424,10 +2427,10 @@ int button_function(int n)
HUD_printf("%s", XSTR("Engine failure. Cannot engage subspace drive.", 40));
} else if (!ship_navigation_ok_to_warp(Player_ship)) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
HUD_printf("%s", XSTR("Navigation failure. Cannot engage subspace drive.", 1572));
HUD_printf("%s", XSTR("Navigation failure. Cannot engage subspace drive.", 1596));
} else if ( (Player_obj != NULL) && object_get_gliding(Player_obj)) {
gamesnd_play_iface(InterfaceSounds::GENERAL_FAIL);
HUD_printf("%s", XSTR("Cannot engage subspace drive while gliding.", 1573));
HUD_printf("%s", XSTR("Cannot engage subspace drive while gliding.", 1597));
} else {
gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_START );
}
+2
View File
@@ -23,6 +23,8 @@ extern bool Perspective_locked;
extern int Ignored_keys[];
extern bool quit_mission_popup_shown;
typedef struct button_info
{
int status[NUM_BUTTON_FIELDS];
+11 -30
View File
@@ -920,7 +920,7 @@ void labviewer_update_variables_window()
Assert(Lab_selected_index < Num_weapon_types);
weapon_info *wip = &Weapon_info[Lab_selected_index];
VAR_SET_VALUE(wip->get_display_string());
VAR_SET_VALUE(wip->name);
VAR_SET_VALUE_SAVE(wip->subtype, Num_weapon_subtypes - 1);
VAR_SET_VALUE_SAVE(wip->mass, 0);
@@ -1257,7 +1257,7 @@ void labviewer_update_desc_window()
}
}
else if (Lab_mode == LAB_MODE_WEAPON) {
Lab_description_window->SetCaption(Weapon_info[Lab_selected_index].get_display_string());
Lab_description_window->SetCaption(Weapon_info[Lab_selected_index].name);
if (Weapon_info[Lab_selected_index].tech_desc != NULL) {
Lab_description_text->SetText(Weapon_info[Lab_selected_index].tech_desc);
@@ -1543,7 +1543,7 @@ void labviewer_make_weap_window(Button* /*caller*/)
stip = type_nodes[Weapon_info[i].subtype];
}
cmp->AddItem(stip, Weapon_info[i].get_display_string(), i, false, labviewer_change_weapon);
cmp->AddItem(stip, Weapon_info[i].name, i, false, labviewer_change_weapon);
//if (Weapon_info[i].tech_model[0] != '\0') {
// cmp->AddItem(cwip, "Tech Model", 0, false, labviewer_show_tech_model);
@@ -1599,7 +1599,7 @@ char envmap_name[MAX_FILENAME_LEN];
const char* mission_ext_list[] = { ".fs2" };
SCP_string get_directory_or_vp(const char* path)
SCP_string get_directory_or_vp(char* path)
{
SCP_string result(path);
@@ -1806,7 +1806,6 @@ void labviewer_change_background_actual()
else {
// (DahBlount) - This spot should be used to disable rendering features that only apply to missions.
Motion_debris_override = true;
Num_stars = 0;
}
}
@@ -1833,15 +1832,14 @@ void labviewer_make_background_window(Button* /*caller*/)
cf_get_file_list(missions, CF_TYPE_MISSIONS, NOX("*.fs2"));
SCP_map<SCP_string, SCP_vector<SCP_string>> directories;
char fullpath[MAX_PATH_LEN];
for (const auto& filename : missions) {
auto res = cf_find_file_location((filename + ".fs2").c_str(), CF_TYPE_MISSIONS);
for (const auto& filename : missions)
{
cf_find_file_location((filename + ".fs2").c_str(), CF_TYPE_MISSIONS, sizeof(fullpath) - 1, fullpath, NULL, NULL);
auto location = get_directory_or_vp(fullpath);
if (res.found) {
auto location = get_directory_or_vp(res.full_name.c_str());
directories[location].push_back(filename);
}
directories[location].push_back(filename);
}
Num_mission_directories = directories.size();
@@ -1926,10 +1924,6 @@ void lab_init()
Lab_viewer_flags |= LAB_FLAG_NO_ROTATION;
Lab_viewer_flags |= LAB_FLAG_INITIAL_ROTATION;
obj_init();
//Reset the background
labviewer_change_background_actual();
flagset<Object::Object_Flags> obs_flags;
auto obj_index = obj_create(OBJ_OBSERVER, -1, 0, &vmd_identity_matrix, &vmd_zero_vector, 0, obs_flags);
@@ -1947,19 +1941,6 @@ void lab_init()
if (The_mission.ai_profile == nullptr)
The_mission.ai_profile = &Ai_profiles[Default_ai_profile];
lab_cam_distance = 100.0f;
lab_cam_phi = 1.24f;
lab_cam_theta = 2.25f;
Lab_selected_index = -1;
Lab_last_selected_ship = -1;
Lab_selected_object = -1;
Lab_last_selected_weapon = -1;
Lab_model_num = -1;
Lab_selected_mission = "None";
Lab_skybox_orientation = vmd_identity_matrix;
}
#include "controlconfig/controlsconfig.h"
@@ -2193,5 +2174,5 @@ void lab_close()
cam_delete(Lab_cam);
obj_init();
Missiontime = Lab_Save_Missiontime;
}
-254
View File
@@ -1,254 +0,0 @@
#include "discord.h"
#include "freespace.h"
#include "events/events.h"
#include "gamesequence/gamesequence.h"
#include "io/timer.h"
#include "mission/missioncampaign.h"
#include "mission/missionparse.h"
#include "parse/parselo.h"
#include "playerman/player.h"
#include "discord_rpc.h"
namespace {
struct PresenceInfo {
SCP_string state;
int64_t timestamp;
};
bool initialized = false;
bool discord_ready = false;
int next_mission_update = -1;
bool in_mission = false;
PresenceInfo current_info;
const char* APPLICATION_ID = "465270111440470016";
SCP_unordered_map<SCP_string, SCP_string> campaign_name_cache;
SCP_string get_campaign_name(const char* filename)
{
SCP_string name = filename;
auto iter = campaign_name_cache.find(name);
if (iter != campaign_name_cache.end()) {
return iter->second;
}
auto campaign_name = mission_campaign_get_name(filename);
campaign_name_cache[name] = campaign_name;
return campaign_name;
}
SCP_string get_current_campaign_name()
{
if (Game_mode & GM_CAMPAIGN_MODE) {
return Campaign.name;
} else if (Player != nullptr) {
return get_campaign_name(Player->current_campaign);
} else {
return "";
}
}
SCP_string get_details()
{
SCP_string res;
auto has_campaign = Player != nullptr && strlen(Player->current_campaign) > 0;
if (in_mission && !(Game_mode & GM_CAMPAIGN_MODE)) {
// This is a standalone mission so we don't actually have a campaign
has_campaign = false;
}
if (has_campaign && in_mission) {
sprintf(res, "%s: %s", get_current_campaign_name().c_str(), The_mission.name);
} else if (has_campaign) {
sprintf(res, "Campaign %s", get_current_campaign_name().c_str());
} else if (in_mission) {
res = The_mission.name;
} else {
res = "In game";
}
return res;
}
void update_presence() {
auto details = get_details();
DiscordRichPresence presence;
memset(&presence, 0, sizeof(presence));
presence.details = details.c_str();
presence.state = current_info.state.c_str();
presence.startTimestamp = current_info.timestamp;
Discord_UpdatePresence(&presence);
}
void set_presence(const SCP_string& state, int64_t timestamp = 0) {
if (current_info.state == state && current_info.timestamp == timestamp) {
// No changes
return;
}
current_info.state = state;
current_info.timestamp = timestamp;
if (discord_ready) {
update_presence();
}
}
void set_game_play_presence()
{
SCP_string state;
sprintf(state, "In mission (%d %s)", Player->stats.m_kill_count_ok,
Player->stats.m_kill_count_ok == 1 ? "kill" : "kills");
set_presence(state, (int64_t)time(nullptr) - f2i(Missiontime));
// Update this every 20 seconds since Discord already has a 15 second rate-limit
// This will update the "elapsed" time even if time compression is active but the clock will jump forward
next_mission_update = timestamp(20000);
}
void update_discord()
{
if (!initialized)
return;
Discord_RunCallbacks();
if (gameseq_get_state() == GS_STATE_GAME_PLAY && timestamp_elapsed(next_mission_update)) {
set_game_play_presence();
}
}
void shutdown_discord()
{
if (!initialized)
return;
Discord_Shutdown();
initialized = false;
discord_ready = false;
}
void handleEnterState(int old_state, int new_state)
{
if (old_state == new_state) {
return;
}
if (new_state == GS_STATE_GAME_PLAY) {
// Update immediately if we enter the game play state again
set_game_play_presence();
return;
}
if (gameseq_get_state_idx(GS_STATE_GAME_PLAY) >= 0) {
// Special case for when we come out of game play
switch (new_state) {
case GS_STATE_OPTIONS_MENU:
case GS_STATE_HOTKEY_SCREEN:
case GS_STATE_GAMEPLAY_HELP:
case GS_STATE_MISSION_LOG_SCROLLBACK:
set_presence("In game menu");
return;
default:
break;
}
}
switch (new_state) {
case GS_STATE_MAIN_MENU:
set_presence("In Mainhall");
break;
case GS_STATE_BRIEFING:
set_presence("In mission briefing");
break;
case GS_STATE_CMD_BRIEF:
set_presence("In command briefing");
break;
case GS_EVENT_DEBRIEF:
set_presence("In debriefing");
break;
case GS_STATE_GAME_PAUSED:
set_presence("Paused");
break;
case GS_STATE_RED_ALERT:
set_presence("Red alert briefing");
break;
case GS_STATE_INITIAL_PLAYER_SELECT:
set_presence("Selecting player");
break;
case GS_STATE_FICTION_VIEWER:
set_presence("In fiction viewer");
break;
default:
break;
}
}
void handleLeaveState(int old_state, int /*new_state*/)
{
if (old_state == GS_STATE_GAME_PAUSED) {
// Reset the game play state immediately
set_game_play_presence();
}
if (old_state == GS_STATE_GAME_PLAY) {
in_mission = false;
next_mission_update = -1;
}
}
void handleMissionLoad(const char* /*filename*/)
{
set_presence("Loading mission");
in_mission = true;
}
} // namespace
namespace libs {
namespace discord {
void init()
{
Assertion(!initialized, "Discord integration can only be initialized once!");
DiscordEventHandlers handlers;
memset(&handlers, 0, sizeof(handlers));
handlers.ready = [](const DiscordUser* connectedUser) {
mprintf(("Discord: connected to user %s#%s - %s\n", connectedUser->username, connectedUser->discriminator,
connectedUser->userId));
discord_ready = true;
update_presence();
};
handlers.errored = [](int errcode, const char* message) {
mprintf(("Discord: error (%d: %s)\n", errcode, message));
discord_ready = false;
};
handlers.disconnected = [](int errcode, const char* message) {
mprintf(("Discord: disconnected (%d: %s)\n", errcode, message));
discord_ready = false;
};
Discord_Initialize(APPLICATION_ID, &handlers, 0, nullptr);
events::EngineUpdate.add(update_discord);
events::EngineShutdown.add(shutdown_discord);
events::GameEnterState.add(handleEnterState);
events::GameLeaveState.add(handleLeaveState);
events::GameMissionLoad.add(handleMissionLoad);
initialized = true;
}
} // namespace discord
} // namespace libs
-8
View File
@@ -1,8 +0,0 @@
#pragma once
namespace libs {
namespace discord {
void init();
}
} // namespace libs
-3
View File
@@ -55,10 +55,7 @@ void initialize() {
return;
}
// This is deprecated since 58.9.100 and not needed anymore
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 9, 100)
av_register_all();
#endif
check_version("libavcodec", avcodec_version(), LIBAVCODEC_VERSION_INT);
check_version("libavformat", avformat_version(), LIBAVFORMAT_VERSION_INT);
-83
View File
@@ -1,83 +0,0 @@
#include "renderdoc.h"
#include "renderdoc_app.h"
#include "globalincs/pstypes.h"
#ifdef SCP_UNIX
#include <dlfcn.h>
#endif
namespace {
bool api_loaded = false;
RENDERDOC_API_1_1_1* api = nullptr;
pRENDERDOC_GetAPI load_getAPI() {
#ifdef SCP_UNIX
auto handle = dlopen("librenderdoc.so", RTLD_NOLOAD);
auto symbol = dlsym(handle, "RENDERDOC_GetAPI");
if (handle != nullptr) {
dlclose(handle);
}
return (pRENDERDOC_GetAPI)symbol;
#else
// Renderdoc API loading is not implemented for this platform yet!
return nullptr;
#endif
}
}
namespace renderdoc {
bool loadApi() {
if (api_loaded) {
return true;
}
auto getAPI = load_getAPI();
if (getAPI == nullptr) {
return false;
}
auto res = getAPI(eRENDERDOC_API_Version_1_1_1, reinterpret_cast<void**>(&api));
if (res != 1) {
return false;
}
api_loaded = true;
return true;
}
void triggerCapture() {
if (!api_loaded) {
// Do nothing if API is not available
return;
}
api->TriggerCapture();
}
void startCapture() {
if (api_loaded) {
api->StartFrameCapture(nullptr, nullptr);
}
}
bool isCapturing() {
if (api_loaded) {
return api->IsFrameCapturing() == 1;
}
return false;
}
void endCapture() {
if (api_loaded) {
api->EndFrameCapture(nullptr, nullptr);
}
}
}
-15
View File
@@ -1,15 +0,0 @@
#pragma once
namespace renderdoc {
bool loadApi();
void triggerCapture();
void startCapture();
bool isCapturing();
void endCapture();
}
-617
View File
@@ -1,617 +0,0 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2015-2017 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#pragma once
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Documentation for the API is available at https://renderdoc.org/docs/in_application_api.html
//
#if !defined(RENDERDOC_NO_STDINT)
#include <cstdint>
#endif
#if defined(WIN32)
#define RENDERDOC_CC __cdecl
#elif defined(__linux__)
#define RENDERDOC_CC
#elif defined(__APPLE__)
#define RENDERDOC_CC
#else
#error "Unknown platform"
#endif
#ifdef __cplusplus
extern "C" {
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////
// Constants not used directly in below API
// This is a GUID/magic value used for when applications pass a path where shader debug
// information can be found to match up with a stripped shader.
// the define can be used like so: const GUID RENDERDOC_ShaderDebugMagicValue =
// RENDERDOC_ShaderDebugMagicValue_value
#define RENDERDOC_ShaderDebugMagicValue_struct \
{ \
0xeab25520, 0x6670, 0x4865, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \
}
// as an alternative when you want a byte array (assuming x86 endianness):
#define RENDERDOC_ShaderDebugMagicValue_bytearray \
{ \
0x20, 0x55, 0xb2, 0xea, 0x70, 0x66, 0x65, 0x48, 0x84, 0x29, 0x6c, 0x8, 0x51, 0x54, 0x00, 0xff \
}
// truncated version when only a uint64_t is available (e.g. Vulkan tags):
#define RENDERDOC_ShaderDebugMagicValue_truncated 0x48656670eab25520ULL
//////////////////////////////////////////////////////////////////////////////////////////////////
// RenderDoc capture options
//
typedef enum {
// Allow the application to enable vsync
//
// Default - enabled
//
// 1 - The application can enable or disable vsync at will
// 0 - vsync is force disabled
eRENDERDOC_Option_AllowVSync = 0,
// Allow the application to enable fullscreen
//
// Default - enabled
//
// 1 - The application can enable or disable fullscreen at will
// 0 - fullscreen is force disabled
eRENDERDOC_Option_AllowFullscreen = 1,
// Record API debugging events and messages
//
// Default - disabled
//
// 1 - Enable built-in API debugging features and records the results into
// the capture logfile, which is matched up with events on replay
// 0 - no API debugging is forcibly enabled
eRENDERDOC_Option_APIValidation = 2,
eRENDERDOC_Option_DebugDeviceMode = 2, // deprecated name of this enum
// Capture CPU callstacks for API events
//
// Default - disabled
//
// 1 - Enables capturing of callstacks
// 0 - no callstacks are captured
eRENDERDOC_Option_CaptureCallstacks = 3,
// When capturing CPU callstacks, only capture them from drawcalls.
// This option does nothing without the above option being enabled
//
// Default - disabled
//
// 1 - Only captures callstacks for drawcall type API events.
// Ignored if CaptureCallstacks is disabled
// 0 - Callstacks, if enabled, are captured for every event.
eRENDERDOC_Option_CaptureCallstacksOnlyDraws = 4,
// Specify a delay in seconds to wait for a debugger to attach, after
// creating or injecting into a process, before continuing to allow it to run.
//
// 0 indicates no delay, and the process will run immediately after injection
//
// Default - 0 seconds
//
eRENDERDOC_Option_DelayForDebugger = 5,
// Verify any writes to mapped buffers, by checking the memory after the
// bounds of the returned pointer to detect any modification.
//
// Default - disabled
//
// 1 - Verify any writes to mapped buffers
// 0 - No verification is performed, and overwriting bounds may cause
// crashes or corruption in RenderDoc
eRENDERDOC_Option_VerifyMapWrites = 6,
// Hooks any system API calls that create child processes, and injects
// RenderDoc into them recursively with the same options.
//
// Default - disabled
//
// 1 - Hooks into spawned child processes
// 0 - Child processes are not hooked by RenderDoc
eRENDERDOC_Option_HookIntoChildren = 7,
// By default RenderDoc only includes resources in the final logfile necessary
// for that frame, this allows you to override that behaviour.
//
// Default - disabled
//
// 1 - all live resources at the time of capture are included in the log
// and available for inspection
// 0 - only the resources referenced by the captured frame are included
eRENDERDOC_Option_RefAllResources = 8,
// By default RenderDoc skips saving initial states for resources where the
// previous contents don't appear to be used, assuming that writes before
// reads indicate previous contents aren't used.
//
// Default - disabled
//
// 1 - initial contents at the start of each captured frame are saved, even if
// they are later overwritten or cleared before being used.
// 0 - unless a read is detected, initial contents will not be saved and will
// appear as black or empty data.
eRENDERDOC_Option_SaveAllInitials = 9,
// In APIs that allow for the recording of command lists to be replayed later,
// RenderDoc may choose to not capture command lists before a frame capture is
// triggered, to reduce overheads. This means any command lists recorded once
// and replayed many times will not be available and may cause a failure to
// capture.
//
// Note this is only true for APIs where multithreading is difficult or
// discouraged. Newer APIs like Vulkan and D3D12 will ignore this option
// and always capture all command lists since the API is heavily oriented
// around it and the overheads have been reduced by API design.
//
// 1 - All command lists are captured from the start of the application
// 0 - Command lists are only captured if their recording begins during
// the period when a frame capture is in progress.
eRENDERDOC_Option_CaptureAllCmdLists = 10,
// Mute API debugging output when the API validation mode option is enabled
//
// Default - enabled
//
// 1 - Mute any API debug messages from being displayed or passed through
// 0 - API debugging is displayed as normal
eRENDERDOC_Option_DebugOutputMute = 11,
} RENDERDOC_CaptureOption;
// Sets an option that controls how RenderDoc behaves on capture.
//
// Returns 1 if the option and value are valid
// Returns 0 if either is invalid and the option is unchanged
typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionU32)(RENDERDOC_CaptureOption opt, uint32_t val);
typedef int(RENDERDOC_CC *pRENDERDOC_SetCaptureOptionF32)(RENDERDOC_CaptureOption opt, float val);
// Gets the current value of an option as a uint32_t
//
// If the option is invalid, 0xffffffff is returned
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionU32)(RENDERDOC_CaptureOption opt);
// Gets the current value of an option as a float
//
// If the option is invalid, -FLT_MAX is returned
typedef float(RENDERDOC_CC *pRENDERDOC_GetCaptureOptionF32)(RENDERDOC_CaptureOption opt);
typedef enum {
// '0' - '9' matches ASCII values
eRENDERDOC_Key_0 = 0x30,
eRENDERDOC_Key_1 = 0x31,
eRENDERDOC_Key_2 = 0x32,
eRENDERDOC_Key_3 = 0x33,
eRENDERDOC_Key_4 = 0x34,
eRENDERDOC_Key_5 = 0x35,
eRENDERDOC_Key_6 = 0x36,
eRENDERDOC_Key_7 = 0x37,
eRENDERDOC_Key_8 = 0x38,
eRENDERDOC_Key_9 = 0x39,
// 'A' - 'Z' matches ASCII values
eRENDERDOC_Key_A = 0x41,
eRENDERDOC_Key_B = 0x42,
eRENDERDOC_Key_C = 0x43,
eRENDERDOC_Key_D = 0x44,
eRENDERDOC_Key_E = 0x45,
eRENDERDOC_Key_F = 0x46,
eRENDERDOC_Key_G = 0x47,
eRENDERDOC_Key_H = 0x48,
eRENDERDOC_Key_I = 0x49,
eRENDERDOC_Key_J = 0x4A,
eRENDERDOC_Key_K = 0x4B,
eRENDERDOC_Key_L = 0x4C,
eRENDERDOC_Key_M = 0x4D,
eRENDERDOC_Key_N = 0x4E,
eRENDERDOC_Key_O = 0x4F,
eRENDERDOC_Key_P = 0x50,
eRENDERDOC_Key_Q = 0x51,
eRENDERDOC_Key_R = 0x52,
eRENDERDOC_Key_S = 0x53,
eRENDERDOC_Key_T = 0x54,
eRENDERDOC_Key_U = 0x55,
eRENDERDOC_Key_V = 0x56,
eRENDERDOC_Key_W = 0x57,
eRENDERDOC_Key_X = 0x58,
eRENDERDOC_Key_Y = 0x59,
eRENDERDOC_Key_Z = 0x5A,
// leave the rest of the ASCII range free
// in case we want to use it later
eRENDERDOC_Key_NonPrintable = 0x100,
eRENDERDOC_Key_Divide,
eRENDERDOC_Key_Multiply,
eRENDERDOC_Key_Subtract,
eRENDERDOC_Key_Plus,
eRENDERDOC_Key_F1,
eRENDERDOC_Key_F2,
eRENDERDOC_Key_F3,
eRENDERDOC_Key_F4,
eRENDERDOC_Key_F5,
eRENDERDOC_Key_F6,
eRENDERDOC_Key_F7,
eRENDERDOC_Key_F8,
eRENDERDOC_Key_F9,
eRENDERDOC_Key_F10,
eRENDERDOC_Key_F11,
eRENDERDOC_Key_F12,
eRENDERDOC_Key_Home,
eRENDERDOC_Key_End,
eRENDERDOC_Key_Insert,
eRENDERDOC_Key_Delete,
eRENDERDOC_Key_PageUp,
eRENDERDOC_Key_PageDn,
eRENDERDOC_Key_Backspace,
eRENDERDOC_Key_Tab,
eRENDERDOC_Key_PrtScrn,
eRENDERDOC_Key_Pause,
eRENDERDOC_Key_Max,
} RENDERDOC_InputButton;
// Sets which key or keys can be used to toggle focus between multiple windows
//
// If keys is NULL or num is 0, toggle keys will be disabled
typedef void(RENDERDOC_CC *pRENDERDOC_SetFocusToggleKeys)(RENDERDOC_InputButton *keys, int num);
// Sets which key or keys can be used to capture the next frame
//
// If keys is NULL or num is 0, captures keys will be disabled
typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureKeys)(RENDERDOC_InputButton *keys, int num);
typedef enum {
// This single bit controls whether the overlay is enabled or disabled globally
eRENDERDOC_Overlay_Enabled = 0x1,
// Show the average framerate over several seconds as well as min/max
eRENDERDOC_Overlay_FrameRate = 0x2,
// Show the current frame number
eRENDERDOC_Overlay_FrameNumber = 0x4,
// Show a list of recent captures, and how many captures have been made
eRENDERDOC_Overlay_CaptureList = 0x8,
// Default values for the overlay mask
eRENDERDOC_Overlay_Default = (eRENDERDOC_Overlay_Enabled | eRENDERDOC_Overlay_FrameRate |
eRENDERDOC_Overlay_FrameNumber | eRENDERDOC_Overlay_CaptureList),
// Enable all bits
eRENDERDOC_Overlay_All = ~0U,
// Disable all bits
eRENDERDOC_Overlay_None = 0,
} RENDERDOC_OverlayBits;
// returns the overlay bits that have been set
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetOverlayBits)();
// sets the overlay bits with an and & or mask
typedef void(RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or);
// this function will attempt to shut down RenderDoc.
//
// Note: that this will only work correctly if done immediately after
// the dll is loaded, before any API work happens. RenderDoc will remove its
// injected hooks and shut down. Behaviour is undefined if this is called
// after any API functions have been called.
typedef void(RENDERDOC_CC *pRENDERDOC_Shutdown)();
// This function will unload RenderDoc's crash handler.
//
// If you use your own crash handler and don't want RenderDoc's handler to
// intercede, you can call this function to unload it and any unhandled
// exceptions will pass to the next handler.
typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)();
// Sets the logfile path template
//
// logfile is a UTF-8 string that gives a template for how captures will be named
// and where they will be saved.
//
// Any extension is stripped off the path, and captures are saved in the directory
// specified, and named with the filename and the frame number appended. If the
// directory does not exist it will be created, including any parent directories.
//
// If pathtemplate is NULL, the template will remain unchanged
//
// Example:
//
// SetLogFilePathTemplate("my_captures/example");
//
// Capture #1 -> my_captures/example_frame123.rdc
// Capture #2 -> my_captures/example_frame456.rdc
typedef void(RENDERDOC_CC *pRENDERDOC_SetLogFilePathTemplate)(const char *pathtemplate);
// returns the current logfile template, see SetLogFileTemplate above, as a UTF-8 string
typedef const char *(RENDERDOC_CC *pRENDERDOC_GetLogFilePathTemplate)();
// returns the number of captures that have been made
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetNumCaptures)();
// This function returns the details of a capture, by index. New captures are added
// to the end of the list.
//
// logfile will be filled with the absolute path to the capture file, as a UTF-8 string
// pathlength will be written with the length in bytes of the logfile string
// timestamp will be written with the time of the capture, in seconds since the Unix epoch
//
// Any of the parameters can be NULL and they'll be skipped.
//
// The function will return 1 if the capture index is valid, or 0 if the index is invalid
// If the index is invalid, the values will be unchanged
//
// Note: when captures are deleted in the UI they will remain in this list, so the
// logfile path may not exist anymore.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetCapture)(uint32_t idx, char *logfile,
uint32_t *pathlength, uint64_t *timestamp);
// returns 1 if the RenderDoc UI is connected to this application, 0 otherwise
// This was renamed to IsTargetControlConnected in API 1.1.1, the old typedef is kept here for
// backwards compatibility with old code, it is castable either way since it's ABI compatible
// as the same function pointer type.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsRemoteAccessConnected)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsTargetControlConnected)();
// This function will launch the Replay UI associated with the RenderDoc library injected
// into the running application.
//
// if connectTargetControl is 1, the Replay UI will be launched with a command line parameter
// to connect to this application
// cmdline is the rest of the command line, as a UTF-8 string. E.g. a captures to open
// if cmdline is NULL, the command line will be empty.
//
// returns the PID of the replay UI if successful, 0 if not successful.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_LaunchReplayUI)(uint32_t connectTargetControl,
const char *cmdline);
// RenderDoc can return a higher version than requested if it's backwards compatible,
// this function returns the actual version returned. If a parameter is NULL, it will be
// ignored and the others will be filled out.
typedef void(RENDERDOC_CC *pRENDERDOC_GetAPIVersion)(int *major, int *minor, int *patch);
//////////////////////////////////////////////////////////////////////////
// Capturing functions
//
// A device pointer is a pointer to the API's root handle.
//
// This would be an ID3D11Device, HGLRC/GLXContext, ID3D12Device, etc
typedef void *RENDERDOC_DevicePointer;
// A window handle is the OS's native window handle
//
// This would be an HWND, GLXDrawable, etc
typedef void *RENDERDOC_WindowHandle;
// This sets the RenderDoc in-app overlay in the API/window pair as 'active' and it will
// respond to keypresses. Neither parameter can be NULL
typedef void(RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(RENDERDOC_DevicePointer device,
RENDERDOC_WindowHandle wndHandle);
// capture the next frame on whichever window and API is currently considered active
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerCapture)();
// capture the next N frames on whichever window and API is currently considered active
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerMultiFrameCapture)(uint32_t numFrames);
// When choosing either a device pointer or a window handle to capture, you can pass NULL.
// Passing NULL specifies a 'wildcard' match against anything. This allows you to specify
// any API rendering to a specific window, or a specific API instance rendering to any window,
// or in the simplest case of one window and one API, you can just pass NULL for both.
//
// In either case, if there are two or more possible matching (device,window) pairs it
// is undefined which one will be captured.
//
// Note: for headless rendering you can pass NULL for the window handle and either specify
// a device pointer or leave it NULL as above.
// Immediately starts capturing API calls on the specified device pointer and window handle.
//
// If there is no matching thing to capture (e.g. no supported API has been initialised),
// this will do nothing.
//
// The results are undefined (including crashes) if two captures are started overlapping,
// even on separate devices and/oror windows.
typedef void(RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(RENDERDOC_DevicePointer device,
RENDERDOC_WindowHandle wndHandle);
// Returns whether or not a frame capture is currently ongoing anywhere.
//
// This will return 1 if a capture is ongoing, and 0 if there is no capture running
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)();
// Ends capturing immediately.
//
// This will return 1 if the capture succeeded, and 0 if there was an error capturing.
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_EndFrameCapture)(RENDERDOC_DevicePointer device,
RENDERDOC_WindowHandle wndHandle);
//////////////////////////////////////////////////////////////////////////////////////////////////
// RenderDoc API versions
//
// RenderDoc uses semantic versioning (http://semver.org/).
//
// MAJOR version is incremented when incompatible API changes happen.
// MINOR version is incremented when functionality is added in a backwards-compatible manner.
// PATCH version is incremented when backwards-compatible bug fixes happen.
//
// Note that this means the API returned can be higher than the one you might have requested.
// e.g. if you are running against a newer RenderDoc that supports 1.0.1, it will be returned
// instead of 1.0.0. You can check this with the GetAPIVersion entry point
typedef enum {
eRENDERDOC_API_Version_1_0_0 = 10000, // RENDERDOC_API_1_0_0 = 1 00 00
eRENDERDOC_API_Version_1_0_1 = 10001, // RENDERDOC_API_1_0_1 = 1 00 01
eRENDERDOC_API_Version_1_0_2 = 10002, // RENDERDOC_API_1_0_2 = 1 00 02
eRENDERDOC_API_Version_1_1_0 = 10100, // RENDERDOC_API_1_1_0 = 1 01 00
eRENDERDOC_API_Version_1_1_1 = 10101, // RENDERDOC_API_1_1_1 = 1 01 01
} RENDERDOC_Version;
// API version changelog:
//
// 1.0.0 - initial release
// 1.0.1 - Bugfix: IsFrameCapturing() was returning false for captures that were triggered
// by keypress or TriggerCapture, instead of Start/EndFrameCapture.
// 1.0.2 - Refactor: Renamed eRENDERDOC_Option_DebugDeviceMode to eRENDERDOC_Option_APIValidation
// 1.1.0 - Add feature: TriggerMultiFrameCapture(). Backwards compatible with 1.0.x since the new
// function pointer is added to the end of the struct, the original layout is identical
// 1.1.1 - Refactor: Renamed remote access to target control (to better disambiguate from remote
// replay/remote server concept in replay UI)
// eRENDERDOC_API_Version_1_1_0
typedef struct
{
pRENDERDOC_GetAPIVersion GetAPIVersion;
pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32;
pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32;
pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32;
pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32;
pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys;
pRENDERDOC_SetCaptureKeys SetCaptureKeys;
pRENDERDOC_GetOverlayBits GetOverlayBits;
pRENDERDOC_MaskOverlayBits MaskOverlayBits;
pRENDERDOC_Shutdown Shutdown;
pRENDERDOC_UnloadCrashHandler UnloadCrashHandler;
pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate;
pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate;
pRENDERDOC_GetNumCaptures GetNumCaptures;
pRENDERDOC_GetCapture GetCapture;
pRENDERDOC_TriggerCapture TriggerCapture;
pRENDERDOC_IsRemoteAccessConnected IsRemoteAccessConnected;
pRENDERDOC_LaunchReplayUI LaunchReplayUI;
pRENDERDOC_SetActiveWindow SetActiveWindow;
pRENDERDOC_StartFrameCapture StartFrameCapture;
pRENDERDOC_IsFrameCapturing IsFrameCapturing;
pRENDERDOC_EndFrameCapture EndFrameCapture;
pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture;
} RENDERDOC_API_1_1_0;
typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_0;
typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_1;
typedef RENDERDOC_API_1_1_0 RENDERDOC_API_1_0_2;
// although this structure is identical to RENDERDOC_API_1_1_0, the member
// IsRemoteAccessConnected was renamed to IsTargetControlConnected. So that
// old code can still compile with a new header, we must declare a new struct
// type. It can be casted back and forth though, so we will still return a
// pointer to this type for all previous API versions - the above struct is
// purely legacy for compilation compatibility
// eRENDERDOC_API_Version_1_1_1
typedef struct
{
pRENDERDOC_GetAPIVersion GetAPIVersion;
pRENDERDOC_SetCaptureOptionU32 SetCaptureOptionU32;
pRENDERDOC_SetCaptureOptionF32 SetCaptureOptionF32;
pRENDERDOC_GetCaptureOptionU32 GetCaptureOptionU32;
pRENDERDOC_GetCaptureOptionF32 GetCaptureOptionF32;
pRENDERDOC_SetFocusToggleKeys SetFocusToggleKeys;
pRENDERDOC_SetCaptureKeys SetCaptureKeys;
pRENDERDOC_GetOverlayBits GetOverlayBits;
pRENDERDOC_MaskOverlayBits MaskOverlayBits;
pRENDERDOC_Shutdown Shutdown;
pRENDERDOC_UnloadCrashHandler UnloadCrashHandler;
pRENDERDOC_SetLogFilePathTemplate SetLogFilePathTemplate;
pRENDERDOC_GetLogFilePathTemplate GetLogFilePathTemplate;
pRENDERDOC_GetNumCaptures GetNumCaptures;
pRENDERDOC_GetCapture GetCapture;
pRENDERDOC_TriggerCapture TriggerCapture;
pRENDERDOC_IsTargetControlConnected IsTargetControlConnected;
pRENDERDOC_LaunchReplayUI LaunchReplayUI;
pRENDERDOC_SetActiveWindow SetActiveWindow;
pRENDERDOC_StartFrameCapture StartFrameCapture;
pRENDERDOC_IsFrameCapturing IsFrameCapturing;
pRENDERDOC_EndFrameCapture EndFrameCapture;
pRENDERDOC_TriggerMultiFrameCapture TriggerMultiFrameCapture;
} RENDERDOC_API_1_1_1;
//////////////////////////////////////////////////////////////////////////////////////////////////
// RenderDoc API entry point
//
// This entry point can be obtained via GetProcAddress/dlsym if RenderDoc is available.
//
// The name is the same as the typedef - "RENDERDOC_GetAPI"
//
// This function is not thread safe, and should not be called on multiple threads at once.
// Ideally, call this once as early as possible in your application's startup, before doing
// any API work, since some configuration functionality etc has to be done also before
// initialising any APIs.
//
// Parameters:
// version is a single value from the RENDERDOC_Version above.
//
// outAPIPointers will be filled out with a pointer to the corresponding struct of function
// pointers.
//
// Returns:
// 1 - if the outAPIPointers has been filled with a pointer to the API struct requested
// 0 - if the requested version is not supported or the arguments are invalid.
//
typedef int(RENDERDOC_CC *pRENDERDOC_GetAPI)(RENDERDOC_Version version, void **outAPIPointers);
#ifdef __cplusplus
} // extern "C"
#endif
+1
View File
@@ -278,6 +278,7 @@ void parse_stringstbl_common(const char *filename, const bool external)
if (external) {
ignore_white_space();
get_string(buf, sizeof(buf));
drop_trailing_white_space(buf);
} else {
stuff_string(buf, F_RAW, sizeof(buf));
}
+951 -970
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -445,7 +445,7 @@ void vm_vec_random_in_circle(vec3d *out, const vec3d *in, const matrix *orient,
// given a start vector, an orientation, and a radius, give a point in a spherical volume
// if on_edge is 1, the point is on the very edge of the sphere
void vm_vec_random_in_sphere(vec3d *out, const vec3d *in, float radius, int on_edge);
void vm_vec_random_in_sphere(vec3d *out, const vec3d *in, const matrix *orient, float radius, int on_edge);
// find the nearest point on the line to p. if dist is non-NULL, it is filled in
// returns 0 if the point is inside the line segment, -1 if "before" the line segment and 1 ir "after" the line segment
+2 -4
View File
@@ -433,7 +433,7 @@ void barracks_init_stats(scoring_struct *stats)
Num_stat_lines++;
Assert(Num_stat_lines < Max_stat_lines);
strcpy_s(Stat_labels[Num_stat_lines], XSTR( "Current Score:", 1583));
STRCPY1(Stat_labels[Num_stat_lines], "Current Score:");
sprintf(Stats[Num_stat_lines], "%d", stats->score);
Num_stat_lines++;
@@ -952,9 +952,7 @@ void barracks_init_player_stuff(int mode)
Num_pilots = 0;
Get_file_list_filter = barracks_pilot_filter;
Num_pilots =
cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_PLAYERS, NOX("*.plr"), CF_SORT_TIME,
nullptr, CF_LOCATION_ROOT_USER | CF_LOCATION_ROOT_GAME | CF_LOCATION_TYPE_ROOT);
Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
int ranks[MAX_PILOTS];
+18 -18
View File
@@ -123,7 +123,7 @@ int Main_hall_next_intercom_sound = 0;
int Main_hall_next_intercom_sound_stamp = -1;
// handle to any playing instance of a random intercom sound
sound_handle Main_hall_intercom_sound_handle = sound_handle::invalid();
int Main_hall_intercom_sound_handle = -1;
// handle any details related to random intercom sounds
void main_hall_handle_random_intercom_sounds();
@@ -225,10 +225,10 @@ void main_hall_mouse_grab_region(int region);
#define ALLENDER_REGION 4
// handles to the sound instances of the doors opening/closing
SCP_vector<sound_handle> Main_hall_door_sound_handles;
SCP_vector<int> Main_hall_door_sound_handles;
// sound handle for looping ambient sound
sound_handle Main_hall_ambient_loop = sound_handle::invalid();
int Main_hall_ambient_loop = -1;
// cull any door sounds that have finished playing
void main_hall_cull_door_sounds();
@@ -592,7 +592,7 @@ void main_hall_init(const SCP_string &main_hall_name)
// initialize door sound handles
Main_hall_door_sound_handles.clear();
for (idx = 0; idx < Main_hall->num_door_animations; idx++) {
Main_hall_door_sound_handles.push_back(sound_handle::invalid());
Main_hall_door_sound_handles.push_back(-1);
}
// skip the first frame
@@ -607,7 +607,7 @@ void main_hall_init(const SCP_string &main_hall_name)
// initialize the random intercom sound stuff
Main_hall_next_intercom_sound = 0;
Main_hall_next_intercom_sound_stamp = -1;
Main_hall_intercom_sound_handle = sound_handle::invalid();
Main_hall_intercom_sound_handle = -1;
// set the placement of the mouse cursor (start at the ready room)
Main_hall_mouse_region = -1;
@@ -1061,9 +1061,9 @@ void main_hall_close()
// stop any playing door sounds
for (idx = 0; idx < Main_hall->num_door_animations-2; idx++) {
if ((Main_hall_door_sound_handles.at(idx).isValid()) && snd_is_playing(Main_hall_door_sound_handles.at(idx))) {
if ( (Main_hall_door_sound_handles.at(idx) != -1) && snd_is_playing(Main_hall_door_sound_handles.at(idx)) ) {
snd_stop(Main_hall_door_sound_handles.at(idx));
Main_hall_door_sound_handles.at(idx) = sound_handle::invalid();
Main_hall_door_sound_handles.at(idx) = -1;
}
}
@@ -1382,7 +1382,7 @@ void main_hall_mouse_release_region(int region)
// check for door sounds, ignoring the OPTIONS_REGION (which isn't a door)
if (Main_hall_door_anim.at(region).num_frames > 0) {
// don't stop the toaster oven or microwave regions from playing all the way through
if (Main_hall_door_sound_handles.at(region).isValid()) {
if (Main_hall_door_sound_handles.at(region) != -1) {
snd_stop(Main_hall_door_sound_handles.at(region));
}
@@ -1425,7 +1425,7 @@ void main_hall_mouse_grab_region(int region)
// check for opening/starting sounds
// kill the currently playing sounds if necessary
if (Main_hall_door_sound_handles.at(region).isValid()) {
if (Main_hall_door_sound_handles.at(region) != -1) {
snd_stop(Main_hall_door_sound_handles.at(region));
}
@@ -1508,8 +1508,8 @@ void main_hall_cull_door_sounds()
// basically just set the handle of any finished sound to be -1, so that we know its free any where else in the code we may need it
Assert(Main_hall_door_sound_handles.size() < INT_MAX);
for (idx = 0; idx < (int)Main_hall_door_sound_handles.size(); idx++) {
if ((Main_hall_door_sound_handles.at(idx).isValid()) && !snd_is_playing(Main_hall_door_sound_handles.at(idx))) {
Main_hall_door_sound_handles.at(idx) = sound_handle::invalid();
if ( (Main_hall_door_sound_handles.at(idx) != -1) && !snd_is_playing(Main_hall_door_sound_handles.at(idx)) ) {
Main_hall_door_sound_handles.at(idx) = -1;
}
}
}
@@ -1526,14 +1526,14 @@ void main_hall_handle_random_intercom_sounds()
}
// if we have no timestamp for the next random sound, then set on
if ((Main_hall_next_intercom_sound_stamp == -1) && (!Main_hall_intercom_sound_handle.isValid())) {
if ( (Main_hall_next_intercom_sound_stamp == -1) && (Main_hall_intercom_sound_handle == -1) ) {
Main_hall_next_intercom_sound_stamp = timestamp((int)((rand() * RAND_MAX_1f) *
(float)(Main_hall->intercom_delay.at(Main_hall_next_intercom_sound).at(1)
- Main_hall->intercom_delay.at(Main_hall_next_intercom_sound).at(0))) );
}
// if the there is no sound playing
if (!Main_hall_intercom_sound_handle.isValid()) {
if (Main_hall_intercom_sound_handle == -1) {
if (Main_hall_paused) {
return;
}
@@ -1571,7 +1571,7 @@ void main_hall_handle_random_intercom_sounds()
- Main_hall->intercom_delay.at(Main_hall_next_intercom_sound).at(0))) );
// release the sound handle
Main_hall_intercom_sound_handle = sound_handle::invalid();
Main_hall_intercom_sound_handle = -1;
}
}
}
@@ -1624,7 +1624,7 @@ void main_hall_start_ambient()
return;
}
if (!Main_hall_ambient_loop.isValid()) {
if (Main_hall_ambient_loop == -1) {
play_ambient_loop = 1;
} else {
if (!snd_is_playing(Main_hall_ambient_loop)) {
@@ -1642,9 +1642,9 @@ void main_hall_start_ambient()
*/
void main_hall_stop_ambient()
{
if (Main_hall_ambient_loop.isValid()) {
if (Main_hall_ambient_loop != -1) {
snd_stop(Main_hall_ambient_loop);
Main_hall_ambient_loop = sound_handle::invalid();
Main_hall_ambient_loop = -1;
}
}
@@ -1655,7 +1655,7 @@ void main_hall_stop_ambient()
*/
void main_hall_reset_ambient_vol()
{
if (Main_hall_ambient_loop.isValid()) {
if (Main_hall_ambient_loop >= 0) {
snd_set_volume(Main_hall_ambient_loop, gamesnd_get_interface_sound(InterfaceSounds::MAIN_HALL_AMBIENT)->volume_range.next());
}
}
+7 -5
View File
@@ -242,7 +242,7 @@ static int Sound_volume_int;
static int Music_volume_int;
static int Voice_volume_int;
static sound_handle Voice_vol_handle = sound_handle::invalid();
static int Voice_vol_handle = -1;
int Options_notify_stamp = -1;
char Options_notify_string[200];
@@ -465,14 +465,16 @@ UI_XSTR Options_text[GR_NUM_RESOLUTIONS][OPTIONS_NUM_TEXT] = {
void options_play_voice_clip()
{
int snd_id;
if ( snd_is_playing(Voice_vol_handle) ) {
snd_stop(Voice_vol_handle);
Voice_vol_handle = sound_handle::invalid();
Voice_vol_handle=-1;
}
auto gs = gamesnd_get_interface_sound(InterfaceSounds::VOICE_SLIDER_CLIP);
auto entry = gamesnd_choose_entry(gs);
auto snd_id = snd_load(entry, gs->flags, 0);
snd_id = snd_load(entry, gs->flags, 0);
Voice_vol_handle = snd_play_raw( snd_id, 0.0f, 1.0f, SND_PRIORITY_SINGLE_INSTANCE );
}
@@ -1045,9 +1047,9 @@ void options_menu_close()
}
}
if (Voice_vol_handle.isValid()) {
if ( Voice_vol_handle >= 0 ) {
snd_stop(Voice_vol_handle);
Voice_vol_handle = sound_handle::invalid();
Voice_vol_handle = -1;
}
options_multi_close();
+5 -5
View File
@@ -506,7 +506,7 @@ int Om_vox_voice_buffer_size = -1;
unsigned char Om_vox_comp_buffer[OM_VOX_COMP_SIZE];
int Om_vox_voice_comp_size = -1;
sound_handle Om_vox_playback_handle;
int Om_vox_playback_handle;
// status of any test voice recording
#define OM_VOX_TEST_NONE -1
@@ -1710,7 +1710,7 @@ void options_multi_disable_vox_controls()
// unset the sound buffer size so we don't display any waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_playback_handle = -1;
Om_vox_test_status = OM_VOX_TEST_NONE;
// disable the player list select button
@@ -1739,7 +1739,7 @@ void options_multi_enable_vox_controls()
// unset the sound buffer size so we don't display any waveforms
Om_vox_voice_buffer_size = -1;
Om_vox_voice_comp_size = -1;
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_playback_handle = -1;
Om_vox_test_status = OM_VOX_TEST_NONE;
// select the first player on the list
@@ -1851,12 +1851,12 @@ void options_multi_vox_do()
case OM_VOX_TEST_PLAYBACK:
// if we were playing a sound back, but now the sound is done
if ((Om_vox_playback_handle.isValid()) && !ds_is_channel_playing(ds_get_channel(Om_vox_playback_handle))) {
if ( (Om_vox_playback_handle != -1) && !ds_is_channel_playing(ds_get_channel(Om_vox_playback_handle)) ) {
// flush all playing sounds safely
rtvoice_stop_playback_all();
// null the sound handle
Om_vox_playback_handle = sound_handle::invalid();
Om_vox_playback_handle = -1;
// set this so we know not to display any more waveforms
Om_vox_voice_buffer_size = -1;
Loaded 100 of 339 files, more files were not shown because too many files have changed in this diff. Show more