Skip to content

Commit

Permalink
Trainer: add DebugTrg reimpl. along with hotkey
Browse files Browse the repository at this point in the history
More info about DebugTrg at emoose/re4-research#20

Probably won't help speedrunners like 2007's DebugTrg, seeing as this would be counted as a game mod (and re4_tweaks is already banned from speedruns because of all our awesome improvements anyway :P), hopefully it might come in useful for modders to quickly get through levels though.
  • Loading branch information
emoose committed Nov 4, 2022
1 parent 7b07587 commit 2c6b1f1
Show file tree
Hide file tree
Showing 7 changed files with 192 additions and 0 deletions.
10 changes: 10 additions & 0 deletions dllmain/Game.cpp
Expand Up @@ -371,6 +371,12 @@ uint64_t Key_btn_trg()
return *(uint64_t*)(ptrKey_btn_trg);
}

JOY* Joy_ptr = nullptr;
JOY* JoyPtr()
{
return Joy_ptr;
}

GLOBAL_WK** pG_ptr = nullptr;
GLOBAL_WK* GlobalPtr()
{
Expand Down Expand Up @@ -704,6 +710,10 @@ bool Init_Game()
pattern = hook::pattern("A1 ? ? ? ? 25 ? ? ? ? 0B C1 74 ? 88 0D");
ptrKey_btn_trg = *pattern.count(1).get(0).get<uint32_t*>(1);

// Pointer to Joy[4] array
pattern = hook::pattern("83 E0 10 33 C9 0B C1 0F 84 ? ? ? ? 0F BE 05 ? ? ? ?");
Joy_ptr = (JOY*)(*pattern.count(1).get(0).get<uint8_t*>(0x10) - 9);

// Grab pointer to pG (pointer to games Global struct)
pattern = hook::pattern("A1 ? ? ? ? B9 FF FF FF 7F 21 48 ? A1");
pG_ptr = *pattern.count(1).get(0).get<GLOBAL_WK**>(1);
Expand Down
1 change: 1 addition & 0 deletions dllmain/Game.h
Expand Up @@ -46,6 +46,7 @@ MouseAimingModes GetMouseAimingMode();
void SetMouseAimingMode(MouseAimingModes newMode);
uint64_t Key_btn_on();
uint64_t Key_btn_trg();
JOY* JoyPtr();

GLOBAL_WK* GlobalPtr();
DAMAGE* DamagePtr();
Expand Down
79 changes: 79 additions & 0 deletions dllmain/SDK/pad.h
Expand Up @@ -87,3 +87,82 @@ enum class keyConfigTypes : uint8_t
TypeII,
TypeIII
};

struct PAD_MOTOR
{
uint16_t flag_0;
uint16_t delay_2;
uint16_t time_4;
uint16_t dummy_6;
int level_8;
int fade_C;
};
assert_size(PAD_MOTOR, 0x10);

enum JOY_BTN : uint32_t
{
JOY_DPAD_LEFT = 0x1,
JOY_DPAD_RIGHT = 0x2,
JOY_DPAD_DOWN = 0x4,
JOY_DPAD_UP = 0x8,
JOY_RT = 0x10,
JOY_RB = 0x20,
JOY_LB = 0x40,
JOY_LT = 0x80,
JOY_A = 0x100,
JOY_B = 0x200,
JOY_X = 0x400,
JOY_Y = 0x800,
JOY_START = 0x1000,
JOY_BACK = 0x2000,
JOY_RS = 0x4000,
JOY_LS = 0x8000,
JOY_LS_LEFT = 0x10000,
JOY_LS_RIGHT = 0x20000,
JOY_LS_DOWN = 0x40000,
JOY_LS_UP = 0x80000,
JOY_RS_LEFT = 0x100000,
JOY_RS_RIGHT = 0x200000,
JOY_RS_DOWN = 0x400000,
JOY_RS_UP = 0x800000,
};

struct JOY
{
int leftStick_X_0;
int leftStick_Y_4;
int8_t rightStick_X_8;
int8_t rightStick_Y_9;
uint8_t triggerLeft_A;
uint8_t triggerRight_B;
uint8_t analogA_C;
uint8_t analogB_D;
int8_t err_E;
JOY_BTN old_10;
JOY_BTN on_14;
JOY_BTN trg_18;
JOY_BTN rel_1C;
JOY_BTN rep_20;
JOY_BTN rep2_24;
int8_t rep_timer_28[32];
int8_t rep2_timer_48[32];
uint8_t motor_state_68;
uint8_t pad_6A[3];
PAD_MOTOR motor_6C[10];

// extra fields added in Wii/UHD ver, not fully mapped out yet:
uint8_t unk_10C[12];
int pc_leftStick_X_118;
int pc_leftStick_Y_11C;
int8_t pc_rightStick_X_120;
int8_t pc_rightStick_Y_121;
__int16 pc_unk_A_122;
uint8_t unk_124[4];
int pc_buttonStates0_128;
int pc_buttonsOn_12C;
int pc_buttonStates2_130;
uint8_t unk_134[312];
int8_t wpad_rightStick_X_26C;
int8_t wpad_rightStick_Y_26D;
};
assert_size(JOY, 0x270);
5 changes: 5 additions & 0 deletions dllmain/Settings.cpp
Expand Up @@ -374,6 +374,7 @@ void Config::ReadSettings(std::string_view ini_path)
pConfig->bTrainerDisableEnemySpawn = iniReader.ReadBoolean("TRAINER", "DisableEnemySpawn", pConfig->bTrainerDisableEnemySpawn);
pConfig->bTrainerDeadBodiesNeverDisappear = iniReader.ReadBoolean("TRAINER", "DeadBodiesNeverDisappear", pConfig->bTrainerDeadBodiesNeverDisappear);
pConfig->bTrainerAllowEnterDoorsWithoutAsh = iniReader.ReadBoolean("TRAINER", "AllowEnterDoorsWithoutAshley", pConfig->bTrainerAllowEnterDoorsWithoutAsh);
pConfig->bTrainerEnableDebugTrg = iniReader.ReadBoolean("TRAINER", "EnableDebugTrg", pConfig->bTrainerEnableDebugTrg);

// ESP
pConfig->bShowESP = iniReader.ReadBoolean("ESP", "ShowESP", pConfig->bShowESP);
Expand Down Expand Up @@ -428,6 +429,7 @@ void Config::ReadSettings(std::string_view ini_path)
pConfig->sTrainerFreeCamKeyCombo = iniReader.ReadString("TRAINER_HOTKEYS", "FreeCamToggle", pConfig->sTrainerFreeCamKeyCombo);
pConfig->sTrainerSpeedOverrideKeyCombo = iniReader.ReadString("TRAINER_HOTKEYS", "SpeedOverrideToggle", pConfig->sTrainerSpeedOverrideKeyCombo);
pConfig->sTrainerMoveAshToPlayerKeyCombo = iniReader.ReadString("TRAINER_HOTKEYS", "MoveAshleyToPlayer", pConfig->sTrainerMoveAshToPlayerKeyCombo);
pConfig->sTrainerDebugTrgKeyCombo = iniReader.ReadString("TRAINER_HOTKEYS", "DebugTrg", pConfig->sTrainerDebugTrgKeyCombo);

// WEAPON HOTKEYS
pConfig->bWeaponHotkeysEnable = iniReader.ReadBoolean("WEAPON_HOTKEYS", "Enable", pConfig->bWeaponHotkeysEnable);
Expand Down Expand Up @@ -562,6 +564,7 @@ void WriteSettings(std::string_view iniPath, bool trainerIni)
iniReader.WriteBoolean("TRAINER", "DisableEnemySpawn", pConfig->bTrainerDisableEnemySpawn);
iniReader.WriteBoolean("TRAINER", "DeadBodiesNeverDisappear", pConfig->bTrainerDeadBodiesNeverDisappear);
iniReader.WriteBoolean("TRAINER", "AllowEnterDoorsWithoutAshley", pConfig->bTrainerAllowEnterDoorsWithoutAsh);
iniReader.WriteBoolean("TRAINER", "EnableDebugTrg", pConfig->bTrainerEnableDebugTrg);

// ESP
iniReader.WriteBoolean("ESP", "ShowESP", pConfig->bShowESP);
Expand Down Expand Up @@ -629,6 +632,7 @@ void WriteSettings(std::string_view iniPath, bool trainerIni)
iniReader.WriteString("TRAINER_HOTKEYS", "FreeCamToggle", " " + pConfig->sTrainerFreeCamKeyCombo);
iniReader.WriteString("TRAINER_HOTKEYS", "SpeedOverrideToggle", " " + pConfig->sTrainerSpeedOverrideKeyCombo);
iniReader.WriteString("TRAINER_HOTKEYS", "MoveAshleyToPlayer", " " + pConfig->sTrainerMoveAshToPlayerKeyCombo);
iniReader.WriteString("TRAINER_HOTKEYS", "DebugTrg", " " + pConfig->sTrainerDebugTrgKeyCombo);

// WEAPON HOTKEYS
iniReader.WriteBoolean("WEAPON_HOTKEYS", "Enable", pConfig->bWeaponHotkeysEnable);
Expand Down Expand Up @@ -957,6 +961,7 @@ void Config::LogSettings()
spd::log()->info("| {:<30} | {:>15} |", "NoclipToggle", pConfig->sTrainerNoclipKeyCombo.data());
spd::log()->info("| {:<30} | {:>15} |", "SpeedOverrideToggle", pConfig->sTrainerSpeedOverrideKeyCombo.data());
spd::log()->info("| {:<30} | {:>15} |", "MoveAshleyToPlayer", pConfig->sTrainerMoveAshToPlayerKeyCombo.data());
spd::log()->info("| {:<30} | {:>15} |", "DebugTrg", pConfig->sTrainerDebugTrgKeyCombo.data());
spd::log()->info("+--------------------------------+-----------------+");

// FPS WARNING
Expand Down
2 changes: 2 additions & 0 deletions dllmain/Settings.h
Expand Up @@ -130,6 +130,7 @@ class Config
std::string sTrainerFreeCamKeyCombo = "";
std::string sTrainerSpeedOverrideKeyCombo = "";
std::string sTrainerMoveAshToPlayerKeyCombo = "";
std::string sTrainerDebugTrgKeyCombo = "SHIFT+ALT";

// ESP
bool bShowESP = false;
Expand Down Expand Up @@ -193,6 +194,7 @@ class Config
bool bTrainerDisableEnemySpawn = false;
bool bTrainerDeadBodiesNeverDisappear = false;
bool bTrainerAllowEnterDoorsWithoutAsh = false;
bool bTrainerEnableDebugTrg = false;

// WARNING
bool bIgnoreFPSWarning = false;
Expand Down
88 changes: 88 additions & 0 deletions dllmain/Trainer.cpp
Expand Up @@ -101,6 +101,7 @@ std::vector<uint32_t> KeyComboNoclipToggle;
std::vector<uint32_t> KeyComboFreeCamToggle;
std::vector<uint32_t> KeyComboSpeedOverride;
std::vector<uint32_t> KeyComboAshToPlayer;
std::vector<uint32_t> KeyComboDebugTrg;

std::vector<uint32_t> KeyComboWeaponHotkey[5];
std::vector<uint32_t> KeyComboLastWeaponHotkey;
Expand Down Expand Up @@ -258,6 +259,12 @@ void Trainer_ParseKeyCombos()
}, &KeyComboAshToPlayer });
}

// DebugTrg
{
KeyComboDebugTrg.clear();
KeyComboDebugTrg = ParseKeyCombo(pConfig->sTrainerDebugTrgKeyCombo);
}

// WeaponHotkey
{
for (int i = 0; i < 5; i++)
Expand Down Expand Up @@ -292,6 +299,46 @@ bool __cdecl cameraHitCheck_hook(Vec *pCross, Vec *pNorm, Vec p0, Vec p1)
return cameraHitCheck_orig(pCross, pNorm, p0, p1);
}

// DebugTrg reimpl based on 2007 port, thank you SourceNext!
// (no other publicly available builds appear to include this, even the debug builds...)
// Gamepad combo is LB + B + X
bool __cdecl DebugTrg_hook(uint32_t flag)
{
if (!pConfig->bTrainerEnableDebugTrg)
return false;

if (FlagIsSet(GlobalPtr()->Flags_SYSTEM_0_54, uint32_t(Flags_SYSTEM::SYS_PUBLICITY_VER)))
return false; // disallowed if SYS_PUBLICITY_VER set, probably set on E3/TGS/trade show builds

// if flag is set, then caller func seems to allow checking for previously held buttons
// otherwise, buttons must have only been pressed this frame

if (flag && pInput->is_combo_down(&KeyComboDebugTrg))
return true;
if (!flag && pInput->is_combo_pressed(&KeyComboDebugTrg))
return true;

JOY* Joy = JoyPtr();

if ((Joy[0].on_14 & JOY_START) != 0)
return false; // if start pressed, always return false

if (flag)
{
if ((Joy[0].on_14 & JOY_LB) == 0 || (Joy[0].on_14 & JOY_B) == 0)
return false; // LB or B not pressed/held, return false
return ((Joy[0].on_14 & JOY_X) != 0); // return true if X also pressed/held
}

// If flag == 0, the same LB/B checks are used as above, but the X check is performed on Joy.trg instead of Joy.on
// Seems trg shows buttons that were newly pressed on this frame, then gets cleared on subsequent frame even if held down
// I guess to help ensure the function only runs once, on the frame when button was first pressed
// (and not on any subsequent frames where it might still be held down)

if ((Joy[0].on_14 & JOY_LB) == 0 || (Joy[0].on_14 & JOY_B) == 0)
return false; // LB or B not pressed/held, return false
return ((Joy[0].trg_18 & JOY_X) != 0); // return true if X was newly pressed
}

std::vector<FlagPatch> flagPatches;
void Trainer_Init()
Expand Down Expand Up @@ -637,6 +684,12 @@ void Trainer_Init()
pattern = hook::pattern("D9 83 ? ? ? ? 52 DC 0D ? ? ? ? 51 8D 45 ? D9 9D");
injector::MakeInline<calcOffset_depression>(pattern.count(1).get(0).get<uint32_t>(0), pattern.count(1).get(0).get<uint32_t>(6));
}

// Hook DebugTrg stub to use our reimplemented version
{
auto pattern = hook::pattern("83 C4 18 6A 01 E8 ? ? ? ? 83 C4 04 3C 01");
InjectHook(injector::GetBranchDestination(pattern.count(1).get(0).get<uint32_t>(0x5)).as_int(), DebugTrg_hook, PATCH_JUMP);
}
}

void Trainer_Update()
Expand Down Expand Up @@ -1583,6 +1636,21 @@ void Trainer_RenderUI(int columnCount)
ImGui::TextWrapped("Allows the player to go through doors even if Ashley is far away.");
}

// EnableDebugTrg
{
ImGui_ColumnSwitch();

if (ImGui::Checkbox("Enable DebugTrg function", &pConfig->bTrainerEnableDebugTrg))
pConfig->HasUnsavedChanges = true;

ImGui_ItemSeparator();

ImGui::Dummy(ImVec2(10, 10 * esHook._cur_monitor_dpi));

ImGui::TextWrapped("Reimplements the games DebugTrg function, usually allowing certain sections of rooms/events to be skipped.");
ImGui::TextWrapped("Can be trigged by pressing LB + X + B together on controller, a hotkey can also be bound in the hotkeys page.");
}

ImGui_ColumnFinish();
ImGui::EndTable();
}
Expand Down Expand Up @@ -1770,6 +1838,26 @@ void Trainer_RenderUI(int columnCount)
ImGui::TextWrapped("Move Ashley to Player");
}

// DebugTrg trigger
{
ImGui_ColumnSwitch();

ImGui::TextWrapped("DebugTrg combination, requires EnableDebugTrg to be enabled.");
ImGui::Dummy(ImVec2(10, 10 * esHook._cur_monitor_dpi));

ImGui::PushID(5);
if (ImGui::Button(pConfig->sTrainerDebugTrgKeyCombo.c_str(), ImVec2(btn_size_x, 0)))
{
pConfig->HasUnsavedChanges = true;
CreateThreadAutoClose(0, 0, (LPTHREAD_START_ROUTINE)&SetHotkeyComboThread, &pConfig->sTrainerDebugTrgKeyCombo, 0, NULL);
}
ImGui::PopID();

ImGui::SameLine();

ImGui::TextWrapped("DebugTrg");
}

ImGui_ColumnFinish();
ImGui::EndTable();
}
Expand Down
7 changes: 7 additions & 0 deletions settings/trainer_settings.ini
Expand Up @@ -62,6 +62,10 @@ DeadBodiesNeverDisappear = False
; Allows the player to go through doors even if Ashley is far away.
AllowEnterDoorsWithoutAshley = False

; Reimplements the games DebugTrg function, usually allowing certain sections of rooms/events to be skipped.
; Can be trigged by pressing LB + X + B together on controller, a hotkey can also be bound in the hotkeys section.
EnableDebugTrg = False

[ESP]
; Displays information on Ems
ShowESP = False
Expand Down Expand Up @@ -139,3 +143,6 @@ SpeedOverrideToggle =

; Key combination to move Ashley to the player's position
MoveAshleyToPlayer =

; DebugTrg combination, requires EnableDebugTrg to be enabled.
DebugTrg = SHIFT+ALT

0 comments on commit 2c6b1f1

Please sign in to comment.