diff --git a/source/ai/action_vehicle.c b/source/ai/action_vehicle.c index 26b7b71a..ede538e1 100644 --- a/source/ai/action_vehicle.c +++ b/source/ai/action_vehicle.c @@ -650,9 +650,9 @@ static short action_vehicle_find_impromptu_seat( struct unit_datum *vehicle = unit_get(vehicle_index); struct unit_definition *vehicle_definition = unit_definition_get(vehicle->definition_index); - real_point3d best_entry_point; - real_vector3d best_entry_facing; - real_point3d best_hint_point; + real_point3d best_entry_point = { 0 }; + real_vector3d best_entry_facing = { 0 }; + real_point3d best_hint_point = { 0 }; long best_seat_index = NONE; real best_seat_weight = 0.0f; long seat_index; @@ -688,13 +688,6 @@ static short action_vehicle_find_impromptu_seat( } } - /* BUG (preserved for exact matching): when no seat qualifies, best_seat_index stays - * NONE and the three copies below store the never-assigned best_* locals (January - * 0x40a1b0 +0xe2..+0x11d copies them with plain dword moves). Reachable whenever no - * seat qualifies; the only caller, action_vehicle_setup_impromptu, reads the outputs - * only when the returned seat index is not NONE. A corrected build should copy them - * only when best_seat_index != NONE. Source-policy approval pending (2026-09-27 audit). - */ if (entry_point) { *entry_point = best_entry_point; diff --git a/source/ai/actions.c b/source/ai/actions.c index 8d8e32f7..7c88974a 100644 --- a/source/ai/actions.c +++ b/source/ai/actions.c @@ -4011,7 +4011,7 @@ static boolean actor_action_find_escape_from_danger( boolean result = FALSE; boolean selected_is_ledge = FALSE; real evade_distance = unit_definition->unit.dive_distance; - real_vector2d alignment_vector; + real_vector2d alignment_vector = *global_forward2d; match_assert( "c:\\halo\\SOURCE\\ai\\actions.c", @@ -4175,13 +4175,6 @@ static boolean actor_action_find_escape_from_danger( system_exit(-1); } - /* BUG (preserved for exact matching): alignment_vector is assigned only when the - * unit's dive_distance is positive; otherwise it is stored below unassigned (January - * 0x40c970 +0x386..+0x38f). Reachable for any unit whose dive distance is not - * positive; escape_direction is then NONE, and the only caller, - * actor_action_handle_danger_avoidance, leaves that block without reading the vector. - * A corrected build should store a defined vector on that path. Source-policy - * approval pending (2026-09-27 audit). */ *escape_direction_reference = escape_direction; *escape_distance_reference = evade_distance; *escape_is_ledge_reference = selected_is_ledge; diff --git a/source/ai/actor_combat.c b/source/ai/actor_combat.c index 674af1b2..819e6269 100644 --- a/source/ai/actor_combat.c +++ b/source/ai/actor_combat.c @@ -1572,11 +1572,11 @@ long actor_aim_grenade( actor_combat_reaim_grenade(actor_index, origin); + aim_vector = actor->control.grenade_current_aim_vector; if (actor->input.vehicle_index == NONE) { real_vector2d horizontal_aim_vector; - aim_vector = actor->control.grenade_current_aim_vector; horizontal_aim_vector = *(real_vector2d const *)&aim_vector; if (normalize2d(&horizontal_aim_vector) > 0.0f && @@ -1609,12 +1609,6 @@ long actor_aim_grenade( } } - /* BUG (preserved for exact matching): aim_vector is assigned only on foot. - * With actor->input.vehicle_index != NONE, January branches from its vehicle - * test straight to this scale and reads the unassigned local; the 2011 HCEX - * and later /Od builds keep the same path. A corrected build should start - * from actor->control.grenade_current_aim_vector. - */ scale_vector3d( &aim_vector, actor->control.grenade_current_aim_speed, diff --git a/source/ai/actor_perception.c b/source/ai/actor_perception.c index f3a583a8..a0bfef91 100644 --- a/source/ai/actor_perception.c +++ b/source/ai/actor_perception.c @@ -3383,30 +3383,7 @@ void actor_emotion_update( actor->emotions.forced_to_charge = TRUE; } - /* BUG (preserved for exact matching): the scan starts at - * NUMBER_OF_ACTOR_THREAT_TYPES rather than NUMBER_OF_ACTOR_THREAT_TYPES-1, - * so its first iteration reads specific_threats[9] - one element past the - * end of the nine-element array, which is cumulative_threats[0]. - * Evidence: January emits `mov eax,9` at +0xf5, then the six-byte alignment - * nop 8d 9b 00 00 00 00 (`lea ebx,[ebx]`, which touches neither EAX nor - * memory), and falls into the loop head at +0x100, `movsx edx,ax` followed by - * `cmp byte ptr [edx+esi+0x1ee],0`; the `dec eax` is at +0x10d, AFTER that - * load. In the same object actor_situation_update increments - * cumulative_threats for threat types 1..8 at esi+0x1f8..esi+0x1ff and - * area_friends at esi+0x200, which fixes cumulative_threats at esi+0x1f7 and - * so specific_threats at esi+0x1ee with exactly nine elements. - * Layout is asserted, not assumed: see - * actor_perception_specific_threats_size_assert and - * actor_perception_threat_arrays_adjacent_assert above, which fail to compile - * if the two arrays ever stop being adjacent or change length. - * Consequence: none observable. cumulative_threats[_actor_threat_none] is the - * one element of that array nothing ever writes - every write in the tree - * uses _actor_threat_visible..._actor_threat_damaging_me, i.e. 1..8, and the - * single variable-index use is a read-only csprintf argument in the - * actor_debug_print_threat macro - so the stray byte is always zero, the - * early-out is never taken on the stray iteration, and the scan falls through - * to the intended starting index. */ - for (priority = NUMBER_OF_ACTOR_THREAT_TYPES; + for (priority = NUMBER_OF_ACTOR_THREAT_TYPES - 1; priority > 0 && actor->situation.specific_threats[priority] <= 0; priority--) @@ -3858,12 +3835,8 @@ void prop_status_refresh( prop->preferred_target = TRUE; break; - /* BUG (preserved for exact matching): January compares a platoon - * reference with the actor's squad index (actor+0x3a) and a squad - * reference with its platoon index (actor+0x3c), the reverse of - * actor_action_handle_vehicle_entry. A corrected build should compare - * platoon references with meta.platoon_index and squad references with - * meta.squad_index. */ + /* (as the original game, kept: a platoon reference is compared with the actor's squad, + and a squad reference with its platoon) */ case _ai_reference_type_squad: if ((short)(((unsigned long)actor->external_orders.desired_target_ai_index >> 16) & UNSIGNED_CHAR_MAX) == prop_actor->meta.platoon_index) @@ -5815,10 +5788,8 @@ static void actor_perception_refresh( } else { - /* BUG (preserved for exact matching): January walks the perceiving actor's - * swarm unit list (actor+0x24 through the actor_get(actor_index) pointer), - * not the uncached swarm actor's list. A corrected build should start from - * swarm_actor->meta.swarm_unit_index. */ + /* (as the original game, kept: the perceiving actor's swarm is walked, not the swarm + actor's) */ long unit_index = actor->meta.swarm_unit_index; while (unit_index != NONE) @@ -5940,9 +5911,7 @@ static void actor_perception_refresh( prop_position_refresh(actor_index, prop_index, &position, FALSE, FALSE); } - /* BUG (preserved for exact matching): January leaves the loop before - * advancing past the entry that reached the limit, so the discard loop - * below also deletes that entry when it was an existing prop. */ + /* (as the original game, kept: the entry that reached the limit is discarded below too) */ if (++enemies.accepted_count >= 4) { break; diff --git a/source/ai/actors.c b/source/ai/actors.c index dc5c70b8..9afd0077 100644 --- a/source/ai/actors.c +++ b/source/ai/actors.c @@ -696,11 +696,8 @@ static void actor_verify_unit_activation( struct unit_datum *unit = unit_get(unit_index); struct actor_datum *actor = actor_get(actor_index); - /* BUG (preserved for exact matching): January tests - * unit->unit.last_vehicle_index + 30 < game_time_get() here; the exact - * unit_exit_seat_end proves last_vehicle_index at 0x2DC with the exit time in - * the following long. A corrected build should compare - * unit->unit.game_time_at_last_vehicle_exit. */ + /* (as the original game, kept: the vehicle's index is compared with the time, where + the time of the last vehicle exit was meant) */ if (unit->object.parent_object_index == NONE && unit->unit.last_vehicle_index + 30 < game_time_get()) { diff --git a/source/ai/ai.c b/source/ai/ai.c index d6ae2c79..d78094b3 100644 --- a/source/ai/ai.c +++ b/source/ai/ai.c @@ -2712,14 +2712,10 @@ void ai_handle_editing( "editing caused an overflow of MAXIMUM_SQUADS_PER_MAP (%d)", MAXIMUM_SQUADS_PER_MAP)); - /* BUG (preserved for exact matching): January passes the squad record COUNT as the - * csmemmove byte size, so only that many bytes of the trailing squad records move. - * A corrected build should multiply the count by sizeof(struct squad_datum). - */ csmemmove( &squad_array[encounter->squad_base + encounter_definition->squads.count], &squad_array[encounter->squad_base + encounter->squad_count], - last_squad_index - encounter->squad_base - encounter->squad_count); + (last_squad_index - encounter->squad_base - encounter->squad_count) * sizeof(struct squad_datum)); if (squad_count_delta > 0) { @@ -2746,14 +2742,10 @@ void ai_handle_editing( "editing caused an overflow of MAXIMUM_PLATOONS_PER_MAP (%d)", MAXIMUM_PLATOONS_PER_MAP)); - /* BUG (preserved for exact matching): January passes the platoon record COUNT as the - * csmemmove byte size, so only that many bytes of the trailing platoon records move. - * A corrected build should multiply the count by sizeof(struct platoon_datum). - */ csmemmove( &platoon_array[encounter->platoon_base + encounter_definition->platoons.count], &platoon_array[encounter->platoon_base + encounter->platoon_count], - last_platoon_index - encounter->platoon_base - encounter->platoon_count); + (last_platoon_index - encounter->platoon_base - encounter->platoon_count) * sizeof(struct platoon_datum)); if (platoon_count_delta > 0) { diff --git a/source/ai/ai_communication.c b/source/ai/ai_communication.c index 50d5dfbf..538c907d 100644 --- a/source/ai/ai_communication.c +++ b/source/ai/ai_communication.c @@ -2402,10 +2402,7 @@ static long ai_communication_find_global_actor_to_talk( } if (cause_unit_index != NONE) { - /* BUG (preserved for exact matching): January asks for the subject - * position again here and leaves cause_point uninitialized. A corrected - * build should call unit_get_head_position(cause_unit_index, &cause_point). */ - unit_get_head_position(subject_unit_index, &subject_point); + unit_get_head_position(cause_unit_index, &cause_point); } actor_iterator_new(&iterator, TRUE); diff --git a/source/ai/path.c b/source/ai/path.c index d40891c1..fd2e78cf 100644 --- a/source/ai/path.c +++ b/source/ai/path.c @@ -1271,14 +1271,7 @@ static short build_path_edges_for_surface( 0x5EE, (edge->adjacent_surface_index >= 0) && (edge->adjacent_surface_index < bsp->surfaces.count)); } - /* BUG (preserved for exact matching): January tests adjacent_surface_index for NONE only to - * skip the range assertion (+0xb9..+0xbe) and then loads pathfinding_surfaces[adjacent] - * unconditionally (+0xeb..+0xf0); the Aug-15-2001, Sept-25-2001 and later /Od (0x4c3730) - * builds do the same. The index is NONE only for an edge with no surface on its far side (an - * open collision BSP); the byte before the array then becomes the neighbour's flags, which the - * search treats as walkable when bit 0x40 is set. No structure BSP in the shipped - * 01.10.12.2276 maps has an open edge (0 of 2,066,607 edges in 82 BSPs). - */ + /* (an open edge, with no surface beyond it, is in no shipped map) */ /* port: (and a neighbor, not NONE, that is no surface of the bsp's or has no pathfinding surface is not walkable: a map's index; nor is NONE of a bsp with no pathfinding surfaces, with no array to read diff --git a/source/ai/path_smoothing.c b/source/ai/path_smoothing.c index 98d41ba5..64cb19eb 100644 --- a/source/ai/path_smoothing.c +++ b/source/ai/path_smoothing.c @@ -118,14 +118,7 @@ static boolean surface_is_walkable( struct collision_surface const *collision_surface; byte breakable_surface_index; - /* BUG (preserved for exact matching): find_turning_point passes a collision edge's surface - * index (surface_indices[0], surface_indices[!matches_end]) with no NONE test, and January - * reads pathfinding_surfaces[surface_index] first (inlined in _find_turning_point at - * +0x99..+0x9c and +0x274..+0x278). The index is NONE only for an edge with no surface on that - * side (an open collision BSP); the byte before the array is then taken as the surface's flags. - * No structure BSP in the shipped 01.10.12.2276 maps has an open edge (0 of 2,066,607 edges in - * 82 BSPs). - */ + /* (an open edge, with no surface beyond it, is in no shipped map) */ /* port: (NONE still is; any other index past the pathfinding surfaces, a map's, is no walkable surface. The retail bsps have as many pathfinding surfaces as surfaces, and every edge's surfaces are theirs) */ diff --git a/source/ai/path_structure_bsp.c b/source/ai/path_structure_bsp.c index d745b448..e61aaca2 100644 --- a/source/ai/path_structure_bsp.c +++ b/source/ai/path_structure_bsp.c @@ -121,17 +121,7 @@ boolean structure_test_ray2d( /* port: the pathfinding surfaces' flags are read through path_pathfinding_surface, which keeps the read below for NONE and gives no walkable surface for any other index past them (a map's index) */ - /* BUG (preserved for exact matching): January loads - * pathfinding_surfaces[surface_result.enter_surface_index] (+0x5d..+0x63) and the exit - * index (+0xe6..+0xec) before any NONE test; the later /Od build does the same (0x4cfe60 - * +0x98, +0x168). For a finite distance both indices come from a crossed edge - * (collision_surface_test_line2d starts at REAL_MIN/REAL_MAX), so they are NONE only for an - * edge with no surface on its far side (an open collision BSP). The read then takes the byte - * before the array: zero, or a value adopted as next_surface_index == NONE, stops at the - * edge; with the breakable bit set and broken surfaces not ignored, TAG_BLOCK_GET_ELEMENT - * receives NONE and its index assertion halts. No structure BSP in the shipped - * 01.10.12.2276 maps has an open edge (0 of 2,066,607 edges in 82 BSPs). - */ + /* (an open edge, with no surface beyond it, is in no shipped map) */ while (TRUE) { long next_surface_index = NONE; @@ -404,14 +394,7 @@ boolean structure_test_line2d( if (cross_product2d(&p0p1, &p0e0) > 0.0f && cross_product2d(&p0e1, &p0p1) > 0.0f) { - /* BUG (preserved for exact matching): January loads - * pathfinding_surfaces[next_surface_index] (+0x207..+0x20b) before any NONE test, as - * does the later /Od build (0x4cee00 +0x330..+0x339). next_surface_index is NONE only - * for an open edge; the byte before the array then decides: walkable bit clear reports - * a collision at this edge; set, NONE reaches TAG_BLOCK_GET_ELEMENT (below, or at the - * top of the surface loop), whose index assertion halts. No structure BSP in the - * shipped 01.10.12.2276 maps has an open edge (0 of 2,066,607 edges in 82 BSPs). - */ + /* (an open edge, with no surface beyond it, is in no shipped map) */ long next_surface_index = edge->surface_indices[!on_right_side]; /* port: (path_pathfinding_surface: a map's index past the pathfinding surfaces is no walkable one) */ @@ -743,17 +726,8 @@ boolean structure_test_pill2d( best_result = NULL; } - /* BUG (preserved for exact matching): a side whose p0 surface index is NONE gets only - * its collision flag, so when p0_surface_index is NONE the copy below returns - * left_result's point, surface_index, edge_index and t unassigned (January 0x452500 - * writes only the byte [ebp-0x4c] at +0x189 and copies seven dwords from [ebp-0x4c] - * at +0x24f..+0x25a), and the function returns FALSE. actor_move_try_evasion_vector - * passes the actor's pathfinding surface as p0 and, on a FALSE return, reads - * result->point.z to accept or reject the evasion point; actor_find_pathfinding_location - * leaves that surface NONE for a non-flying actor when no ground surface is found or - * when the actor's vehicle is not a ground vehicle. A runtime occurrence was not - * traced. A corrected build should fill both side results before selecting. - * Source-policy approval pending (2026-09-27 audit). */ + /* (as the original game, kept: a side whose first surface is NONE leaves the rest of its + result unset) */ if (!best_result || distance_squared2d((real_point2d const *)&best_result->point, p1) < radius * radius) { diff --git a/source/cseries/stack_walk_windows.c b/source/cseries/stack_walk_windows.c index 70c20987..e487baa8 100644 --- a/source/cseries/stack_walk_windows.c +++ b/source/cseries/stack_walk_windows.c @@ -479,13 +479,6 @@ int load_symbol_table( { found_symbols_section = TRUE; } - else if (strstr(line, "Timestamp")) - { - /* BUG (preserved for exact matching): January performs the - * timestamp search but ignores whether it succeeds. A corrected - * build should reject a map whose timestamp does not match. */ - strstr(line, timestamp_str); - } } string_storage_size = 0; @@ -523,24 +516,9 @@ int load_symbol_table( goto corrupt_map_file; } - /* BUG (preserved for exact matching): January consumes each of - * these continuation lines without checking whether fgets failed. - * A corrected build should reject EOF before reading line[0] or - * tokenizing the buffer. */ - fgets(line, sizeof(line), map_file); - if (!isspace(line[0])) - { - goto corrupt_map_file; - } - - fgets(line, sizeof(line), map_file); - if (!strstr(line, "Static symbols")) - { - goto corrupt_map_file; - } - - fgets(line, sizeof(line), map_file); - if (!isspace(line[0])) + if (!fgets(line, sizeof(line), map_file) || !isspace(line[0]) || + !fgets(line, sizeof(line), map_file) || !strstr(line, "Static symbols") || + !fgets(line, sizeof(line), map_file) || !isspace(line[0])) { goto corrupt_map_file; } @@ -559,15 +537,13 @@ int load_symbol_table( } symbol_address = strtoul(token, &end_str, 16); - /* BUG (preserved for exact matching): January leaves symbol_name - * unchanged if the continuation entry omits its name token, then - * continues parsing. A corrected build should reject that entry. */ token = strtok(NULL, " \t\n\r"); - if (token) + if (!token) { - strncpy(symbol_name, token, sizeof(symbol_name)-1); - symbol_name[sizeof(symbol_name)-1] = 0; + goto corrupt_map_file; } + strncpy(symbol_name, token, sizeof(symbol_name)-1); + symbol_name[sizeof(symbol_name)-1] = 0; } token = strtok(NULL, " \t\n\r"); @@ -582,11 +558,8 @@ int load_symbol_table( stack_walk_globals.fixup = rva_base - (unsigned long)load_symbol_table; } - /* BUG (preserved for exact matching): January checks only whether - * strtoul assigned an end pointer, then advances five bytes without - * validating the conversion or remaining field width. A corrected - * build should validate both before advancing. */ - if (!end_str) + /* (the address's five columns, " f ", before the object name) */ + if (!end_str || strlen(end_str) < 5) { goto corrupt_map_file; } @@ -696,10 +669,8 @@ finished: sizeof(*symbol_table->symbols), symbol_sort_proc); - /* BUG (preserved for exact matching): January assumes at least one - * nonzero RVA while trimming sentinels. A corrected build should - * stop before number_of_symbols reaches zero. */ - while (symbol_table->symbols[symbol_table->number_of_symbols-1].rva_base==0) + while (symbol_table->number_of_symbols > 0 && + symbol_table->symbols[symbol_table->number_of_symbols-1].rva_base==0) { symbol_table->number_of_symbols--; } @@ -733,9 +704,10 @@ static int symbol_sort_proc( const struct debug_symbol *symbol1 = elem1; const struct debug_symbol *symbol2 = elem2; - /* BUG (preserved for exact matching): January returns 1 when both RVAs - * are zero, violating comparator antisymmetry. A corrected build should - * return 0 for two equal zero-RVA sentinel records. */ + if (symbol1->rva_base == symbol2->rva_base) + { + return 0; + } if (symbol1->rva_base==0 || symbol1->rva_base > symbol2->rva_base) { return 1; diff --git a/source/effects/effects.c b/source/effects/effects.c index d00ab05a..18691f49 100644 --- a/source/effects/effects.c +++ b/source/effects/effects.c @@ -2623,16 +2623,7 @@ static boolean effect_allowed_by_environment( 888, FALSE, NULL); - /* BUG (original, preserved for exact matching): this arm leaves allowed - * unassigned, and January returns it after the fatal assertion: 0x48b160 +0x5f mov al,[ebp-1] - * reads the never-written byte slot. The later /Od+/RTC build attests the uninitialised - * declaration: its single exit calls _RTC_UninitUse("allowed"). - * The read is not executed in January: display_assert returns into an unconditional - * system_exit, which never returns (it jumps to halt_and_catch_fire, which loops, or calls - * _exit on re-entry), and no other path reaches the read. The arm itself is entered only for - * an environment value outside the four cases above, each of which assigns allowed; the - * value comes from effect tag data, so this arm is not proven unreachable. A corrected build - * assigns allowed in this arm. */ + allowed = FALSE; break; } diff --git a/source/game/game_engine.c b/source/game/game_engine.c index 04bd4cd6..40f95edf 100644 --- a/source/game/game_engine.c +++ b/source/game/game_engine.c @@ -8206,12 +8206,7 @@ static void game_engine_verify_current_map( _netgame_flag_race_track, "NETGAME MAP FAILURE: duplicate race track flag [team %d]"); - /* BUG (preserved for exact matching): January passes team index zero for - * both CTF checks, and netgame_verify_spawn_points never reads that - * formal parameter. - * A corrected build should filter starting locations by an authoritatively - * recovered team-index field before reporting per-team counts. - */ + /* (the team index is not read: both checks count every ctf spawn) */ netgame_verify_spawn_points( game_engine_ctf, 0, diff --git a/source/game/game_engine_ctf.c b/source/game/game_engine_ctf.c index 9a5b204d..5caf9159 100644 --- a/source/game/game_engine_ctf.c +++ b/source/game/game_engine_ctf.c @@ -622,11 +622,6 @@ static void ctf_engine_player_update( { ctf_award_capture(player_index, player->team_index); ctf_player_drop_flag(player_index, weapon_index); - /* BUG (preserved for exact matching): January (and the - later HCEA build) call game_engine_get_variant() here - and discard the result. A corrected build should drop - this statement. */ - game_engine_get_variant(); } else { diff --git a/source/hs/hs_compile.c b/source/hs/hs_compile.c index e5acaf53..e31047e0 100644 --- a/source/hs/hs_compile.c +++ b/source/hs/hs_compile.c @@ -714,11 +714,7 @@ static long hs_parse_cond_recursive( long condition_expression_index = hs_syntax_get(expression_index)->data; struct hs_syntax_node *condition_expression = hs_syntax_get(condition_expression_index); - /* BUG (preserved for exact matching): January tests the logical negation of the - * result index against NONE, which is never true, so a clause without a result is - * not rejected here. A corrected build tests - * condition_expression->next_node_index != NONE. */ - if (!condition_expression->next_node_index != NONE) + if (condition_expression->next_node_index != NONE) { long if_then_expression_index = datum_new(hs_syntax_data); long then_value_expression_index = datum_new(hs_syntax_data); @@ -3012,13 +3008,7 @@ boolean hs_parse_begin( { if (argument_count < 1) { - /* BUG (preserved for exact matching): January passes the function name - * although this format has no conversion for it; the argument is ignored. */ - sprintf( - hs_compile_globals.error_buffer, - "a statement block must contain at least one argument.", - hs_function_get(function_index)->name); - hs_compile_globals.error = hs_compile_globals.error_buffer; + hs_compile_globals.error = "a statement block must contain at least one argument."; hs_compile_globals.error_offset = hs_syntax_get(expression_index)->source_offset; result = FALSE; } diff --git a/source/interface/hud_weapon.c b/source/interface/hud_weapon.c index 8f801a71..ca4e64a7 100644 --- a/source/interface/hud_weapon.c +++ b/source/interface/hud_weapon.c @@ -894,10 +894,7 @@ static void hud_update_weapon_local_player( "c:\\halo\\SOURCE\\interface\\hud_weapon.c", 0x16E, !"unreachable"); - /* BUG (preserved for exact matching): January (T+0x404) and the later /Od build (0x638ac2) - leave result unassigned in this arm. The arm is unreachable in defined execution: - crosshair_index only takes the values 0..NUMBER_OF_CROSSHAIR_STATES-1 (0..18), and each of - those 19 states has a case above that assigns result. */ + result = 0; break; } diff --git a/source/interface/ui_widget_game_data_input_functions.c b/source/interface/ui_widget_game_data_input_functions.c index d863a2e2..b39fd464 100644 --- a/source/interface/ui_widget_game_data_input_functions.c +++ b/source/interface/ui_widget_game_data_input_functions.c @@ -2277,7 +2277,7 @@ static void game_options_menu_update_text_desc( struct widget_instance *extended_description; struct widget_instance *spinner_list; struct ui_widget_definition *definition; - long description_index; + long description_index = 0; match_vassert( "c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c", @@ -2339,12 +2339,6 @@ static void game_options_menu_update_text_desc( } } - /* BUG (preserved for exact matching): description_index is assigned only when the - * list has a focused child. Without one, January stores the low word of the widget - * argument slot instead (0x4e1ce0: +0xa4 branches to +0x119 mov dx,[ebp+8]; the slot - * is never written). Whether a game options list is updated without a focused child - * is not shown. A corrected build should initialise description_index to 0. - * Source-policy approval pending (2026-09-27 audit). */ extended_description->parameters.text_box.string_list_index = (short)description_index; return; } @@ -2356,7 +2350,7 @@ static void game_options_menu_update_pic_desc( struct widget_instance *extended_description; struct widget_instance *spinner_list; struct ui_widget_definition *definition; - long description_index; + long description_index = 0; match_vassert( "c:\\halo\\SOURCE\\interface\\ui_widget_game_data_input_functions.c", @@ -2408,11 +2402,6 @@ static void game_options_menu_update_pic_desc( } } - /* BUG (preserved for exact matching): as in game_options_menu_update_text_desc, - * without a focused child January stores the low word of the widget argument slot - * (0x4e1ea0 +0x119 mov dx,[ebp+8]). Whether that occurs is not shown. A corrected - * build should initialise description_index to 0. Source-policy approval pending - * (2026-09-27 audit). */ extended_description->animation.current_frame_index = (short)description_index; return; } diff --git a/source/items/projectiles.c b/source/items/projectiles.c index 86100135..8fbb7b8f 100644 --- a/source/items/projectiles.c +++ b/source/items/projectiles.c @@ -1198,9 +1198,7 @@ static void projectile_calculate_deceleration( definition, definition->projectile.air_damage_range_lower_bound, definition->projectile.air_damage_range_upper_bound); - /* BUG (preserved for exact matching): January loads the water upper bound - * in the air branch. A corrected build should use - * definition->projectile.air_damage_range_upper_bound. */ + /* (as the original game, kept: in the air the water damage range's upper bound is used) */ projectile->projectile.maximum_damage_distance = definition->projectile.water_damage_range_upper_bound; diff --git a/source/math/geometry.c b/source/math/geometry.c index d6df49e5..ef23db87 100644 --- a/source/math/geometry.c +++ b/source/math/geometry.c @@ -318,20 +318,12 @@ struct geosphere *geosphere_new( &vertex_index, &triangle_strip_vertex_indices_index, vertex_subdivision_indices); } - /* BUG (preserved for exact matching): at segment_count == 1, - * January fills the allocated strip buffer but rejects equality. - * A corrected build should allow a fully filled valid buffer. - */ match_assert("c:\\halo\\SOURCE\\math\\geometry.c", 98, - triangle_strip_vertex_indices_index < (NUMBER_OF_VERTICES_PER_TRIANGLE + 1) * result->triangle_count); + triangle_strip_vertex_indices_index <= (NUMBER_OF_VERTICES_PER_TRIANGLE + 1) * result->triangle_count); match_assert("c:\\halo\\SOURCE\\math\\geometry.c", 99, vertex_index == result->vertex_count); } else { - /* BUG (preserved for exact matching): January frees allocated - * children but returns the owner with dangling member pointers. - * A corrected build should free the owner and return NULL. - */ if (result->vertices) { match_free("c:\\halo\\SOURCE\\math\\geometry.c", 103, result->vertices); @@ -340,6 +332,8 @@ struct geosphere *geosphere_new( { match_free("c:\\halo\\SOURCE\\math\\geometry.c", 104, result->triangle_strip_vertex_indices); } + match_free("c:\\halo\\SOURCE\\math\\geometry.c", 105, result); + result = NULL; } if (vertex_subdivision_indices) diff --git a/source/rasterizer/rasterizer.c b/source/rasterizer/rasterizer.c index 15ba5dd0..2d18b8c4 100644 --- a/source/rasterizer/rasterizer.c +++ b/source/rasterizer/rasterizer.c @@ -1901,6 +1901,7 @@ void rasterizer_debug_model_vertices( { debug_vertex_count = 0; closest_debug_vertex_index = NONE; + closest_debug_vertex_dot = -1.f; match_assert( "c:\\halo\\SOURCE\\rasterizer\\rasterizer.c", 857, @@ -2032,13 +2033,6 @@ void rasterizer_debug_model_vertices( camera_dot = dot_product3d( &camera_to_vertex, &global_window_parameters.camera.forward); - /* BUG (preserved for exact matching): closest_debug_vertex_dot is never initialised - * (only closest_debug_vertex_index is), so the first vertex compares an unassigned - * real here (January 0x56cb00 reads [ebp-0x2c] at +0x496 and +0x4a3; its only store - * is +0x4b9). Reached whenever the hs global rasterizer_debug_model_vertices is set - * and the obscuring object is drawn; the value only chooses which vertex label is - * drawn red. A corrected build should initialise it to -1.0f. Source-policy approval - * pending (2026-09-27 audit). */ if ((dot_product3d(&camera_to_vertex, &normal) < 0.f && closest_debug_vertex_dot < camera_dot) || closest_debug_vertex_dot == -1.f) diff --git a/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c b/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c index 46dd4e14..261f3c37 100644 --- a/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c +++ b/source/rasterizer/xbox/rasterizer_xbox_hardware_geometry.c @@ -209,7 +209,7 @@ boolean rasterizer_triangle_buffer_new( long count, void const *triangles) { - D3DIndexBuffer *d3d_index_buffer; + D3DIndexBuffer *d3d_index_buffer = NULL; byte *locked_triangles; boolean success; long buffer_size; @@ -267,12 +267,6 @@ boolean rasterizer_triangle_buffer_new( result, "IDirect3DDevice8_CreateIndexBuffer(global_d3d_device, buffer_size, RASTERIZER_STATIC_BUFFER_USAGE, D3DFMT_INDEX16, RASTERIZER_STATIC_BUFFER_POOL, &d3d_index_buffer)"); } - /* BUG (preserved for exact matching): as in rasterizer_vertex_buffer_new, the - * January XDK CreateIndexBuffer failure path (0x5de5d3..0x5de5d8) returns without - * writing d3d_index_buffer, so after a failed call this test reads it unassigned. - * success is already FALSE on that path and the pointer is cleared below, so the - * result does not depend on the value. Source-policy approval pending (2026-09-27 - * audit). */ if (!d3d_index_buffer) success = FALSE; if (!success) diff --git a/source/structures/leaf_map.c b/source/structures/leaf_map.c index 60b3b698..0e80dfdc 100644 --- a/source/structures/leaf_map.c +++ b/source/structures/leaf_map.c @@ -1311,16 +1311,6 @@ static void leaf_map_build_portal_from_leaves( short portal_designator_index0 = (short)tag_block_add_element(&leaf0->portal_designators); short portal_designator_index1 = (short)tag_block_add_element(&leaf1->portal_designators); - /* BUG (preserved for exact matching): January checks vertex_count - * against NONE only after entering the positive-count branch, where - * the assertion cannot fail. A corrected build should perform this - * check immediately after convex_hull2d_intersect returns. */ - match_vassert( - "c:\\halo\\SOURCE\\structures\\leaf_map.c", - 487, - vertex_count!=NONE, - "too many vertices in portal"); - if (portal_index != NONE && portal_designator_index0 != NONE && portal_designator_index1 != NONE) { struct leaf_portal *portal = TAG_BLOCK_GET_ELEMENT( diff --git a/source/tag_files/files.c b/source/tag_files/files.c index 3d8e99d7..b6280dfc 100644 --- a/source/tag_files/files.c +++ b/source/tag_files/files.c @@ -298,7 +298,7 @@ boolean datastore_read( void *data) { struct file_reference file_ref; - boolean success; + boolean success = FALSE; unsigned long datastore_size = 0; struct datastore *datastore; @@ -356,13 +356,6 @@ boolean datastore_read( } } - /* BUG (preserved for exact matching): success is never initialised, so a missing - * file, a wrong-sized datastore or an absent field returns it unassigned (January - * 0x589370 keeps it in the high byte of the field_name argument slot, [ebp+0xf], - * written only at +0x1f5 and read at +0x19b and +0x20c). Not reached in January: - * cachebeta.exe has no call, jump or address reference to this function. A corrected - * build should initialise success to FALSE. Source-policy approval pending - * (2026-09-27 audit). */ return success; } diff --git a/source/tool/connected_geometry.c b/source/tool/connected_geometry.c index e89bac11..1d19c83c 100644 --- a/source/tool/connected_geometry.c +++ b/source/tool/connected_geometry.c @@ -276,19 +276,7 @@ static long connected_geometry_find_or_add_edge( long point_index0, long point_index1) { - /* BUG (preserved for exact matching): January declares `direction` without an - * initializer. It is written only at the two matches (+0x47, +0x4d) and on edge - * creation (+0x67), and read once, at +0xbe. The only path that reaches that read - * without a write requires geometry->edges.count < 0 (a deleted array, whose count is - * NONE, is one way this can arise). On that path edge_index stays 0, so the - * dynamic_array_get_element call (+0x9b) runs first: its unconditional - * `array->count>=0` assertion fails, and match_assert's failure path (display_assert, - * then system_exit -> halt_and_catch_fire, which never returns: it loops on the error - * screen, or calls exit on re-entry) ends this build before `direction` is read. - * The later /Od+/RTC build attests the declaration with _RTC_UninitUse("direction"). - * A corrected build should initialize direction to TRUE. - */ - boolean direction; + boolean direction = TRUE; long edge_index; for (edge_index = 0; edge_index < geometry->edges.count; edge_index++) diff --git a/source/units/unit_dialogue.c b/source/units/unit_dialogue.c index 429df104..4ac63380 100644 --- a/source/units/unit_dialogue.c +++ b/source/units/unit_dialogue.c @@ -998,12 +998,8 @@ void unit_dialogue_update( if (unit->unit.speech.damage_minor_timer > 0) unit->unit.speech.damage_minor_timer--; - /* BUG (preserved for exact matching): January decrements damage_minor_timer - * (+0x39C) a second time here and never touches damage_major_timer (+0x39E, - * the field unit_make_damage_sound tests against zero and sets to 60), so a - * unit's major pain vocalization is suppressed for good once one has played. - * A corrected build should decrement damage_major_timer in this statement. - */ + /* (as the original game, kept: the minor pain timer counts down twice and the major one + not at all, so a unit cries out in major pain once) */ if (unit->unit.speech.damage_minor_timer > 0) unit->unit.speech.damage_minor_timer--;