Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions port/linux/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1834,6 +1834,7 @@ Other changes:
| `cache/cache_files.c` | When a map's tags load and unload, the port finds the bitmaps that the high-res HUD replaces (`game/hud_hires_tags.c`), adds the tags of the menus to the menus' map (`game/menu_tags.c`), and plays the mods' tags (`game/mods.c`). |
| `cache/xbox_sound_cache.c`, `cache/xbox_texture_cache.c` | The samples of a mod's sound are copied from memory, and the pixels of a mod's bitmap read from its file and laid out for the hardware, at once (`game/mod_sounds.c`, `game/mod_bitmaps.c`); a mod's linear bitmap need not have rows of whole steps of the pitch. |
| `hs/hs.c` | The console's `mods_reload`, `mods_enable` and `mods_list`, which a client may run too. |
| `hs/hs_runtime.c`, `hs/object_lists.c`, `units/units.c`, `objects/scenery.c` | A script that holds an object or a list that no longer exists gets none, not a crash: a global, a function's result or an argument with a deleted object's index is none, and walking a list passes over the objects that are gone. `list_count` still counts them. |
| `interface/ui_widget.c`, `interface/ui_widget_event_handler_functions.c`, `interface/ui_widget_game_data_input_functions.c` | The main menu is the PC version's from `port/assets/menus` (`display.menus`); the menus' widgets can call the port's functions (`game/menu_functions.c`) and send the PC version's custom activation event; the widgets' memory is 256 KB, not 16 KB; the main menu and Multiplayer clear co-op's controllers, so that a gamepad going back to controller 1 is not a controller unplugged; the lobby's split screen players leave alone, and one who quits in game is not joined to the next game (`interface/player_ui.c`). |
| `interface/player_ui.c` | Fast setup opens the pregame screen through the port's menus (the lobby), as `interface/ui_widget.c` does. |
| `game/game_engine.c`, `game/game_engine.h`, `game/game_engine_slayer.c`, `game/game.c`, `game/aim_assist.c`, `game/players.c`, `objects/damage.c`, `objects/objects.c`, `units/units.c`, `items/weapons.c`, `saved games/playlist_profile.c`, `saved games/saved_game_files.c` | OpenCE's gametypes (`game/game_modes.c`, "OpenCE gametypes"): the gametype's PC options carry a mode and Hardcore with their options; the built-in ones are written after the Xbox's default gametypes; Infection's and Gun Game's game engines are Slayer's with their rules; SWAT's headshots, Hardcore's motion sensor, aim assist and restore of the killer; Infection's zombies' skulls, grenades, powerups, seats and melee. |
Expand Down
39 changes: 39 additions & 0 deletions source/hs/hs_runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,9 @@ static long hs_object_to_object_list(
static boolean hs_object_type_can_cast(
short actual_type,
short desired_type);
static long hs_value_still_exists(
short type,
long value);
static char const *hs_thread_format(
long thread_index);
static void hs_stack_pop(
Expand Down Expand Up @@ -1842,6 +1845,25 @@ boolean hs_can_cast(
}
}

/* port: an object or a list that a script holds can be gone when the script
uses it. A global keeps a vehicle's index after the vehicle is deleted, and a
list made for an argument is collected while a later argument's static script
sleeps. Maps do this, and Halo PC plays them, but here datum_get gives NULL for
it and the read through that crashes the game. Such a value is none, which is
already how a script says no object: an object's name gives none when that
object doesn't exist. */
static long hs_value_still_exists(
short type,
long value)
{
if (HS_TYPE_IS_OBJECT(type))
return object_try_and_get(value) ? value : NONE;
if (type==_hs_type_object_list)
return datum_try_and_get(object_list_header_data, value) ? value : NONE;

return value;
}

long hs_cast(
long thread_index,
short actual_type,
Expand All @@ -1851,6 +1873,13 @@ long hs_cast(
match_hs_assert("c:\\halo\\SOURCE\\hs\\hs_runtime.c", 0x5d8, thread_index,
hs_can_cast(actual_type, desired_type), "bad typecast.");

/* port: every global read and every function's or script's result comes
through here. Checked before the casts below, so no list is made of an
object that is gone */
value = hs_value_still_exists(
actual_type==_hs_passthrough ? desired_type : actual_type,
value);

if (actual_type!=desired_type &&
actual_type!=_hs_passthrough &&
!HS_TYPE_IS_OBJECT_NAME(desired_type))
Expand Down Expand Up @@ -3363,6 +3392,7 @@ static long *hs_arguments_evaluate(
long *values = hs_stack_allocate(thread_index, formal_parameter_count*sizeof(long));
short *argument_index = hs_stack_allocate(thread_index, sizeof(short));
long *expression_index = hs_stack_allocate(thread_index, sizeof(long));
short value_index;

/* port: none on a stack overflow (hs_stack_overflow): as for arguments
still being evaluated, the caller returns on NULL */
Expand Down Expand Up @@ -3399,6 +3429,15 @@ static long *hs_arguments_evaluate(
match_hs_assert("c:\\halo\\SOURCE\\hs\\hs_runtime.c", 0x3d1, thread_index,
*expression_index==NONE, "corrupted syntax tree.");

/* port: an argument was checked when it was evaluated, and a later one's
static script may have slept since (hs_value_still_exists) */
for (value_index = 0; value_index<formal_parameter_count; value_index++)
{
values[value_index] = hs_value_still_exists(
formal_parameters[value_index],
values[value_index]);
}

return values;
}

Expand Down
24 changes: 23 additions & 1 deletion source/hs/object_lists.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ symbols in this file:
#include "errors.h"
#include "data.h"
#include "reference_lists.h"
#include "objects/objects.h"

/* ---------- constants */

Expand All @@ -80,6 +81,8 @@ enum

/* ---------- prototypes */

static long object_list_skip_deleted(long object_index, long *reference_index);

/* ---------- globals */

struct data_array *object_list_header_data;
Expand Down Expand Up @@ -192,7 +195,10 @@ long object_list_get_next(
long object_list_index,
long *reference_index)
{
return reference_list_get_next_datum_index(object_list_data, reference_index);
/* port: (object_list_skip_deleted) */
return object_list_skip_deleted(
reference_list_get_next_datum_index(object_list_data, reference_index),
reference_index);
}

void object_list_add_reference(
Expand Down Expand Up @@ -277,9 +283,25 @@ long object_list_get_first(
if (object_list_index != NONE)
{
object_list_get_first_internal(object_list_index, reference_index, index);
/* port: (object_list_skip_deleted) */
index = object_list_skip_deleted(index, reference_index);
}

return index;
}

/* ---------- private code */

/* port: a list in a script's global outlives the objects it holds, and its
entry for a deleted object still has that object's index. Whoever walks the list
gets the objects that still exist (hs_value_still_exists says why). list_count
still counts the entries, as it always has. */
static long object_list_skip_deleted(
long object_index,
long *reference_index)
{
while (object_index!=NONE && !object_try_and_get(object_index))
object_index = reference_list_get_next_datum_index(object_list_data, reference_index);

return object_index;
}
5 changes: 3 additions & 2 deletions source/objects/scenery.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,10 @@ short scenery_get_animation_time(
{
struct animation *animation;
struct animation_graph *animation_graph;
struct scenery_datum *scenery = scenery_get(object_index);
/* port: a script's scenery may be none (hs_value_still_exists) */
struct scenery_datum *scenery = scenery_try_and_get(object_index);

if (TEST_FLAG(scenery->flags, 0))
if (scenery && TEST_FLAG(scenery->flags, 0))
{
animation_graph = animation_graph_definition_get(
scenery->object.object.animation.animation_graph_index);
Expand Down
12 changes: 8 additions & 4 deletions source/units/units.c
Original file line number Diff line number Diff line change
Expand Up @@ -1053,19 +1053,23 @@ void units_dispose(
void unit_kill(
long unit_index)
{
struct unit_datum *unit = unit_get(unit_index);
/* port: a script's unit may be none (hs_value_still_exists) */
struct unit_datum *unit = unit_try_and_get(unit_index);

SET_FLAG(unit->object.damage_flags, _object_die_act_of_god_bit, TRUE);
if (unit)
SET_FLAG(unit->object.damage_flags, _object_die_act_of_god_bit, TRUE);

return;
}

void unit_kill_silent(
long unit_index)
{
struct unit_datum *unit = unit_get(unit_index);
/* port: a script's unit may be none (hs_value_still_exists) */
struct unit_datum *unit = unit_try_and_get(unit_index);

SET_FLAG(unit->object.damage_flags, _object_die_act_of_god_silent_bit, TRUE);
if (unit)
SET_FLAG(unit->object.damage_flags, _object_die_act_of_god_silent_bit, TRUE);

return;
}
Expand Down
Loading
Loading