Enable -Wformat-truncation
Add macro cf_assert ("control flow" assert) to hint to gcc that certain conditions are impossible. Use it to avoid generating range checks for situations that never happen. If the event did happen, the only consequence would be truncated UI text, rather than a correctness problem.
This commit is contained in:
parent
dc0a405222
commit
ec1cf005b6
30
SConstruct
30
SConstruct
|
@ -2576,36 +2576,6 @@ where the cast is useless.
|
|||
'-Wsuggest-attribute=noreturn',
|
||||
'-Wlogical-op',
|
||||
'-Wold-style-cast',
|
||||
# Starting in gcc-7, Rebirth default options cause gcc to enable
|
||||
# -Wformat-truncation automatically. Unless proven otherwise by
|
||||
# data flow analysis, gcc pessimistically assumes that input
|
||||
# parameters might have their most space-consuming value (3
|
||||
# digits for a uint8_t, 5 for uint16_t, etc.). This causes
|
||||
# numerous warnings for places where Rebirth allocated a buffer
|
||||
# that is exactly big enough for the small numbers that are
|
||||
# actually used, but the data flow analysis is unable to prove
|
||||
# that larger numbers are not used.
|
||||
#
|
||||
# It would be nice to remove this option and eliminate the
|
||||
# warnings with fixes in the code, since this test completely
|
||||
# suppresses all -Wformat-truncation diagnostics, including any
|
||||
# that may be true bugs. However, gcc provides no documented
|
||||
# way to do this that does not generate extra runtime
|
||||
# instructions, which are unnecessary in at least some of the
|
||||
# cases where gcc warns.
|
||||
#
|
||||
# In testing, setting -Wformat-truncation=1 was insufficient to
|
||||
# silence a warning in similar/main/net_udp.cpp:
|
||||
#
|
||||
# similar/main/net_udp.cpp: In static member function 'static void {anonymous}::more_game_options_menu_items::net_udp_more_game_options()':
|
||||
# similar/main/net_udp.cpp:3528:6: error: ' Furthest Sites' directive output may be truncated writing 15 bytes into a region of size between 14 and 16 [-Werror=format-truncation=]
|
||||
# void more_game_options_menu_items::net_udp_more_game_options()
|
||||
# ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# similar/main/net_udp.cpp:3433:11: note: 'snprintf' output between 21 and 23 bytes into a destination of size 21
|
||||
# snprintf(SecludedSpawnText, sizeof(SecludedSpawnText), "Use %u Furthest Sites", Netgame.SecludedSpawns + 1);
|
||||
# ~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
#
|
||||
'-Wno-format-truncation',
|
||||
]
|
||||
__preferred_win32_linker_options = [
|
||||
'-Wl,--large-address-aware',
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "compiler-range_for.h"
|
||||
|
||||
#if DXX_MAX_JOYSTICKS
|
||||
#include "compiler-cf_assert.h"
|
||||
#include "compiler-integer_sequence.h"
|
||||
#include "d_enumerate.h"
|
||||
#include "partial_range.h"
|
||||
|
@ -294,7 +295,8 @@ void joy_init()
|
|||
|
||||
const auto n = check_warn_joy_support_limit(SDL_NumJoysticks(), "joystick", DXX_MAX_JOYSTICKS);
|
||||
unsigned joystick_n_buttons = 0, joystick_n_axes = 0;
|
||||
for (int i = 0; i < n; i++) {
|
||||
for (unsigned i = 0; i < n; i++)
|
||||
{
|
||||
auto &joystick = SDL_Joysticks[num_joysticks];
|
||||
const auto handle = SDL_JoystickOpen(i);
|
||||
joystick.handle().reset(handle);
|
||||
|
@ -311,6 +313,7 @@ void joy_init()
|
|||
joyaxis_text.resize(joyaxis_text.size() + n_axes);
|
||||
range_for (auto &&e, enumerate(partial_range(joystick.axis_map(), n_axes), 1))
|
||||
{
|
||||
cf_assert(e.idx <= DXX_MAX_AXES_PER_JOYSTICK);
|
||||
auto &text = joyaxis_text[joystick_n_axes];
|
||||
e.value = joystick_n_axes++;
|
||||
snprintf(&text[0], sizeof(text), "J%d A%u", i + 1, e.idx);
|
||||
|
@ -325,6 +328,7 @@ void joy_init()
|
|||
#if DXX_MAX_BUTTONS_PER_JOYSTICK
|
||||
range_for (auto &&e, enumerate(partial_range(joystick.button_map(), n_buttons), 1))
|
||||
{
|
||||
cf_assert(e.idx <= DXX_MAX_BUTTONS_PER_JOYSTICK);
|
||||
auto &text = joybutton_text[joystick_n_buttons];
|
||||
e.value = joystick_n_buttons++;
|
||||
snprintf(&text[0], sizeof(text), "J%d B%d", i + 1, e.idx);
|
||||
|
@ -334,6 +338,7 @@ void joy_init()
|
|||
range_for (auto &&e, enumerate(partial_range(joystick.hat_map(), n_hats), 1))
|
||||
{
|
||||
e.value = joystick_n_buttons;
|
||||
cf_assert(e.idx <= DXX_MAX_HATS_PER_JOYSTICK);
|
||||
//a hat counts as four buttons
|
||||
snprintf(&joybutton_text[joystick_n_buttons++][0], sizeof(joybutton_text[0]), "J%d H%d%c", i + 1, e.idx, 0202);
|
||||
snprintf(&joybutton_text[joystick_n_buttons++][0], sizeof(joybutton_text[0]), "J%d H%d%c", i + 1, e.idx, 0177);
|
||||
|
|
|
@ -39,6 +39,8 @@ COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
|
|||
#include "ui.h"
|
||||
#include "strutil.h"
|
||||
|
||||
#include "compiler-cf_assert.h"
|
||||
|
||||
namespace dcx {
|
||||
|
||||
#define AUTOSAVE_PERIOD 5 // Number of minutes for timed autosave
|
||||
|
@ -66,7 +68,10 @@ void init_autosave(void) {
|
|||
void close_autosave(void) {
|
||||
char *ext;
|
||||
|
||||
for (int i=0;i<Autosave_total;i++) {
|
||||
const unsigned t = Autosave_total;
|
||||
cf_assert(t < 10);
|
||||
for (unsigned i = 0; i < t; ++i)
|
||||
{
|
||||
|
||||
char delname[PATH_MAX];
|
||||
|
||||
|
|
86
common/include/compiler-cf_assert.h
Normal file
86
common/include/compiler-cf_assert.h
Normal file
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* This file is part of the DXX-Rebirth project <http://www.dxx-rebirth.com/>.
|
||||
* It is copyright by its individual contributors, as recorded in the
|
||||
* project's Git history. See COPYING.txt at the top level for license
|
||||
* terms and a link to the Git history.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/* Define a utility macro `cf_assert` that, like `assert`, is meant to
|
||||
* check invariants. Unlike `assert`, it has a small but configurable
|
||||
* effect on NDEBUG builds.
|
||||
*
|
||||
* This macro is mainly used to try to hint to gcc that it is
|
||||
* excessively cautious in determining whether a
|
||||
* -Wformat-truncation warning is appropriate.
|
||||
*
|
||||
* Unless proved otherwise by control flow analysis, gcc will assume
|
||||
* that a variable to be formatted could have any value that fits in the
|
||||
* underlying type, and then gcc will warn if any of those values does
|
||||
* not fit. In most cases, program logic constrains the value to a
|
||||
* smaller range than the underlying type supports. Correct placement
|
||||
* of this macro can inform the compiler that a variable's actual range
|
||||
* is less than the full supported range of the underlying type. For
|
||||
* example, a player counter should never exceed MAX_PLAYERS, but
|
||||
* MAX_PLAYERS is far less than MAX_UCHAR.
|
||||
*
|
||||
* Unfortunately, in tested versions of gcc-8, the compiler's range
|
||||
* propagation pass is hampered by strange rules in the flow control
|
||||
* logic. Consider:
|
||||
|
||||
unsigned var = unconstrained_expression();
|
||||
// var can now be anything in [0, UINT_MAX]
|
||||
cf_assert(var <= 8);
|
||||
// If execution gets here, `var <= 8` is true.
|
||||
snprintf(..., var);
|
||||
|
||||
* Suppose cf_assert(X) is defined as `((X) || (assert(X),
|
||||
* __builtin_unreachable()))`, so the above becomes:
|
||||
|
||||
unsigned var = unconstrained_expression();
|
||||
if (var <= 8) {
|
||||
}
|
||||
else {
|
||||
assert_fail(...);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
snprintf(..., var);
|
||||
|
||||
* In testing, gcc deleted __builtin_unreachable (probably because
|
||||
* assert_fail is noreturn), then warned because, without the
|
||||
* __builtin_unreachable, flow control decides the snprintf is reachable
|
||||
* (even though assert_fail is noreturn) on the else path and would
|
||||
* misbehave if reached. Remove the call to `assert` so that you have
|
||||
* `else { __builtin_unreachable(); }` and gcc will retain the
|
||||
* `__builtin_unreachable` and not warn.
|
||||
*
|
||||
* For an even more bizarre result:
|
||||
|
||||
if (var <= 8) {
|
||||
snprintf(..., var);
|
||||
} else {
|
||||
assert(var <= 8); // always fails
|
||||
__builtin_unreachable();
|
||||
}
|
||||
|
||||
* This block warns that `var` is out of range. Comment out the
|
||||
* `assert`, which cannot influence whether `snprintf` is reached, and
|
||||
* the warning goes away.
|
||||
*
|
||||
* --
|
||||
*
|
||||
* Leave cf_assert set as an alias for (X || __builtin_unreachable())
|
||||
* unless you know what you are doing and are prepared for the warnings
|
||||
* that will arise.
|
||||
*/
|
||||
#include <cassert>
|
||||
#if defined(DXX_CF_ASSERT_ASSERT)
|
||||
#define cf_assert assert
|
||||
#else
|
||||
#ifdef DXX_CF_ASSERT_TRAP
|
||||
#define cf_assert_fail __builtin_trap
|
||||
#else
|
||||
#define cf_assert_fail __builtin_unreachable
|
||||
#endif
|
||||
#define cf_assert(X) ((X) ? static_cast<void>(0) : (cf_assert_fail()))
|
||||
#endif
|
|
@ -741,7 +741,7 @@ int menubar_init(grs_canvas &canvas, const char *const file)
|
|||
{
|
||||
int np;
|
||||
char buf1[200];
|
||||
char buf2[200];
|
||||
char buf2[204];
|
||||
|
||||
num_menus = state = 0;
|
||||
|
||||
|
@ -786,7 +786,7 @@ int menubar_init(grs_canvas &canvas, const char *const file)
|
|||
CommaParse( 2, buf1, buffer );
|
||||
ul_xlate(buf1);
|
||||
|
||||
item.Text.reset(d_strdup(buf1[0] == '-' ? buf1 : (snprintf(buf2, sizeof(buf2), " %s ", buf1), buf2)));
|
||||
item.Text.reset(d_strdup(buf1[0] == '-' ? buf1 : (snprintf(buf2, sizeof(buf2), " %.197s ", buf1), buf2)));
|
||||
|
||||
item.InactiveText.reset(d_strdup(item.Text.get()));
|
||||
|
||||
|
|
|
@ -1741,7 +1741,7 @@ window_event_result escort_menu::event_handler(window *, const d_event &event, e
|
|||
void do_escort_menu(void)
|
||||
{
|
||||
int next_goal;
|
||||
char goal_str[32];
|
||||
char goal_str[12];
|
||||
const char *goal_txt;
|
||||
const char *tstr;
|
||||
escort_menu *menu;
|
||||
|
|
|
@ -178,9 +178,9 @@ static int med_save_situation(char * filename)
|
|||
{
|
||||
auto SaveFile = PHYSFSX_openWriteBuffered(filename);
|
||||
if (!SaveFile) {
|
||||
char ErrorMessage[200];
|
||||
char ErrorMessage[512];
|
||||
|
||||
snprintf(ErrorMessage, sizeof(ErrorMessage), "ERROR: Unable to open %s\n", filename);
|
||||
snprintf(ErrorMessage, sizeof(ErrorMessage), "ERROR: Unable to open %.480s", filename);
|
||||
ui_messagebox( -2, -2, 1, ErrorMessage, "Ok" );
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ static void ab_load(int skip, const char * filename, array<bitmap_index, MAX_BIT
|
|||
bitmap_index bi;
|
||||
int iff_error; //reference parm to avoid warning message
|
||||
palette_array_t newpal;
|
||||
char tempname[20];
|
||||
array<char, 24> tempname;
|
||||
|
||||
if (skip) {
|
||||
Assert( bogus_bitmap_initialized != 0 );
|
||||
|
@ -293,11 +293,11 @@ static void ab_load(int skip, const char * filename, array<bitmap_index, MAX_BIT
|
|||
unsigned i;
|
||||
for (i=0; i<MAX_BITMAPS_PER_BRUSH; i++ ) {
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
snprintf(tempname, sizeof(tempname), "%s#%d", fname.data(), i);
|
||||
snprintf(tempname.data(), tempname.size(), "%.16s#%d", fname.data(), i);
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
snprintf( tempname, sizeof(tempname), "%.*s#%d", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, i );
|
||||
snprintf(tempname.data(), tempname.size(), "%.*s#%d", DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, i);
|
||||
#endif
|
||||
bi = piggy_find_bitmap( tempname );
|
||||
bi = piggy_find_bitmap(tempname.data());
|
||||
if ( !bi.index )
|
||||
break;
|
||||
bmp[i] = bi;
|
||||
|
@ -326,13 +326,13 @@ static void ab_load(int skip, const char * filename, array<bitmap_index, MAX_BIT
|
|||
for (uint_fast32_t i = 0; i != nf; ++i)
|
||||
{
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
snprintf(tempname, sizeof(tempname), "%s#%" PRIuFAST32, fname.data(), i);
|
||||
snprintf(tempname.data(), tempname.size(), "%s#%" PRIuFAST32, fname.data(), i);
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
snprintf( tempname, sizeof(tempname), "%.*s#%" PRIuFAST32, DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, i );
|
||||
snprintf(tempname.data(), tempname.size(), "%.*s#%" PRIuFAST32, DXX_ptrdiff_cast_int(path.base_end - path.base_start), path.base_start, i );
|
||||
#endif
|
||||
gr_remap_bitmap_good(*bm[i].get(), newpal, iff_has_transparency ? iff_transparent_color : -1, SuperX);
|
||||
bm[i]->avg_color = compute_average_pixel(bm[i].get());
|
||||
bmp[i] = piggy_register_bitmap(*bm[i].get(), tempname, 0);
|
||||
bmp[i] = piggy_register_bitmap(*bm[i].get(), tempname.data(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -893,16 +893,11 @@ void StartNewGame(int start_level)
|
|||
static void DoEndLevelScoreGlitz()
|
||||
{
|
||||
int level_points, skill_points, energy_points, shield_points, hostage_points;
|
||||
int all_hostage_points;
|
||||
int endgame_points;
|
||||
char all_hostage_text[64];
|
||||
char endgame_text[64];
|
||||
#define N_GLITZITEMS 9
|
||||
char m_str[N_GLITZITEMS][30];
|
||||
char m_str[N_GLITZITEMS][32];
|
||||
newmenu_item m[N_GLITZITEMS];
|
||||
int i,c;
|
||||
char title[128];
|
||||
int is_last_level;
|
||||
#if defined(DXX_BUILD_DESCENT_I)
|
||||
gr_palette_load( gr_palette );
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
|
@ -947,26 +942,7 @@ static void DoEndLevelScoreGlitz()
|
|||
hostage_points = 0;
|
||||
}
|
||||
|
||||
all_hostage_text[0] = 0;
|
||||
endgame_text[0] = 0;
|
||||
|
||||
auto &plr = get_local_player();
|
||||
if (!cheats.enabled && player_info.mission.hostages_on_board == plr.hostages_level)
|
||||
{
|
||||
all_hostage_points = player_info.mission.hostages_on_board * 1000 * (Difficulty_level+1);
|
||||
snprintf(all_hostage_text, sizeof(all_hostage_text), "%s%i\n", TXT_FULL_RESCUE_BONUS, all_hostage_points);
|
||||
} else
|
||||
all_hostage_points = 0;
|
||||
|
||||
if (!cheats.enabled && !(Game_mode & GM_MULTI) && plr.lives && Current_level_num == Last_level)
|
||||
{ //player has finished the game!
|
||||
endgame_points = plr.lives * 10000;
|
||||
snprintf(endgame_text, sizeof(endgame_text), "%s%i\n", TXT_SHIP_BONUS, endgame_points);
|
||||
is_last_level=1;
|
||||
} else
|
||||
endgame_points = is_last_level = 0;
|
||||
|
||||
add_bonus_points_to_score(player_info, skill_points + energy_points + shield_points + hostage_points + all_hostage_points + endgame_points);
|
||||
|
||||
c = 0;
|
||||
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_SHIELD_BONUS, shield_points); // Return at start to lower menu...
|
||||
|
@ -974,9 +950,35 @@ static void DoEndLevelScoreGlitz()
|
|||
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_HOSTAGE_BONUS, hostage_points);
|
||||
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_SKILL_BONUS, skill_points);
|
||||
|
||||
snprintf(m_str[c++], sizeof(m_str[0]), "%s", all_hostage_text);
|
||||
if (!(Game_mode & GM_MULTI) && plr.lives && Current_level_num == Last_level)
|
||||
snprintf(m_str[c++], sizeof(m_str[0]), "%s", endgame_text);
|
||||
const unsigned hostages_on_board = player_info.mission.hostages_on_board;
|
||||
unsigned all_hostage_points = 0;
|
||||
unsigned endgame_points = 0;
|
||||
uint8_t is_last_level = 0;
|
||||
auto &hostage_text = m_str[c++];
|
||||
if (cheats.enabled)
|
||||
snprintf(hostage_text, sizeof(hostage_text), "Hostages saved: \t%u", hostages_on_board);
|
||||
else if (const auto hostages_lost = plr.hostages_level - hostages_on_board)
|
||||
snprintf(hostage_text, sizeof(hostage_text), "Hostages lost: \t%u", hostages_lost);
|
||||
else
|
||||
{
|
||||
all_hostage_points = hostages_on_board * 1000 * (Difficulty_level + 1);
|
||||
snprintf(hostage_text, sizeof(hostage_text), "%s%i\n", TXT_FULL_RESCUE_BONUS, all_hostage_points);
|
||||
}
|
||||
|
||||
auto &endgame_text = m_str[c++];
|
||||
endgame_text[0] = 0;
|
||||
if (cheats.enabled)
|
||||
{
|
||||
/* Nothing */
|
||||
}
|
||||
else if (!(Game_mode & GM_MULTI) && plr.lives && Current_level_num == Last_level)
|
||||
{ //player has finished the game!
|
||||
endgame_points = plr.lives * 10000;
|
||||
snprintf(endgame_text, sizeof(endgame_text), "%s%i\n", TXT_SHIP_BONUS, endgame_points);
|
||||
is_last_level=1;
|
||||
}
|
||||
|
||||
add_bonus_points_to_score(player_info, skill_points + energy_points + shield_points + hostage_points + all_hostage_points + endgame_points);
|
||||
|
||||
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i\n", TXT_TOTAL_BONUS, shield_points + energy_points + hostage_points + skill_points + all_hostage_points + endgame_points);
|
||||
snprintf(m_str[c++], sizeof(m_str[0]), "%s%i", TXT_TOTAL_SCORE, player_info.mission.score);
|
||||
|
|
|
@ -216,10 +216,13 @@ static const char *load_mission_d1()
|
|||
break;
|
||||
case D1_OEM_MISSION_HOGSIZE:
|
||||
case D1_OEM_10_MISSION_HOGSIZE:
|
||||
{
|
||||
N_secret_levels = 1;
|
||||
|
||||
Last_level = 15;
|
||||
Last_secret_level = -1;
|
||||
constexpr unsigned last_level = 15;
|
||||
constexpr int last_secret_level = -1;
|
||||
Last_level = last_level;
|
||||
Last_secret_level = last_secret_level;
|
||||
|
||||
if (!allocate_levels())
|
||||
{
|
||||
|
@ -228,14 +231,24 @@ static const char *load_mission_d1()
|
|||
}
|
||||
|
||||
//build level names
|
||||
for (int i=0; i < Last_level - 1; i++)
|
||||
snprintf(&Level_names[i][0u], Level_names[i].size(), "level%02d.rdl", i+1);
|
||||
snprintf(&Level_names[Last_level - 1][0u], Level_names[Last_level - 1].size(), "saturn%02d.rdl", Last_level);
|
||||
for (int i=0; i < -Last_secret_level; i++)
|
||||
snprintf(&Secret_level_names[i][0u], Secret_level_names[i].size(), "levels%1d.rdl", i+1);
|
||||
for (unsigned i = 0; i < last_level - 1; ++i)
|
||||
{
|
||||
auto &ln = Level_names[i];
|
||||
snprintf(&ln[0u], ln.size(), "level%02u.rdl", i + 1);
|
||||
}
|
||||
{
|
||||
auto &ln = Level_names[last_level - 1];
|
||||
snprintf(&ln[0u], ln.size(), "saturn%02d.rdl", last_level);
|
||||
}
|
||||
for (int i = 0; i < -last_secret_level; ++i)
|
||||
{
|
||||
auto &sn = Secret_level_names[i];
|
||||
snprintf(&sn[0u], sn.size(), "levels%1d.rdl", i + 1);
|
||||
}
|
||||
Secret_level_table[0] = 10;
|
||||
Briefing_text_filename = "briefsat.txb";
|
||||
Ending_text_filename = BIMD1_ENDING_FILE_OEM;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Int3(); // fall through
|
||||
|
@ -243,10 +256,13 @@ static const char *load_mission_d1()
|
|||
case D1_MISSION_HOGSIZE2:
|
||||
case D1_10_MISSION_HOGSIZE:
|
||||
case D1_MAC_MISSION_HOGSIZE:
|
||||
{
|
||||
N_secret_levels = 3;
|
||||
|
||||
Last_level = BIMD1_LAST_LEVEL;
|
||||
Last_secret_level = BIMD1_LAST_SECRET_LEVEL;
|
||||
constexpr unsigned last_level = BIMD1_LAST_LEVEL;
|
||||
constexpr int last_secret_level = BIMD1_LAST_SECRET_LEVEL;
|
||||
Last_level = last_level;
|
||||
Last_secret_level = last_secret_level;
|
||||
|
||||
if (!allocate_levels())
|
||||
{
|
||||
|
@ -255,16 +271,23 @@ static const char *load_mission_d1()
|
|||
}
|
||||
|
||||
//build level names
|
||||
for (int i=0;i<Last_level;i++)
|
||||
snprintf(&Level_names[i][0u], Level_names[i].size(), "level%02d.rdl", i+1);
|
||||
for (int i=0;i<-Last_secret_level;i++)
|
||||
snprintf(&Secret_level_names[i][0u], Secret_level_names[i].size(), "levels%1d.rdl", i+1);
|
||||
for (unsigned i = 0; i < last_level; ++i)
|
||||
{
|
||||
auto &ln = Level_names[i];
|
||||
snprintf(&ln[0u], ln.size(), "level%02u.rdl", i + 1);
|
||||
}
|
||||
for (int i = 0; i < -last_secret_level; ++i)
|
||||
{
|
||||
auto &sn = Secret_level_names[i];
|
||||
snprintf(&sn[0u], sn.size(), "levels%1d.rdl", i + 1);
|
||||
}
|
||||
Secret_level_table[0] = 10;
|
||||
Secret_level_table[1] = 21;
|
||||
Secret_level_table[2] = 24;
|
||||
Briefing_text_filename = BIMD1_BRIEFING_FILE;
|
||||
Ending_text_filename = "endreg.txb";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include "dxxsconf.h"
|
||||
#include "compiler-array.h"
|
||||
#include "compiler-cf_assert.h"
|
||||
#include "compiler-exchange.h"
|
||||
#include "compiler-range_for.h"
|
||||
#include "compiler-lengthof.h"
|
||||
|
@ -850,7 +851,7 @@ struct list_join : direct_join
|
|||
entries = ((UDP_NETGAMES_PPAGE + 5) * 2) + 1,
|
||||
};
|
||||
array<newmenu_item, entries> m;
|
||||
array<array<char, 74>, entries> ljtext;
|
||||
array<array<char, 92>, entries> ljtext;
|
||||
};
|
||||
|
||||
manual_join_user_inputs manual_join::s_last_inputs;
|
||||
|
@ -1206,7 +1207,8 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
|
|||
// Copy the active games data into the menu options
|
||||
for (int i = 0; i < UDP_NETGAMES_PPAGE; i++)
|
||||
{
|
||||
int game_status = Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_status;
|
||||
const auto &augi = Active_udp_games[(i + (NLPage * UDP_NETGAMES_PPAGE))];
|
||||
int game_status = augi.game_status;
|
||||
int j,x, k,nplayers = 0;
|
||||
char levelname[8],MissName[25],GameName[25],thold[2];
|
||||
thold[1]=0;
|
||||
|
@ -1224,9 +1226,9 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
|
|||
const auto &&fspacx = FSPACX();
|
||||
for (x=0,k=0,j=0;j<15;j++)
|
||||
{
|
||||
if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].mission_title[j]=='\t')
|
||||
if (augi.mission_title[j]=='\t')
|
||||
continue;
|
||||
thold[0]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].mission_title[j];
|
||||
thold[0] = augi.mission_title[j];
|
||||
int tx;
|
||||
gr_get_string_size(*grd_curcanv->cv_font, thold, &tx, nullptr, nullptr);
|
||||
|
||||
|
@ -1237,15 +1239,15 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
|
|||
break;
|
||||
}
|
||||
|
||||
MissName[k++]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].mission_title[j];
|
||||
MissName[k++] = augi.mission_title[j];
|
||||
}
|
||||
MissName[k]=0;
|
||||
|
||||
for (x=0,k=0,j=0;j<15;j++)
|
||||
{
|
||||
if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_name[j]=='\t')
|
||||
if (augi.game_name[j]=='\t')
|
||||
continue;
|
||||
thold[0]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_name[j];
|
||||
thold[0]=augi.game_name[j];
|
||||
int tx;
|
||||
gr_get_string_size(*grd_curcanv->cv_font, thold, &tx, nullptr, nullptr);
|
||||
|
||||
|
@ -1255,25 +1257,32 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
|
|||
k+=3;
|
||||
break;
|
||||
}
|
||||
GameName[k++]=Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_name[j];
|
||||
GameName[k++]=augi.game_name[j];
|
||||
}
|
||||
GameName[k]=0;
|
||||
|
||||
nplayers = Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].numconnected;
|
||||
nplayers = augi.numconnected;
|
||||
|
||||
if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].levelnum < 0)
|
||||
snprintf(levelname, sizeof(levelname), "S%d", -Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].levelnum);
|
||||
const int levelnum = augi.levelnum;
|
||||
if (levelnum < 0)
|
||||
{
|
||||
cf_assert(-levelnum < MAX_SECRET_LEVELS_PER_MISSION);
|
||||
snprintf(levelname, sizeof(levelname), "S%d", -levelnum);
|
||||
}
|
||||
else
|
||||
snprintf(levelname, sizeof(levelname), "%d", Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].levelnum);
|
||||
{
|
||||
cf_assert(levelnum < MAX_LEVELS_PER_MISSION);
|
||||
snprintf(levelname, sizeof(levelname), "%d", levelnum);
|
||||
}
|
||||
|
||||
const char *status;
|
||||
if (game_status == NETSTAT_STARTING)
|
||||
status = "FORMING ";
|
||||
else if (game_status == NETSTAT_PLAYING)
|
||||
{
|
||||
if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].RefusePlayers)
|
||||
if (augi.RefusePlayers)
|
||||
status = "RESTRICT";
|
||||
else if (Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].game_flag.closed)
|
||||
else if (augi.game_flag.closed)
|
||||
status = "CLOSED ";
|
||||
else
|
||||
status = "OPEN ";
|
||||
|
@ -1281,9 +1290,9 @@ static int net_udp_list_join_poll(newmenu *menu, const d_event &event, list_join
|
|||
else
|
||||
status = "BETWEEN ";
|
||||
|
||||
unsigned gamemode = Active_udp_games[(i+(NLPage*UDP_NETGAMES_PPAGE))].gamemode;
|
||||
unsigned gamemode = augi.gamemode;
|
||||
auto &p = dj->ljtext[i];
|
||||
snprintf(&p[0], p.size(), "%d.\t%s \t%s \t %d/%d \t%s \t %s \t%s", (i + (NLPage * UDP_NETGAMES_PPAGE)) + 1, GameName, (gamemode < sizeof(GMNamesShrt) / sizeof(GMNamesShrt[0])) ? GMNamesShrt[gamemode] : "INVALID", nplayers, Active_udp_games[(i + (NLPage * UDP_NETGAMES_PPAGE))].max_numplayers, MissName, levelname, status);
|
||||
snprintf(&p[0], p.size(), "%d.\t%.24s \t%.7s \t%3u/%u \t%.24s \t %s \t%s", (i + (NLPage * UDP_NETGAMES_PPAGE)) + 1, GameName, (gamemode < sizeof(GMNamesShrt) / sizeof(GMNamesShrt[0])) ? GMNamesShrt[gamemode] : "INVALID", nplayers, augi.max_numplayers, MissName, levelname, status);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -3464,7 +3473,9 @@ public:
|
|||
}
|
||||
void update_secluded_spawn_string()
|
||||
{
|
||||
snprintf(SecludedSpawnText, sizeof(SecludedSpawnText), "Use %u Furthest Sites", Netgame.SecludedSpawns + 1);
|
||||
const unsigned SecludedSpawns = Netgame.SecludedSpawns;
|
||||
cf_assert(SecludedSpawns < MAX_PLAYERS);
|
||||
snprintf(SecludedSpawnText, sizeof(SecludedSpawnText), "Use %u Furthest Sites", SecludedSpawns + 1);
|
||||
}
|
||||
void update_kill_goal_string()
|
||||
{
|
||||
|
@ -3712,7 +3723,9 @@ struct param_opt
|
|||
}
|
||||
void update_max_players_string()
|
||||
{
|
||||
snprintf(srmaxnet, sizeof(srmaxnet), "Maximum players: %u", Netgame.max_numplayers);
|
||||
const unsigned max_numplayers = Netgame.max_numplayers;
|
||||
cf_assert(max_numplayers < MAX_PLAYERS);
|
||||
snprintf(srmaxnet, sizeof(srmaxnet), "Maximum players: %u", max_numplayers);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -3876,7 +3876,7 @@ static void newdemo_write_end()
|
|||
nd_write_byte(ND_EVENT_EOF);
|
||||
}
|
||||
|
||||
static bool guess_demo_name(ntstring<PATH_MAX - 1> &filename)
|
||||
static bool guess_demo_name(ntstring<PATH_MAX - 16> &filename)
|
||||
{
|
||||
filename[0] = 0;
|
||||
const auto &n = CGameArg.SysRecordDemoNameTemplate;
|
||||
|
@ -3964,7 +3964,7 @@ void newdemo_stop_recording()
|
|||
{
|
||||
int exit;
|
||||
static sbyte tmpcnt = 0;
|
||||
ntstring<PATH_MAX - 1> filename;
|
||||
ntstring<PATH_MAX - 16> filename;
|
||||
|
||||
exit = 0;
|
||||
|
||||
|
|
|
@ -620,6 +620,7 @@ int properties_init()
|
|||
return retval;
|
||||
}
|
||||
#elif defined(DXX_BUILD_DESCENT_II)
|
||||
|
||||
//initialize a pigfile, reading headers
|
||||
//returns the size of all the bitmap data
|
||||
void piggy_init_pigfile(const char *filename)
|
||||
|
@ -819,6 +820,7 @@ void piggy_new_pigfile(char *pigname)
|
|||
unsigned nframes;
|
||||
|
||||
const std::size_t len = p - AllBitmaps[i].name.data();
|
||||
cf_assert(len < AllBitmaps[i].name.size());
|
||||
memcpy(basename, AllBitmaps[i].name.data(), len);
|
||||
basename[len] = 0;
|
||||
|
||||
|
|
Loading…
Reference in a new issue