From 815e23fec4c6619b25e0f2433ad98e08d29fd4f6 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Wed, 5 Oct 2022 22:10:32 -0500 Subject: [PATCH 01/10] Update players_globals_t definition --- src/common.h | 8 ++++---- src/halo/game/players.c | 6 +++--- src/types.h | 14 +++++++++++++- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/common.h b/src/common.h index b0e75db..a0caa8a 100644 --- a/src/common.h +++ b/src/common.h @@ -15,6 +15,10 @@ extern const char *build_rev; extern const char *build_date; extern const char *build_ui_widget_text; +#define MAXIMUM_GAMEPADS 4 +#define MAXIMUM_NUMBER_OF_LOCAL_PLAYERS 4 +#define MAXIMUM_STRING_SIZE 0x2000 + #include "types.h" #include "inlines.h" #include "decl.h" @@ -38,10 +42,6 @@ extern const char *build_ui_widget_text; #define CLAMP(x, low, high) \ ((x) < (low) ? (low) : ((x) > (high) ? (high) : (x))) -#define MAXIMUM_GAMEPADS 4 -#define MAXIMUM_NUMBER_OF_LOCAL_PLAYERS 4 -#define MAXIMUM_STRING_SIZE 0x2000 - static const int _scenario_type_main_menu = 2; #ifdef DEBUG_BUILD diff --git a/src/halo/game/players.c b/src/halo/game/players.c index 04e730f..2657fb0 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -4,9 +4,9 @@ void players_initialize(void) team_data = game_state_data_new("teams", 16, sizeof(team_data_t)); players_globals = (players_globals_t *)game_state_malloc( "players globals", NULL, sizeof(players_globals_t)); - csmemset(&players_globals->unk_0[4], -1, 0x10u); - *(_DWORD *)players_globals->unk_0 = -1; - *(_WORD *)&players_globals->unk_0[36] = 0; + csmemset(&players_globals->local_player_indices[0], -1, 0x10u); + players_globals->unk_0 = -1; + players_globals->local_player_count = 0; player_control_globals = (player_control_globals_t *)game_state_malloc( "player control globals", 0, sizeof(player_control_globals_t)); } diff --git a/src/types.h b/src/types.h index f64a79b..5f9e7ae 100644 --- a/src/types.h +++ b/src/types.h @@ -88,7 +88,19 @@ typedef struct { /// size=0xb0 typedef struct { - char unk_0[0xb0]; + int unk_0; //< offset=0x00 see local_player_get_next, players_compute_local_player_count + int local_player_indices[MAXIMUM_NUMBER_OF_LOCAL_PLAYERS]; //< offset=0x04 + int local_dead_player_indices[MAXIMUM_NUMBER_OF_LOCAL_PLAYERS]; //< offset=0x14 + int16_t local_player_count; //< offset=0x24 + int16_t double_speed_ticks_remaining; //< offset=0x26 + bool are_all_dead; //< offset=0x28 + bool input_disabled; //< offset=0x29 + int16_t unk_tag_index; //< offset=0x2A bsp index? see players_reconnect_to_structure_bsp pulling from tag block at scnr+0x39C + int16_t respawn_failure; //< offset=0x2C enum, see _players_get_respawn_failure + bool teleported; //< offset=0x2E + char unk_flags; //< offset=0x2F bsp-related flags? see players_update_after_game + char combined_pvs[0x40]; //< offset=0x30 + char combined_pvs_local[0x40]; //< offset=0x70 } players_globals_t; /// size=0x110 From ad944a3817b36e20d63ad6363b3dd9fc7e7bbad1 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Wed, 5 Oct 2022 23:18:00 -0500 Subject: [PATCH 02/10] Add broken players_initialize_for_new_map --- kb.json | 14 ++++++++++++++ src/halo/game/players.c | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/kb.json b/kb.json index b3363c2..4f64761 100644 --- a/kb.json +++ b/kb.json @@ -340,6 +340,10 @@ { "decl": "void *data_iterator_next(data_iter_t *iterator);", "addr": "0x119810" + }, + { + "decl": "void data_make_valid(data_t *data);", + "addr": "0x119b20" } ] }, @@ -1151,6 +1155,10 @@ "name": "player_control.obj", "source": "game/player_control.c", "functions": [ + { + "decl": "void player_control_dispose(void);", + "addr": "0xb63f0" + }, { "decl": "void player_control_initialize_for_new_map(void);", "addr": "0xb85c0" @@ -1248,6 +1256,12 @@ { "name": "players.obj", "source": "game/players.c", + "data": [ + { + "decl": "char unk_46B668[64];", + "addr": "0x46b668" + } + ], "functions": [ { "decl": "void players_initialize(void);", diff --git a/src/halo/game/players.c b/src/halo/game/players.c index 2657fb0..8cab9f9 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -10,3 +10,20 @@ void players_initialize(void) player_control_globals = (player_control_globals_t *)game_state_malloc( "player control globals", 0, sizeof(player_control_globals_t)); } + +void players_initialize_for_new_map(void) +{ + player_control_dispose(); + csmemset(&players_globals, 0, sizeof(players_globals_t)); + csmemset(&players_globals->local_player_indices[0], -1, 0x10u); + csmemset(&players_globals->local_dead_player_indices[0], -1, 0x10u); + players_globals->unk_0 = -1; + players_globals->input_disabled = false; + players_globals->double_speed_ticks_remaining = 0; + players_globals->are_all_dead = false; + players_globals->unk_tag_index = -1; + players_globals->respawn_failure = 0; + data_make_valid(player_data); + data_make_valid(team_data); + csmemset(&unk_46B668, -1, 64); +} From 4a80d1adcafd89d25afb08e7ca782b6ab3262f82 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Thu, 6 Oct 2022 00:13:33 -0500 Subject: [PATCH 03/10] Fix players_initialize_for_new_map --- src/halo/game/players.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/halo/game/players.c b/src/halo/game/players.c index 8cab9f9..13e69a0 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -14,7 +14,7 @@ void players_initialize(void) void players_initialize_for_new_map(void) { player_control_dispose(); - csmemset(&players_globals, 0, sizeof(players_globals_t)); + csmemset(players_globals, 0, sizeof(players_globals_t)); csmemset(&players_globals->local_player_indices[0], -1, 0x10u); csmemset(&players_globals->local_dead_player_indices[0], -1, 0x10u); players_globals->unk_0 = -1; From 1e8d0779353eb95a253df566a922b3a0449c4509 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Thu, 6 Oct 2022 01:52:25 -0500 Subject: [PATCH 04/10] wip --- kb.json | 34 ++++++++++++++- src/common.h | 1 + src/halo/game/players.c | 94 +++++++++++++++++++++++++++++++++++++++++ src/types.h | 4 +- 4 files changed, 131 insertions(+), 2 deletions(-) diff --git a/kb.json b/kb.json index 4f64761..bed95a4 100644 --- a/kb.json +++ b/kb.json @@ -333,6 +333,10 @@ "decl": "void data_make_invalid(data_t *data);", "addr": "0x119550" }, + { + "decl": "void datum_delete(data_t *data, int datum_handle);", + "addr": "0x1196d0" + }, { "decl": "void data_iterator_new(data_iter_t *iter, data_t *data);", "addr": "0x1197b0" @@ -835,6 +839,10 @@ "decl": "bool input_key_is_down(uint16_t);", "addr": "0xcf560" }, + { + "decl": "bool input_has_gamepad(uint16_t);", + "addr": "0xcf6c0" + }, { "decl": "void input_update(void);", "addr": "0xd0120" @@ -1258,7 +1266,7 @@ "source": "game/players.c", "data": [ { - "decl": "char unk_46B668[64];", + "decl": "char unk_46B668[16 * MAXIMUM_NUMBER_OF_LOCAL_PLAYERS];", "addr": "0x46b668" } ], @@ -1279,6 +1287,30 @@ "decl": "void players_dispose(void);", "addr": "0xba240" }, + { + "decl": "void *machine_get_player_list(int16_t);", + "addr": "0xba270" + }, + { + "decl": "bool local_player_exists(int16_t);", + "addr": "0xba2e0" + }, + { + "decl": "int find_unused_local_player_index();", + "addr": "0xba340" + }, + { + "decl": "void player_delete(int);", + "addr": "0xba390" + }, + { + "decl": "int16_t players_get_respawn_failure(void);", + "addr": "0xba3b0" + }, + { + "decl": "int local_player_get_player_index(int16_t);", + "addr": "0xba3c0" + }, { "decl": "int local_player_set_player_index(unsigned __int16 a1, int a2);", "addr": "0xba410" diff --git a/src/common.h b/src/common.h index a0caa8a..b133788 100644 --- a/src/common.h +++ b/src/common.h @@ -15,6 +15,7 @@ extern const char *build_rev; extern const char *build_date; extern const char *build_ui_widget_text; +#define NONE -1 #define MAXIMUM_GAMEPADS 4 #define MAXIMUM_NUMBER_OF_LOCAL_PLAYERS 4 #define MAXIMUM_STRING_SIZE 0x2000 diff --git a/src/halo/game/players.c b/src/halo/game/players.c index 13e69a0..cf17d2e 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -27,3 +27,97 @@ void players_initialize_for_new_map(void) data_make_valid(team_data); csmemset(&unk_46B668, -1, 64); } + +void players_dispose_from_old_map(void) +{ + data_make_invalid(player_data); + data_make_invalid(team_data); +} + +void players_dispose(void) +{ + if (player_data) + player_data = NULL; + + if (team_data) + team_data = NULL; + + if (players_globals) + players_globals = NULL; +} + +void *machine_get_player_list(int16_t player_index) +{ + return (char *)&unk_46B668 + 16 * player_index; +} + +// TODO: int __usercall machine_add_player@(unsigned __int16 a1@, int a2) + +bool local_player_exists(int16_t player_index) +{ + player_data_t* player; + data_iter_t iter; + + data_iterator_new(&iter, player_data); + player = data_iterator_next(&iter); + if (!player) + return false; + + while (player->local_player_index != player_index) + { + player = data_iterator_next(&iter); + if (!player) + return false; + } + return true; +} + +int find_unused_local_player_index() +{ + int v0; // edi + int v1; // esi + int v2; // esi + + v0 = -1; + v1 = 0; + while (!input_has_gamepad(v1) || local_player_exists(v1)) + { + if (++v1 >= 4) + goto LABEL_7; + } + v0 = v1; + if (v1 != -1) + return v0; + LABEL_7: + v2 = 0; + while (local_player_exists(v2)) + { + if (++v2 >= 4) + return v0; + } + return v2; +} + +void player_delete(int player_datum) +{ + datum_delete(player_data, player_datum); +} + +int16_t players_get_respawn_failure(void) +{ + return players_globals->respawn_failure; +} + +int local_player_get_player_index(int16_t local_player_index) +{ + int player_index; + + assert_halt(local_player_index>=NONE && local_player_indexlocal_player_indices[local_player_index]; + + return player_index; +} diff --git a/src/types.h b/src/types.h index 5f9e7ae..0206653 100644 --- a/src/types.h +++ b/src/types.h @@ -78,7 +78,9 @@ typedef struct { /// size=0xd4 typedef struct { - char unk_0[0xd4]; + char unk0[2]; + int16_t local_player_index; + char unk_0[0xd0]; } player_data_t; /// size=0x40 From d79b40d38a1cc27904f046cbc3a6e2df277af336 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Sat, 8 Oct 2022 19:07:16 -0500 Subject: [PATCH 05/10] wip --- kb.json | 56 +++++++++++-- src/halo/game/players.c | 167 ++++++++++++++++++++++++++++++++++++-- src/halo/interface/hud.c | 2 +- src/halo/main/main.c | 16 ++-- src/types.h | 168 ++++++++++++++++++++++++++++++++++----- 5 files changed, 364 insertions(+), 45 deletions(-) diff --git a/kb.json b/kb.json index bed95a4..3e4a9e3 100644 --- a/kb.json +++ b/kb.json @@ -325,6 +325,10 @@ "decl": "void data_initialize(data_t *data, char *name, __int16 maximum_count, __int16 size);", "addr": "0x1191a0" }, + { + "decl": "void *datum_get(data_t *data, datum_index_t index);", + "addr": "0x119320" + }, { "decl": "void data_verify(data_t *data);", "addr": "0x1193f0" @@ -334,7 +338,7 @@ "addr": "0x119550" }, { - "decl": "void datum_delete(data_t *data, int datum_handle);", + "decl": "void datum_delete(data_t *data, datum_index_t index);", "addr": "0x1196d0" }, { @@ -1096,7 +1100,7 @@ "addr": "0x8a4d0" }, { - "decl": "void *observer_get_camera(unsigned __int16 local_player_index);", + "decl": "void *observer_get_camera(datum_index_t player);", "addr": "0x8a4e0" }, { @@ -1300,7 +1304,7 @@ "addr": "0xba340" }, { - "decl": "void player_delete(int);", + "decl": "void player_delete(datum_index_t);", "addr": "0xba390" }, { @@ -1308,23 +1312,59 @@ "addr": "0xba3b0" }, { - "decl": "int local_player_get_player_index(int16_t);", + "decl": "int local_player_get_player_index(int16_t local_player_index);", "addr": "0xba3c0" }, { - "decl": "int local_player_set_player_index(unsigned __int16 a1, int a2);", + "decl": "void local_player_set_player_index(int16_t local_player_index, datum_index_t index);", "addr": "0xba410" }, { - "decl": "__int16 local_player_count(void);", + "decl": "int16_t local_player_count(void);", "addr": "0xba4b0" }, { - "decl": "__int16 local_player_get_next(__int16 a1);", + "decl": "bool players_are_all_dead(void);", + "addr": "0xba5e0" + }, + { + "decl": "void* players_get_combined_pvs_local(void);", + "addr": "0xba6b0" + }, + { + "decl": "void* players_get_combined_pvs(void);", + "addr": "0xba6c0" + }, + { + "decl": "void player_input_enable(bool);", + "addr": "0xba6d0" + }, + { + "decl": "bool player_input_enabled(void);", + "addr": "0xba6f0" + }, + { + "decl": "bool any_player_is_dead(void);", + "addr": "0xba800" + }, + { + "decl": "datum_index_t local_player_get_next(datum_index_t local_player);", "addr": "0xba4c0" }, { - "decl": "int player_new(unsigned __int16 a1, int a2, unsigned __int16 a3, char *a4);", + "decl": "int players_compute_local_player_count(void);", + "addr": "0xbadf0" + }, + { + "decl": "void player_examine_nearby_unit(void);", + "addr": "0xbae10" + }, + { + "decl": "void player_reset_action_result(void);", + "addr": "0xbaeb0" + }, + { + "decl": "datum_index_t player_new(unsigned __int16 a1, int a2, unsigned __int16 a3, char *a4);", "addr": "0xbb2f0" }, { diff --git a/src/halo/game/players.c b/src/halo/game/players.c index cf17d2e..cb393fc 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -4,7 +4,7 @@ void players_initialize(void) team_data = game_state_data_new("teams", 16, sizeof(team_data_t)); players_globals = (players_globals_t *)game_state_malloc( "players globals", NULL, sizeof(players_globals_t)); - csmemset(&players_globals->local_player_indices[0], -1, 0x10u); + csmemset(&players_globals->local_players[0], -1, sizeof(datum_index_t) * MAXIMUM_NUMBER_OF_LOCAL_PLAYERS); players_globals->unk_0 = -1; players_globals->local_player_count = 0; player_control_globals = (player_control_globals_t *)game_state_malloc( @@ -15,8 +15,8 @@ void players_initialize_for_new_map(void) { player_control_dispose(); csmemset(players_globals, 0, sizeof(players_globals_t)); - csmemset(&players_globals->local_player_indices[0], -1, 0x10u); - csmemset(&players_globals->local_dead_player_indices[0], -1, 0x10u); + csmemset(&players_globals->local_players[0], -1, sizeof(datum_index_t) * MAXIMUM_NUMBER_OF_LOCAL_PLAYERS); + csmemset(&players_globals->local_dead_players[0], -1, sizeof(datum_index_t) * MAXIMUM_NUMBER_OF_LOCAL_PLAYERS); players_globals->unk_0 = -1; players_globals->input_disabled = false; players_globals->double_speed_ticks_remaining = 0; @@ -25,7 +25,7 @@ void players_initialize_for_new_map(void) players_globals->respawn_failure = 0; data_make_valid(player_data); data_make_valid(team_data); - csmemset(&unk_46B668, -1, 64); + csmemset(&unk_46B668, -1, 16 * MAXIMUM_NUMBER_OF_LOCAL_PLAYERS); } void players_dispose_from_old_map(void) @@ -98,9 +98,9 @@ int find_unused_local_player_index() return v2; } -void player_delete(int player_datum) +void player_delete(datum_index_t player) { - datum_delete(player_data, player_datum); + datum_delete(player_data, player); } int16_t players_get_respawn_failure(void) @@ -117,7 +117,160 @@ int local_player_get_player_index(int16_t local_player_index) if (local_player_index == NONE) player_index = NONE; else - player_index = players_globals->local_player_indices[local_player_index]; + player_index = players_globals->local_players[local_player_index].handle; return player_index; } + +void local_player_set_player_index(int16_t local_player_index, datum_index_t index) +{ + assert_halt(local_player_index>=0 && local_player_indexlocal_players[local_player_index].handle != -1) { + player_data_t* player = datum_get(player_data, players_globals->local_players[local_player_index]); + player->local_player_index = -1; + } + + players_globals->local_players[local_player_index] = index; + if (index.handle != -1) + { + player_data_t* player = datum_get(player_data, players_globals->local_players[local_player_index]); + player->local_player_index = local_player_index; + } +} + +int16_t local_player_count(void) +{ + return players_globals->local_player_count; +} + +datum_index_t local_player_get_next(datum_index_t local_player) +{ + datum_index_t next_player = INVALID_DATUM_HANDLE; + datum_index_t *player = &players_globals->local_players[0]; + + for (int i=0; ihandle != -1 && i > local_player.index && (i < next_player.index || next_player.index == -1)) { + next_player.handle = i; + } + player++; + } + + return next_player; +} + +// TODO: player_index_from_unit_index +// TODO: player_died + +bool players_are_all_dead(void) +{ + return players_globals->are_all_dead; +} + +// TODO: players_set_local_player_unit + +void* players_get_combined_pvs_local(void) +{ + return players_globals->combined_pvs_local; +} + +void* players_get_combined_pvs(void) +{ + return players_globals->combined_pvs; +} + +void player_input_enable(bool enabled) +{ + players_globals->input_disabled = enabled == 0; +} + +bool player_input_enabled(void) +{ + return players_globals->input_disabled == 0; +} + +// TODO: any_player_is_in_the_air + +bool any_player_is_dead(void) +{ + player_data_t* player; + data_iter_t iter; + + data_iterator_new(&iter, player_data); + player = data_iterator_next(&iter); + + if (!player) + return false; + + while (player->slave_unit_index.handle != -1) + { + player = data_iterator_next(&iter); + if ( !player ) + return false; + } + + return true; +} + +// TODO: is_player_in_trigger +// TODO: player_pseudo_kill +// TODO: player_control_fix_for_loaded_game_state +// TODO: player_get_starting_location_count +// TODO: player_get_starting_location +// TODO: placement_data_set_change_color +// TODO: create_weapon +// TODO: players_compute_combined_pvs + +int players_compute_local_player_count() +{ + int count = 0; + + for (int i=0; ilocal_players[i].handle != -1) + count++; + } + + return count; +} + +void player_examine_nearby_unit() +{ + +} + +// TODO: unit_should_autopick_weapon +// TODO: player_reset_action_result (eax = player datum index) +// TODO: player_handle_weapon_swap +// TODO: player_over_shield_screen_effect +// TODO: player_active_camo_screen_effect +// TODO: player_health_pack_screen_effect +// TODO: player_powerup_on +// TODO: player_powerup_additional +// TODO: player_powerup_off +// TODO: players_handle_deleted_object +// TODO: direction3d random_direction3d(int seed); +// TODO: valid_real_vector2d +// TODO: player_new +// TODO: player_add_equipment +// TODO: player_aiming_vector_from_facing +// TODO: player_teleport_internal +// TODO: player_teleport +// TODO: find_best_starting_location_index +// TODO: player_spawn +// TODO: player_set_action_result +// TODO: player_handle_action +// TODO: player_handle_powerup +// TODO: player_handle_powerup_minor +// TODO: player_update_powerups +// TODO: players_debug_render +// TODO: debug_player_teleport +// TODO: players_respawn_coop +// TODO: player_teleport_on_bsp_switch +// TODO: players_reconnect_to_structure_bsp +// TODO: player_examine_nearby_vehicle +// TODO: player_examine_nearby_device +// TODO: player_handle_powerup_equipment +// TODO: players_update_before_game +// TODO: player_examine_nearby_item +// TODO: player_examine_nearby_objects +// TODO: players_update_after_game diff --git a/src/halo/interface/hud.c b/src/halo/interface/hud.c index 5364610..c6020e7 100644 --- a/src/halo/interface/hud.c +++ b/src/halo/interface/hud.c @@ -9,6 +9,6 @@ void hud_load(bool a1) } scripted_hud_messages_clear(); if (v1 != -1) { - hud_print_message(local_player_get_next(-1), hud_get_item_string(v1)); + hud_print_message(local_player_get_next(INVALID_DATUM_HANDLE).index, hud_get_item_string(v1)); } } diff --git a/src/halo/main/main.c b/src/halo/main/main.c index 80e6b77..5e753ab 100644 --- a/src/halo/main/main.c +++ b/src/halo/main/main.c @@ -9,7 +9,7 @@ void create_local_players(void) { int i; int j; - int player; + datum_index_t player; int16_t gamepad_index; int16_t assigned_controllers[4]; int16_t desired_controllers[4]; @@ -197,14 +197,14 @@ void main_game_render(double a2) void *camera; int num_players; int num_screens; - __int16 next_player; + datum_index_t next_player; lock_global_random_seed(); collision_log_continue_period(1); sound_render(); force_single_screen = game_engine_force_single_screen(); - next_player = -1; + next_player.handle = -1; num_screens = CLAMP(local_player_count(), 1, 4); num_players = num_screens; @@ -221,17 +221,17 @@ void main_game_render(double a2) ¤t_window->unk_140); if (!force_single_screen && player_index < num_screens) { - if (!byte_325714 || next_player == -1) { + if (!byte_325714 || next_player.handle == -1) { if (word_46DA0C == 3) { - next_player = 0; + next_player.handle = 0; } else { next_player = local_player_get_next(next_player); } } - current_window->player = next_player; + current_window->local_player_index = next_player.index; camera = observer_get_camera(next_player); } else { - current_window->player = -1; + current_window->local_player_index = -1; } set_window_camera_values(current_window, camera); @@ -241,7 +241,7 @@ void main_game_render(double a2) current_window = &window[num_players]; compute_window_bounds(0, 1, ¤t_window->unk_132, ¤t_window->unk_140); - current_window->player = -1; + current_window->local_player_index = -1; current_window->unk_2 = 1; set_window_camera_values(current_window, 0); diff --git a/src/types.h b/src/types.h index 0206653..635c320 100644 --- a/src/types.h +++ b/src/types.h @@ -41,6 +41,16 @@ static const bool false = 0; #pragma pack(1) +typedef union { + int32_t handle; + struct { + int16_t index; + int16_t salt; + }; +} datum_index_t; + +static const datum_index_t INVALID_DATUM_HANDLE = { -1 }; + /// size=0x10c typedef struct { uint32_t unk_0; ///< offset=0x00 @@ -78,9 +88,125 @@ typedef struct { /// size=0xd4 typedef struct { - char unk0[2]; + char unk0[2]; // salt? and this is actually a datum index? int16_t local_player_index; - char unk_0[0xd0]; + + // .text:000AC599 add ecx, 4 + // .text:000BB398 mov word ptr [esi+1Ah], 0 ; null terminator + wchar_t player_name[12]; + + int32_t unk_28; // .text:000BB3A8 mov [esi+1Ch], edi + + // .text:00085A85 cmp [eax+20h], esi datum_index_t team? or raw index - .text:000B1719 mov ecx, dword_456BA8[eax*4] + // .text:000AD07B mov ax, [edx+20h] + // .text:000BB3B9 mov dword ptr [esi+20h], 1 + int32_t unk_32; + + int32_t unk_36; // .text:000BAEC6 mov dword ptr [eax+24h], 0FFFFFFFFh + int16_t unk_40; // .text:000BAEC0 mov word ptr [eax+28h], 0 + int16_t unk_42; // .text:000BC0C1 mov [ebx+2Ah], ax + int16_t unk_44; // .text:000A8CF3 mov eax, [esi+2Ch] + + int16_t unk_46; + + int32_t unk_48; // .text:000AF707 mov edx, [esi+30h] + datum_index_t slave_unit_index; // mov eax, [esi+34h] + datum_index_t last_slave_unit_index; // .text:00085C51 mov eax, [eax+38h] + + // .text:000BAD03 mov [esi+3Ch], ax + // .text:000BB951 mov word ptr [edi+3Ch], 0FFFFh + int16_t unk_60; + int16_t unk_62; // .text:000BD4CD mov [edx+3Eh], al + int32_t unk_64; // .text:000BB3AF mov [esi+40h], edi + + char unk_68[36]; + + // .text:000BBF8E lea ecx, [edi+68h] + // .text:000BC391 cmp word ptr [ebx+esi*2+68h], 0 + // .text:000BC404 add [ebx+esi*2+68h], dx + // .text:000D12A4 movsx ecx, word ptr [edi+6Ah] + int16_t unk_104; + int16_t unk_106; + + // .text:000A81F8 mov dword ptr [eax+6Ch], 3F800000h speed for score + // .text:000B4C27 fld dword ptr [esi+6Ch] + // .text:001A5A9C fld dword ptr [eax+6Ch] + float unk_108; + + // .text:000A81FF mov [eax+70h], ecx + // .text:000AD696 mov dword ptr [esi+70h], 0FFFFFFFFh + uint32_t unk_112; + + // .text:000A998C mov [eax+74h], edx + // .text:000A81F2 mov [eax+74h], ecx + uint32_t unk_116; + + // .text:000A998F mov [eax+78h], ecx + // .text:000A81F5 mov [eax+78h], ecx + uint32_t unk_120; + + uint32_t unk_124; // .text:000A8202 mov [eax+7Ch], ecx + uint32_t unk_128; // .text:000AC424 mov ecx, [esi+80h] + uint32_t unk_132; // .text:000A8BFA mov eax, [eax+84h] + + // .text:000B3916 mov dword ptr [eax+88h], 0 + // .text:000B4B26 mov dword ptr [eax+88h], 0FFFFFFFFh + uint32_t unk_136; + + uint16_t unk_140; + + uint16_t unk_142; // .text:000B56A3 mov word ptr [esi+8Eh], 1 + uint16_t unk_144; // .text:000B56AE inc word ptr [esi+90h] + uint16_t unk_146; // .text:000B575C mov [eax+92h], si + uint16_t unk_148; // .text:000B576C mov [eax+94h], si + uint16_t unk_150; // .text:000B5763 mov word ptr [eax+96h], 0FFFFh + uint16_t unk_152; // .text:000ABE0C movsx edx, word ptr [ebx+98h] + + char unk_154[6]; + + uint16_t unk_160; // .text:000ABE16 movsx eax, word ptr [ebx+0A0h] + + char unk_162[6]; + + uint16_t unk_168; // .text:000B58E6 inc word ptr [esi+0A8h] + + // .text:00086E9C cmp [eax+0AAh], bx + // .text:000A8C6A movsx edx, word ptr [eax+0AAh] + uint16_t unk_170; + + uint16_t unk_172; // .text:000B5749 inc word ptr [eax+0ACh] + + char unk_174[10]; + + uint32_t unk_184; // .text:000B569D mov [esi+0B8h], edx + + uint32_t unk_188; + + // .text:000AE80F add eax, 0C0h memset size of 4 (array of two words?) + // .text:000B166F inc word ptr [esi+0C0h] + // .text:000B0F78 inc word ptr [esi+0C2h] + uint16_t unk_192; + uint16_t unk_194; + + // .text:000B008D inc word ptr [edi+0C4h] + // .text:000B04FD movsx eax, word ptr [eax+0C4h] score + uint16_t unk_196; + + uint16_t unk_198; // padding? + + uint32_t unk_200; // .text:000BDC78 mov eax, [esi+0C8h] + + // .text:000A71F0 mov eax, [esi+0CCh] + // .text:000C9AD0 cmp [eax+0CCh], edi + uint32_t unk_204; + + bool unk_208; // .text:000BDC70 mov al, [esi+0D0h] + + // .text:000A71FB mov cl, [esi+0D1h] + // .text:000A720F mov byte ptr [esi+0D1h], 1 + bool unk_209; + + uint16_t unk_210; } player_data_t; /// size=0x40 @@ -90,19 +216,19 @@ typedef struct { /// size=0xb0 typedef struct { - int unk_0; //< offset=0x00 see local_player_get_next, players_compute_local_player_count - int local_player_indices[MAXIMUM_NUMBER_OF_LOCAL_PLAYERS]; //< offset=0x04 - int local_dead_player_indices[MAXIMUM_NUMBER_OF_LOCAL_PLAYERS]; //< offset=0x14 - int16_t local_player_count; //< offset=0x24 - int16_t double_speed_ticks_remaining; //< offset=0x26 - bool are_all_dead; //< offset=0x28 - bool input_disabled; //< offset=0x29 - int16_t unk_tag_index; //< offset=0x2A bsp index? see players_reconnect_to_structure_bsp pulling from tag block at scnr+0x39C - int16_t respawn_failure; //< offset=0x2C enum, see _players_get_respawn_failure - bool teleported; //< offset=0x2E - char unk_flags; //< offset=0x2F bsp-related flags? see players_update_after_game - char combined_pvs[0x40]; //< offset=0x30 - char combined_pvs_local[0x40]; //< offset=0x70 + int unk_0; //< offset=0x00 see local_player_get_next, players_compute_local_player_count + datum_index_t local_players[MAXIMUM_NUMBER_OF_LOCAL_PLAYERS]; //< offset=0x04 + datum_index_t local_dead_players[MAXIMUM_NUMBER_OF_LOCAL_PLAYERS]; //< offset=0x14 + int16_t local_player_count; //< offset=0x24 + int16_t double_speed_ticks_remaining; //< offset=0x26 + bool are_all_dead; //< offset=0x28 + bool input_disabled; //< offset=0x29 + int16_t unk_tag_index; //< offset=0x2A bsp index? see players_reconnect_to_structure_bsp pulling from tag block at scnr+0x39C + int16_t respawn_failure; //< offset=0x2C enum, see _players_get_respawn_failure + bool teleported; //< offset=0x2E + char unk_flags; //< offset=0x2F bsp-related flags? see players_update_after_game + char combined_pvs[0x40]; //< offset=0x30 + char combined_pvs_local[0x40]; //< offset=0x70 } players_globals_t; /// size=0x110 @@ -195,12 +321,12 @@ typedef struct { /// size=0xAC typedef struct { - __int16 player; ///< offset=0x00 - bool unk_2; ///< offset=0x02 - char unk_3[129]; ///< offset=0x03 - viewport_bounds_t unk_132; ///< offset=0x84 - viewport_bounds_t unk_140; ///< offset=0x8c - char unk_148[24]; ///< offset=0x94 + __int16 local_player_index; ///< offset=0x00 + bool unk_2; ///< offset=0x02 + char unk_3[129]; ///< offset=0x03 + viewport_bounds_t unk_132; ///< offset=0x84 + viewport_bounds_t unk_140; ///< offset=0x8c + char unk_148[24]; ///< offset=0x94 } window_t; // FIXME: Structure size From 75f22da5a63de7f79d465b18d7b359adb1d78219 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Sat, 8 Oct 2022 19:56:40 -0500 Subject: [PATCH 06/10] Revert observer_get_camera change --- kb.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kb.json b/kb.json index 3e4a9e3..c84018d 100644 --- a/kb.json +++ b/kb.json @@ -1100,7 +1100,7 @@ "addr": "0x8a4d0" }, { - "decl": "void *observer_get_camera(datum_index_t player);", + "decl": "void *observer_get_camera(int16_t local_player_index);", "addr": "0x8a4e0" }, { From 994537c906d4f2e138d2a8c3c96901b38fc75162 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Sat, 8 Oct 2022 20:00:36 -0500 Subject: [PATCH 07/10] Fixup main_game_render --- src/halo/main/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/halo/main/main.c b/src/halo/main/main.c index 5e753ab..e65366e 100644 --- a/src/halo/main/main.c +++ b/src/halo/main/main.c @@ -229,7 +229,7 @@ void main_game_render(double a2) } } current_window->local_player_index = next_player.index; - camera = observer_get_camera(next_player); + camera = observer_get_camera(next_player.index); } else { current_window->local_player_index = -1; } From d9085ba2b027c6c4f40fe893bf61ba6eda119216 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Fri, 14 Oct 2022 18:31:10 -0500 Subject: [PATCH 08/10] Implement player_index_from_unit_index --- kb.json | 4 ++++ src/halo/game/game.c | 2 +- src/halo/game/players.c | 17 ++++++++++++++++- src/halo/memory/data.c | 4 ++-- src/types.h | 10 +++++----- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/kb.json b/kb.json index c84018d..4dcc007 100644 --- a/kb.json +++ b/kb.json @@ -1323,6 +1323,10 @@ "decl": "int16_t local_player_count(void);", "addr": "0xba4b0" }, + { + "decl": "datum_index_t player_index_from_unit_index(datum_index_t);", + "addr": "0xba500" + }, { "decl": "bool players_are_all_dead(void);", "addr": "0xba5e0" diff --git a/src/halo/game/game.c b/src/halo/game/game.c index 4c68d56..1787952 100644 --- a/src/halo/game/game.c +++ b/src/halo/game/game.c @@ -140,7 +140,7 @@ void game_initial_pulse() data_iterator_new(&iter, player_data); while (data_iterator_next(&iter)) - game_engine_player_added(iter.datum_handle); + game_engine_player_added(iter.datum_index.handle); game_engine_game_starting(); } diff --git a/src/halo/game/players.c b/src/halo/game/players.c index cb393fc..3cb9cb8 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -159,7 +159,22 @@ datum_index_t local_player_get_next(datum_index_t local_player) return next_player; } -// TODO: player_index_from_unit_index +datum_index_t player_index_from_unit_index(datum_index_t unit_index) +{ + player_data_t* player; + data_iter_t iter; + + datum_index_t player_index = INVALID_DATUM_HANDLE; + + data_iterator_new(&iter, player_data); + for (player_data_t* player = data_iterator_next(&iter); player; player = data_iterator_next(&iter)) { + if (player->slave_unit_index.handle == unit_index.handle) + player_index = iter.datum_index; + } + + return player_index; +} + // TODO: player_died bool players_are_all_dead(void) diff --git a/src/halo/memory/data.c b/src/halo/memory/data.c index 22f91d7..5a2265e 100644 --- a/src/halo/memory/data.c +++ b/src/halo/memory/data.c @@ -34,7 +34,7 @@ void data_iterator_new(data_iter_t *iter, data_t *data) iter->data = data; iter->cookie = (unsigned int)data ^ 0x69746572; iter->index = 0; - iter->datum_handle = -1; + iter->datum_index = INVALID_DATUM_HANDLE; } void *data_iterator_next(data_iter_t *iterator) @@ -66,7 +66,7 @@ void *data_iterator_next(data_iter_t *iterator) return 0; } } - iterator->datum_handle = handle; + iterator->datum_index.handle = handle; iterator->index = index; } return result; diff --git a/src/types.h b/src/types.h index 635c320..ccc4b3d 100644 --- a/src/types.h +++ b/src/types.h @@ -254,11 +254,11 @@ typedef struct { /// size=0x10 typedef struct { - data_t *data; ///< offset=0x00 - uint16_t index; ///< offset=0x04 - char unk_6[2]; ///< offset=0x06 - uint32_t datum_handle; ///< offset=0x08 - uint32_t cookie; ///< offset=0x0c + data_t *data; ///< offset=0x00 + uint16_t index; ///< offset=0x04 + char unk_6[2]; ///< offset=0x06 + datum_index_t datum_index; ///< offset=0x08 + uint32_t cookie; ///< offset=0x0c } data_iter_t; /// size=8 From 2bd05d77e45fba7e2504c4de2f5a45221161a999 Mon Sep 17 00:00:00 2001 From: Ernegien Date: Fri, 14 Oct 2022 19:06:13 -0500 Subject: [PATCH 09/10] Implement player_died --- kb.json | 8 ++++++++ src/halo/game/players.c | 21 ++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/kb.json b/kb.json index 4dcc007..4693f5b 100644 --- a/kb.json +++ b/kb.json @@ -1171,6 +1171,10 @@ "decl": "void player_control_dispose(void);", "addr": "0xb63f0" }, + { + "decl": "void player_control_new_unit(uint16_t local_player_index, datum_index_t player_index);", + "addr": "0xb6fc0" + }, { "decl": "void player_control_initialize_for_new_map(void);", "addr": "0xb85c0" @@ -1327,6 +1331,10 @@ "decl": "datum_index_t player_index_from_unit_index(datum_index_t);", "addr": "0xba500" }, + { + "decl": "void player_died(datum_index_t);", + "addr": "0xba550" + }, { "decl": "bool players_are_all_dead(void);", "addr": "0xba5e0" diff --git a/src/halo/game/players.c b/src/halo/game/players.c index 3cb9cb8..d43960c 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -175,7 +175,26 @@ datum_index_t player_index_from_unit_index(datum_index_t unit_index) return player_index; } -// TODO: player_died +void player_died(datum_index_t player_index) +{ + player_data_t* player = datum_get(player_data, player_index); + player->last_slave_unit_index = player->slave_unit_index; + player->slave_unit_index = INVALID_DATUM_HANDLE; + + uint16_t local_player_index = player->local_player_index; + if (local_player_index != -1) { + player_control_new_unit(local_player_index, INVALID_DATUM_HANDLE); + } + + players_globals->are_all_dead = true; + + data_iter_t iter; + data_iterator_new(&iter, player_data); + for (player_data_t* player = data_iterator_next(&iter); player; player = data_iterator_next(&iter)) { + if (player->slave_unit_index.handle != -1) + players_globals->are_all_dead = false; + } +} bool players_are_all_dead(void) { From e61efeaff2cee02ab9f4f8364aa05868c7939f4d Mon Sep 17 00:00:00 2001 From: Ernegien Date: Fri, 14 Oct 2022 20:32:21 -0500 Subject: [PATCH 10/10] Tweak find_unused_local_player_index --- src/halo/game/players.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/halo/game/players.c b/src/halo/game/players.c index d43960c..28b7530 100644 --- a/src/halo/game/players.c +++ b/src/halo/game/players.c @@ -74,28 +74,26 @@ bool local_player_exists(int16_t player_index) int find_unused_local_player_index() { - int v0; // edi - int v1; // esi - int v2; // esi + int local_player_index = NONE; + int index = 0; - v0 = -1; - v1 = 0; - while (!input_has_gamepad(v1) || local_player_exists(v1)) - { - if (++v1 >= 4) - goto LABEL_7; + while (!input_has_gamepad(index) || local_player_exists(index)) { + if (++index >= MAXIMUM_NUMBER_OF_LOCAL_PLAYERS) + goto skip; } - v0 = v1; - if (v1 != -1) - return v0; - LABEL_7: - v2 = 0; - while (local_player_exists(v2)) - { - if (++v2 >= 4) - return v0; + + local_player_index = index; + if (index != NONE) + return local_player_index; + + skip: + index = 0; + while (local_player_exists(index)) { + if (++index >= MAXIMUM_NUMBER_OF_LOCAL_PLAYERS) + return local_player_index; } - return v2; + + return index; } void player_delete(datum_index_t player)