Skip to content

Commit

Permalink
UserProfile: add missing variable
Browse files Browse the repository at this point in the history
H3: add unit control record

Splitscreen: change function behavior and remove black bar
  • Loading branch information
WinterSquire committed Jul 25, 2024
1 parent 2c3e777 commit ad6a235
Show file tree
Hide file tree
Showing 13 changed files with 204 additions and 28 deletions.
1 change: 1 addition & 0 deletions lib/game/src/halo3/native_halo3.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ DefNative(Halo3) {
} data;
__int8 un1[0x280];
} data[MAX_LOCAL_PLAYERS];
static_assert(sizeof(raw_data_t) == 0x3D0);
};

DefEntry(TextureCamera, OFFSET_HALO3_V_ENTRY_TEXTURE_CAMERA) {
Expand Down
3 changes: 0 additions & 3 deletions res/patch.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,5 @@
aob="01"
default="false"
/>



</module>
</root>
11 changes: 7 additions & 4 deletions src/mcc/CGameManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,14 @@ bool CGameManager::Initialize(CGameManager* mng) {
{pGameManager->table->retrive_gamepad_mapping, retrive_gamepad_mapping, (void**)&ppOriginal.retrive_gamepad_mapping},
{pGameManager->table->set_state, set_state, (void**)&ppOriginal.set_state},
{pGameManager->table->game_restart, game_restart, (void**)&ppOriginal.game_restart},
{pGameManager->table->game_setup, game_setup, (void**)&ppOriginal.game_setup},
});
}

// b_override = true;

__int64 CGameManager::get_xuid(int index) {
__int64 result;
auto setting = AlphaRing::Global::MCC::Splitscreen();

if (index || setting->b_override_profile)
if (index)
return container.profiles[index].id;
else
return pGameManager->ppOriginal.get_xbox_user_id(pGameManager, &result, nullptr, 0, index) ? result : 0;
Expand Down Expand Up @@ -85,3 +83,8 @@ void *CGameManager::game_restart(CGameManager *self, int type, const char *reaso
LOG_INFO("Game Restart[{}]: {}", type, final_reason);
return ppOriginal.game_restart(self, type, reason);
}

char __fastcall CGameManager::game_setup(CGameManager* self, void* a2) {
// LOG_INFO("game setup"); player init/add
return ppOriginal.game_setup(self, a2);
}
5 changes: 3 additions & 2 deletions src/mcc/CGameManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@
private:
static void __fastcall set_vibration(CGameManager* self, DWORD dwUserIndex, XINPUT_VIBRATION *pVibration);
static CUserProfile* __fastcall get_player_profile(CGameManager* self, __int64 xid);
static char __fastcall get_xbox_user_id(CGameManager* self, __int64* pId, wchar_t *pName, int size, int index);
static bool __fastcall get_xbox_user_id(CGameManager* self, __int64* pId, wchar_t *pName, int size, int index);
static bool __fastcall get_key_state(CGameManager* self, DWORD index, input_data_t* p_input);
static CGamepadMapping* __fastcall retrive_gamepad_mapping(CGameManager* self, __int64 xid);

static void __fastcall set_state(CGameManager* self, eState state);
static void* __fastcall game_restart(CGameManager* self, int type, const char* reason);
static char __fastcall game_setup(CGameManager* self, void* a2);

public:
struct FunctionTable {
Expand All @@ -59,7 +60,7 @@
char pad0[0xD0];

// 0x100
char (__fastcall* sub_1401E51AC)(CGameManager* self, void* a2);
char (__fastcall* game_setup)(CGameManager* self, void* a2);
__int64 (__fastcall* sub_1401E78FC)(CGameManager* self, void* a2);
CUserProfile* (__fastcall* get_player_profile)(CGameManager* self, __int64 xid); // 0x110

Expand Down
4 changes: 2 additions & 2 deletions src/mcc/CGameManagerSplitscreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ void CGameManager::set_vibration(CGameManager *self, DWORD dwUserIndex, XINPUT_V
AlphaRing::Input::SetState(p_device->input_user, pVibration);
}

char CGameManager::get_xbox_user_id(CGameManager *self, __int64 *pId, wchar_t *pName, int size, int index) {
bool CGameManager::get_xbox_user_id(CGameManager *self, __int64 *pId, wchar_t *pName, int size, int index) {
auto p_setting = AlphaRing::Global::MCC::Splitscreen();
auto p_profile = get_profile(index);

if (!p_setting->b_override || (!index && !p_setting->b_override_profile))
if (!p_setting->b_override || !index)
return ppOriginal.get_xbox_user_id(self, pId, pName, size, index);

if (index >= p_setting->player_count)
Expand Down
4 changes: 1 addition & 3 deletions src/mcc/CInputDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ struct CInputDevice {
char un[0x38];
__int64 (__fastcall *set_state)(CInputDevice*, float, void*);
void (__fastcall *check)(CInputDevice*);
};
public:
method_table_t* p_method_table;
}* p_method_table;
char un0[2040];
bool enable_mouse;
char un[0x7];
Expand Down
16 changes: 16 additions & 0 deletions src/mcc/CUserProfile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,22 @@ void CUserProfile::ImGuiContext() {

// CustomKeyboardMouseMappingV2 is ignored as it's used only for player0

result |= ImGui::InputFloat("MouseSensitivity", &MouseSensitivity);
result |= ImGui::Checkbox("MouseSmoothing", &MouseSmoothing);
result |= ImGui::Checkbox("MouseAcceleration", &MouseAcceleration);

int tmp = PixelPerfectHudScale;
if (ImGui::InputInt("PixelPerfectHudScale", &tmp) && tmp >= 0 && tmp <= 0xFFFF) {
PixelPerfectHudScale = static_cast<__int16>(tmp);
result = true;
}

result |= ImGui::InputFloat("MouseAccelerationMinRate", &MouseAccelerationMinRate);
result |= ImGui::InputFloat("MouseAccelerationMaxAccel", &MouseAccelerationMaxAccel);
result |= ImGui::InputFloat("MouseAccelerationScale", &MouseAccelerationScale);
result |= ImGui::InputFloat("MouseAccelerationExp", &MouseAccelerationExp);
result |= ImGui::InputInt("KeyboardMouseButtonPreset", &KeyboardMouseButtonPreset);

result |= ImGui::InputFloat("MasterVolume", &MasterVolume);
result |= ImGui::InputFloat("MusicVolume", &MusicVolume);
result |= ImGui::InputFloat("SfxVolume", &SfxVolume);
Expand Down
8 changes: 4 additions & 4 deletions src/mcc/CUserProfile.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,10 @@ struct CUserProfile {
bool MouseSmoothing; // 0x414
bool MouseAcceleration; // 0x415
__int16 PixelPerfectHudScale; // 0x416
int MouseAccelerationMinRate; // 0x418
int MouseAccelerationMaxAccel; // 0x41C
int MouseAccelerationScale; // 0x420
int MouseAccelerationExp; // 0x424
float MouseAccelerationMinRate; // 0x418
float MouseAccelerationMaxAccel; // 0x41C
float MouseAccelerationScale; // 0x420
float MouseAccelerationExp; // 0x424
int KeyboardMouseButtonPreset; //? 0x428

struct CustomKeyboardMouseMappingV2_t {
Expand Down
15 changes: 15 additions & 0 deletions src/mcc/module/CModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,33 @@ static struct {
{"splitscreen_patch3", "", OFFSET_HALO2_PF_PLAYER_COUNT2, "\x04", true},
}}, {Halo3EntrySet(), {
{"splitscreen_patch1", "", OFFSET_HALO3_PF_COOP_JOIN, "\x31\xC0\xC3\x90", true},
{"splitscreen_patch2", "remove black bar", 0x8AD160, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", true},
{"splitscreen_patch3", "remove black bar", 0x8AD174, "\x00\x00\x00\x00\x00\x00\x00\x3F\x00\x00\x80\x3F", true},
{"splitscreen_patch4", "remove black bar", 0x8AD1B0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", true},
}}, {nullptr, {
{"splitscreen_patch1", "", OFFSET_HALO4_PF_COOP_JOIN, "\x31\xC0\xC3\x90", true},
{"splitscreen_patch2", "", OFFSET_HALO4_PF_COOP_REJOIN, "\xEB", true},
{"splitscreen_patch3", "", OFFSET_HALO4_PF_COOP_PLAYER_LIMIT, "\x90\x90\x90\x90\x90\x90", true},
{"splitscreen_patch4", "remove black bar", 0xE84E40, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", false},
{"splitscreen_patch5", "remove black bar", 0xE84E54, "\x00\x00\x00\x00\x00\x00\x00\x3F\x00\x00\x80\x3F", false},
{"splitscreen_patch6", "remove black bar", 0xE84E90, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", false},
}}, {nullptr, {
{"splitscreen_patch1", "", OFFSET_GROUNDHOG_PF_COOP_JOIN, "\x31\xC0\xC3\x90", true},
{"splitscreen_patch2", "", OFFSET_GROUNDHOG_PF_REJOIN, "\xEB", true},
{"splitscreen_patch3", "remove black bar", 0xE76560, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", false},
{"splitscreen_patch4", "remove black bar", 0xE76574, "\x00\x00\x00\x00\x00\x00\x00\x3F\x00\x00\x80\x3F", false},
{"splitscreen_patch5", "remove black bar", 0xE765B0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", false},
}}, {nullptr, {
{"splitscreen_patch1", "", OFFSET_HALO3ODST_PF_COOP_JOIN, "\x31\xC0\xC3\x90", true},
{"splitscreen_patch2", "remove black bar", 0x8F1FC0, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", true},
{"splitscreen_patch3", "remove black bar", 0x8F1FD4, "\x00\x00\x00\x00\x00\x00\x00\x3F\x00\x00\x80\x3F", true},
{"splitscreen_patch4", "remove black bar", 0x8F2010, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", true},
}}, {nullptr, {
{"splitscreen_patch1", "", OFFSET_HALOREACH_PF_COOP_JOIN, "\x31\xC0\xC3\x90", true},
{"splitscreen_patch2", "", OFFSET_HALOREACH_PF_COOP_REJOIN, "\xEB", true},
{"splitscreen_patch3", "remove black bar", 0xB43D10, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", false},
{"splitscreen_patch4", "remove black bar", 0xB43D24, "\x00\x00\x00\x00\x00\x00\x00\x3F\x00\x00\x80\x3F", false},
{"splitscreen_patch5", "remove black bar", 0xB43D60, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x3F", false},
}}};

static std::unordered_map<std::string, CModule*> map_modules {
Expand Down
125 changes: 125 additions & 0 deletions src/mcc/module/entry/halo3/simulation.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#include "halo3.h"

#include <vector>
#include <mutex>
#include <imgui.h>

namespace Halo3::Entry::Simulation {
struct simulation {
char buffer[2200];
struct queue {
struct item {
int type; // 0x0
item* next; // 0x8
};
bool enable; // 0x0
int count; // 0x4
int mem_size; // 0x8
int queue_count; // 0xC
int queue_size; // 0x10
item* head; // 0x18
item* tail; // 0x20
} queue1, queue2;
__int64 players_bit;
int object_INDEX[16];
struct ControlData {
const static int k_maximum_weapons_per_unit = 4;
const static int k_unit_grenade_types_count = 4;
const static __int16 k_unit_aiming_speeds_count = 0x8000;

int un;
__int16 aiming_speed;
__int16 un2;
char weapon_indices[2];
__int16 grenade_index;
__int16 zoom_level;
char buffer[10];
struct Throttle {
float i,j,k;
} throttle; // 24 movement
float primary_trigger;
float secondary_trigger;
Vector3 facing_vector;
Vector3 aiming_vector;
Vector3 looking_vector;
Vector3 gaze_position;
struct AimAssist {
char buffer[36];
} aim_assist_data;
} control_data[10];
char buffer2[2144];
};

static_assert(sizeof(simulation) == 5776);

static std::mutex g_mutex;
static bool bCapture = false;
static bool bPlayback = false;
static int playback_tick = 0;
static std::vector<simulation::ControlData> simulations;

Halo3Entry(entry, 0x350B24, char, detour, unsigned __int16 unit, simulation::ControlData* control_data) {
if (bCapture) {
std::lock_guard<std::mutex> g_lock(g_mutex);
simulations.push_back(*control_data);
} else if (bPlayback) {
std::lock_guard<std::mutex> g_lock(g_mutex);
if (playback_tick < simulations.size()) {
memcpy(control_data, &simulations[playback_tick], sizeof(simulation::ControlData));
playback_tick++;
} else {
bPlayback = false;
}
}
auto result = ((detour_t)entry.m_pOriginal)(unit, control_data);
return result;
}

void ImGuiContext() {
std::lock_guard<std::mutex> g_lock(g_mutex);

auto status = "Idle";

if (bCapture) status = "Capture";
else if (bPlayback) status = "Playback";

ImGui::Text("Simulation Status: %s", status);

int value = playback_tick;
if (ImGui::InputInt("Tick", &value) && (!value || (value > 0 && value < simulations.size()))) {
playback_tick = value;
}

if (ImGui::Button("Capture")) {
bCapture = true;
bPlayback = false;
}
ImGui::SameLine();
if (ImGui::Button("Pause##0")) {
bCapture = false;
}
ImGui::SameLine();
if (ImGui::Button("Resume##0")) {
bCapture = true;
}
ImGui::SameLine();
if (ImGui::Button("Clear")) {
simulations.clear();
playback_tick = 0;
}

if (ImGui::Button("Replay")) {
bPlayback = true;
bCapture = false;
playback_tick = 0;
}
ImGui::SameLine();
if (ImGui::Button("Pause##1")) {
bPlayback = false;
}
ImGui::SameLine();
if (ImGui::Button("Resume##1")) {
bPlayback = true;
}
}
}
17 changes: 13 additions & 4 deletions src/mcc/splitscreen/Splitscreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,23 @@ namespace MCC::Splitscreen {
ImGui::PushItemWidth(200);ImGui::Combo("Input", &p_profile->controller_index, items, IM_ARRAYSIZE(items));ImGui::PopItemWidth();
ImGui::EndDisabled();

ImGui::BeginDisabled(!p_setting->b_override_profile);
bool is_disabled = (!index && !p_setting->b_override_profile) || (index && p_setting->b_use_player0_profile);

if (ImGui::CollapsingHeader("Gamepad Mapping")) {
ImGui::Indent();
ImGui::BeginDisabled(is_disabled);
p_profile->mapping.ImGuiContext();
ImGui::EndDisabled();
ImGui::Unindent();
}

if (ImGui::CollapsingHeader("Profile")) {
ImGui::Indent();
ImGui::BeginDisabled(is_disabled);
p_profile->profile.ImGuiContext();
ImGui::EndDisabled();
ImGui::Unindent();
}

ImGui::EndDisabled();
}

void RealContext() {
Expand All @@ -117,8 +119,15 @@ namespace MCC::Splitscreen {
ImGui::MenuItem("Override profile", nullptr, &p_setting->b_override_profile);
ImGui::EndMenu();
}
ImGui::PushItemWidth(200);ImGui::InputInt("Players", &p_setting->player_count);ImGui::PopItemWidth();
#pragma region player count
ImGui::PushItemWidth(200);
int count = p_setting->player_count;
if (ImGui::InputInt("Players", &count) && count >= 1 && count <=4) {
p_setting->player_count = count;
}
ImGui::PopItemWidth();
ImGui::EndMenuBar();
#pragma endregion
}

if (ImGui::BeginTabBar("Players")) {
Expand Down
9 changes: 9 additions & 0 deletions src/render/d3d11/Hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@ namespace AlphaRing::Render::D3d11 {
graphics.pDevice->CreateRasterizerState(&r_desc, &r_state);
p_context->RSSetState(r_state);
}
#ifdef NEW_WIREFRAME
D3D11_PRIMITIVE_TOPOLOGY topology;
p_context->IAGetPrimitiveTopology(&topology);

p_context->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_LINELIST);
ppOriginal_DrawIndexed(p_context, IndexCount, StartIndexLocation, BaseVertexLocation);

p_context->IASetPrimitiveTopology(topology);
#endif
}

return ppOriginal_DrawIndexed(p_context, IndexCount, StartIndexLocation, BaseVertexLocation);
Expand Down
14 changes: 8 additions & 6 deletions src/render/imgui/game/halo3/context_global.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
static bool show_context = false;
static const char* map_types[4] = {"", "Campaign", "Multiplayer", "MainMenu"};

namespace Halo3::Entry::Simulation {
void ImGuiContext();
}

void CHalo3Context::context_global() {
if (ImGui::BeginMainMenuBar()) {
ImGui::MenuItem("Global", nullptr, &show_context);
Expand All @@ -18,13 +22,11 @@ void CHalo3Context::context_global() {
__int32 game_time = 0;
float speed = 0;

if (p_time != nullptr) {
tick_per_second = p_time->tick_per_second;
game_time = p_time->game_time;
speed = p_time->speed;
}
if (p_time == nullptr) return;

ImGui::Text("Game Time: %d\nTick Per Second: %hd\nSpeed: %.2f", p_time->game_time, p_time->tick_per_second, p_time->speed);

ImGui::Text("Game Time: %d\nTick Per Second: %hd\nSpeed: %.2f", game_time, tick_per_second, speed);
Halo3::Entry::Simulation::ImGuiContext();

auto map = Halo3::Native::Map();

Expand Down

0 comments on commit ad6a235

Please sign in to comment.