diff --git a/README.md b/README.md index 9de3d1f..69c1d16 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,10 @@ avoid clicking off the window. | Jurassic: The Hunted (USA) | SLUS-21907 | Good | **Requires supplied cheat file**
Optional 60FPS cheat recommended | Aim Assist: Off | **EFE4448F.pnach** | | Monster Attack (PAL) / Chikyū Bōeigun (Japan) | SLES-51856, SLPM-62344 | Good | Vehicle mouse control is experimental
Not fully tested | Control Type: Technical | - | | No One Lives Forever (USA) | SLUS-20028 | Good | Not fully tested | Auto-targeting: Off | - | +| Call of Duty 3 (USA) | SLUS-21426 | Good | 3rd-Person Jeep camera not supported
Not fully tested | - | - | +| TimeSplitters (v1.10, v2.00) (USA) | SLUS-20090 | Good | **Optional cheat to always show crosshair**
Not fully tested | Auto Lookahead: No
Auto Aim: Off | **B4A004F2.pnach (v1.10)
8966730F.pnach (v2.00)** | +| Return to Castle Wolfenstein: Operation Resurrection (USA) | SLUS-20297 | Good | Not fully tested | Auto Center View: Off
Always Aim: Off | - | +| Beverly Hills Cop (USA) | SLES-54456 | Fair | Not fully tested | - | - | * NOTE: PCSX2 will only hook with **BIOS versions 5XXXX and up**. * NOTE: Some aspects may break when a game is started with overclocking. Requires testing. * PCSX2 Settings: **Disable** *'Settings->Interface->Double-Click Toggles Fullscreen'* | **Enable** *'Settings->Interface->Hide Cursor In Fullscreen'* diff --git a/cheats/PS2/8966730F.pnach b/cheats/PS2/8966730F.pnach new file mode 100644 index 0000000..c337ba9 --- /dev/null +++ b/cheats/PS2/8966730F.pnach @@ -0,0 +1,4 @@ +gametitle=TimeSplitters(v2.00) SLUS-20090 0x8966730F + +// Always display crosshair +//patch=1,EE,202817FC,word,AE270320 \ No newline at end of file diff --git a/cheats/PS2/B4A004F2.pnach b/cheats/PS2/B4A004F2.pnach new file mode 100644 index 0000000..0f6c2e7 --- /dev/null +++ b/cheats/PS2/B4A004F2.pnach @@ -0,0 +1,4 @@ +gametitle=TimeSplitters(v1.10) SLUS-20090 0xB4A004F2 + +// Always display crosshair +//patch=1,EE,2027E7A4,word,AE270320 \ No newline at end of file diff --git a/games/game.c b/games/game.c index 3f1ac17..ca07e7e 100644 --- a/games/game.c +++ b/games/game.c @@ -134,9 +134,13 @@ extern const GAMEDRIVER *GAME_PS2_THESUFFERING; extern const GAMEDRIVER *GAME_PS1_007THEWORLDISNOTENOUGH; extern const GAMEDRIVER *GAME_PS2_RETURNTOCASTLEWOLF; extern const GAMEDRIVER *GAME_PS2_BEVERLYHILLSCOP; +extern const GAMEDRIVER *GAME_PS2_KILLZONE; +extern const GAMEDRIVER *GAME_PS2_TIMESPLITTERS; +extern const GAMEDRIVER *GAME_PS2_BATTLEFIELD2; +extern const GAMEDRIVER *GAME_PS2_CALLOFDUTY3; static const GAMEDRIVER **GAMELIST[] = -{ +{ // UNF - Unfinished &GAME_TS2, &GAME_TS3, &GAME_NF, @@ -158,8 +162,8 @@ static const GAMEDRIVER **GAMELIST[] = &GAME_N64_SINPUNISHMENT, &GAME_SNES_PACMAN2, &GAME_SNES_TIMONANDPUMBAA, - &GAME_SNES_SHADOWRUN, - &GAME_SNES_STARFOX, + &GAME_SNES_SHADOWRUN, // UNF + &GAME_SNES_STARFOX, // UNF &GAME_SNES_UNTOUCHABLES, &GAME_SNES_RTYPE3, &GAME_PS2_007AGENTUNDERFIRE, @@ -177,78 +181,82 @@ static const GAMEDRIVER **GAMELIST[] = &GAME_PS2_50CENTBULLETPROOF, &GAME_PS2_COLDWINTER, &GAME_PS1_RESIDENTEVILSURVIVOR, - &GAME_PS1_DNLANDOFTHEBABES, + &GAME_PS1_DNLANDOFTHEBABES, // UNF &GAME_PS2_MERCENARIES, &GAME_PS2_MOHVANGUARD, &GAME_PS1_THENOTE, - &GAME_PS1_POED, + &GAME_PS1_POED, // UNF &GAME_PS1_ECHONIGHT, &GAME_PS1_SHADOWTOWER, &GAME_PS1_SOUTHPARK, &GAME_PS1_JUMPINGFLASH, &GAME_PS1_KINGSFIELD, &GAME_PS1_KINGSFIELD2, - // &GAME_SS_POWERSLAVE, + // &GAME_SS_POWERSLAVE, // UNF &GAME_PS1_KINGSFIELD3, &GAME_PS2_KINGSFIELD4, - &GAME_SD_MAKENX, - &GAME_SD_REDDOG, + &GAME_SD_MAKENX, // UNF + &GAME_SD_REDDOG, // UNF &GAME_PS1_ARMOREDCORE, &GAME_PS1_BAROQUE, - &GAME_PS1_GALEGUNNER, - &GAME_PS1_C12FINALRESISTANCE, - &GAME_PS1_MEGAMANLEGENDS, + &GAME_PS1_GALEGUNNER, // UNF + &GAME_PS1_C12FINALRESISTANCE, // UNF + &GAME_PS1_MEGAMANLEGENDS, // UNF &GAME_SNES_WILDGUNS, &GAME_PS1_ALIENTRILOGY, - &GAME_PS1_HPSORCERERSSTONE, - &GAME_PS1_MEDALOFHONOR, - &GAME_PS3_KILLZONEHD, - &GAME_PS2_GTAVICECITYSTORIES, + &GAME_PS1_HPSORCERERSSTONE, // UNF + &GAME_PS1_MEDALOFHONOR, // UNF + &GAME_PS3_KILLZONEHD, // UNF + &GAME_PS2_GTAVICECITYSTORIES, // UNF &GAME_PS2_ETERNALRING, &GAME_PS1_DISRUPTOR, - &GAME_SNES_CYBERNATOR, - &GAME_N64_TUROK3, + &GAME_SNES_CYBERNATOR, // UNF + &GAME_N64_TUROK3, // UNF &GAME_PS2_MICHIGAN, - &GAME_PS2_STABYSS, - &GAME_PS2_AVPEXTINCTION, - &GAME_N64_007WINE, - &GAME_PS2_GEROGUEAGENT, + &GAME_PS2_STABYSS, // UNF + &GAME_PS2_AVPEXTINCTION, // UNF + &GAME_N64_007WINE, // UNF + &GAME_PS2_GEROGUEAGENT, // UNF &GAME_PS1_LSDDREAMEMULATOR, - &GAME_PS1_DECEPTION, + &GAME_PS1_DECEPTION, // UNF &GAME_PS1_AQUANAUTSHOLIDAY, &GAME_PS1_HELLNIGHT, - &GAME_PS1_MEGAMANLEGENDS2, - &GAME_PS2_TRIBESAA, + &GAME_PS1_MEGAMANLEGENDS2, // UNF + &GAME_PS2_TRIBESAA, // UNF &GAME_PSP_CODEDARMS, - &GAME_SCD_JURASSICPARK, - &GAME_PSP_NOVA, - &GAME_PS2_GHOSTINTHESHELL, + &GAME_SCD_JURASSICPARK, // UNF + &GAME_PSP_NOVA, // UNF + &GAME_PS2_GHOSTINTHESHELL, // UNF &GAME_PSP_GHOSTINTHESHELL, - &GAME_PSP_RESISTANCERETRIBUTION, - &GAME_PS2_GREGMAXD, - &GAME_PS2_SHSHATTEREDMEMORIES, + &GAME_PSP_RESISTANCERETRIBUTION, // UNF + &GAME_PS2_GREGMAXD, // UNF + &GAME_PS2_SHSHATTEREDMEMORIES, // UNF &GAME_PS1_DUKETIMETOKILL, &GAME_PS1_FUTURECOP, &GAME_PS2_ROBOTECHINVASION, &GAME_PS2_SERIOUSSAMNE, - &GAME_SS_PANZERDRAGOON, - &GAME_PS2_STATEOFEMERGENCY2, - &GAME_PS2_RACUPYOURARSENAL, - &GAME_PS2_ECHONIGHTBEYOND, + &GAME_SS_PANZERDRAGOON, // UNF + &GAME_PS2_STATEOFEMERGENCY2, // UNF + &GAME_PS2_RACUPYOURARSENAL, // UNF + &GAME_PS2_ECHONIGHTBEYOND, // UNF &GAME_PS2_ARMOREDCORE2, &GAME_PS2_GLOBALDEFENSEFORCE, &GAME_PS2_JURASSICTHEHUNTED, - &GAME_PS2_MONSTERHUNTER, - &GAME_PS3_HAZE, + &GAME_PS2_MONSTERHUNTER, // UNF + &GAME_PS3_HAZE, // UNF &GAME_PS2_NOONELIVESFOREVER, - &GAME_SS_VIRTUALHYDLIDE, + &GAME_SS_VIRTUALHYDLIDE, // UNF &GAME_PS2_EARTHDEFENSEFORCE, - &GAME_PS2_SHADOWOFROME, + &GAME_PS2_SHADOWOFROME, // UNF &GAME_GC_TUROKEVOLUTION, - &GAME_PS2_THESUFFERING, - &GAME_PS1_007THEWORLDISNOTENOUGH, + &GAME_PS2_THESUFFERING, // UNF + &GAME_PS1_007THEWORLDISNOTENOUGH, // UNF &GAME_PS2_RETURNTOCASTLEWOLF, - &GAME_PS2_BEVERLYHILLSCOP + &GAME_PS2_BEVERLYHILLSCOP, + &GAME_PS2_KILLZONE, // UNF + &GAME_PS2_TIMESPLITTERS, + &GAME_PS2_BATTLEFIELD2, // UNF + &GAME_PS2_CALLOFDUTY3 }; static const GAMEDRIVER *CURRENT_GAME = NULL; diff --git a/games/ps2_battlefield2.c b/games/ps2_battlefield2.c new file mode 100644 index 0000000..299d98a --- /dev/null +++ b/games/ps2_battlefield2.c @@ -0,0 +1,108 @@ +//=========================================================== +// Mouse Injector for Dolphin +//========================================================================== +// Copyright (C) 2019-2020 Carnivorous +// All rights reserved. +// +// Mouse Injector is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html +//========================================================================== +#include +#include "../main.h" +#include "../memory.h" +#include "../mouse.h" +#include "game.h" + +// #define BF2_CAM_BASE_PTR 0x782B98 +#define BF2_CAM_BASE_PTR 0xB295F0 +// offsets from camBase +#define BF2_CAMX 0x4 +#define BF2_CAMY 0x8 + +static uint8_t PS2_BF2_Status(void); +static uint8_t PS2_BF2_DetectCamBase(void); +static void PS2_BF2_Inject(void); + +static const GAMEDRIVER GAMEDRIVER_INTERFACE = +{ + "Battlefield 2: Modern Combat", + PS2_BF2_Status, + PS2_BF2_Inject, + 1, // 1000 Hz tickrate + 0 // crosshair sway not supported for driver +}; + +const GAMEDRIVER *GAME_PS2_BATTLEFIELD2 = &GAMEDRIVER_INTERFACE; + +static uint32_t camBase = 0; + +//========================================================================== +// Purpose: return 1 if game is detected +//========================================================================== +static uint8_t PS2_BF2_Status(void) +{ + // SLUS_210.26 + return (PS2_MEM_ReadWord(0x00093390) == 0x534C5553U && + PS2_MEM_ReadWord(0x00093394) == 0x5F323130U && + PS2_MEM_ReadWord(0x00093398) == 0x2E32363BU); +} + +static uint8_t PS2_BF2_DetectCamBase(void) +{ + uint32_t p4 = PS2_MEM_ReadUInt(BF2_CAM_BASE_PTR) + 0x1C8; // 1AD86B0 + 1C8 = 1AD8878 + uint32_t p3 = PS2_MEM_ReadUInt(p4); // 1DDA760 + uint32_t p2 = PS2_MEM_ReadUInt(p3); // 7F8EF0 + uint32_t p1 = PS2_MEM_ReadUInt(p2) + 0x1C; // 1B11420 + 1C = 1B1143C + uint32_t tempCamBase = PS2_MEM_ReadUInt(p1); + + // TODO: sanity check + if (tempCamBase) + { + camBase = tempCamBase; + return 1; + } + + return 0; +} + +static void PS2_BF2_Inject(void) +{ + // TODO: test camBase tree + // TODO: playerBase? and look for current weapon camera since + // each weapon uses different camera values??? + // TODO: tank barrel + // TODO: turrets + // static + // car mounted + + if(xmouse == 0 && ymouse == 0) // if mouse is idle + return; + + if (!PS2_BF2_DetectCamBase()) + return; + + float looksensitivity = (float)sensitivity / 40.f; + float scale = 250.f; + // float fov = PS2_MEM_ReadFloat(RTCW_FOV) / 106.5f; + float fov = 1.f; + + float camX = PS2_MEM_ReadFloat(camBase + BF2_CAMX); + camX += (float)xmouse * looksensitivity / scale * fov; + PS2_MEM_WriteFloat(camBase + BF2_CAMX, (float)camX); + + float camY = PS2_MEM_ReadFloat(camBase + BF2_CAMY); + camY -= (float)(invertpitch ? -ymouse : ymouse) * looksensitivity / scale * fov; + + PS2_MEM_WriteFloat(camBase + BF2_CAMY, (float)camY); + +} \ No newline at end of file diff --git a/games/ps2_cod3.c b/games/ps2_cod3.c new file mode 100644 index 0000000..596811a --- /dev/null +++ b/games/ps2_cod3.c @@ -0,0 +1,108 @@ +//=========================================================== +// Mouse Injector for Dolphin +//========================================================================== +// Copyright (C) 2019-2020 Carnivorous +// All rights reserved. +// +// Mouse Injector is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html +//========================================================================== +#include +#include "../main.h" +#include "../memory.h" +#include "../mouse.h" +#include "game.h" + +#define COD3_CAMY 0x48FC64 +#define COD3_CAMX 0x48FC68 +#define COD3_AIM_ASSIST 0x47CB74 +#define COD3_FOV 0x4C0430 +#define COD3_CAN_MOVE_JEEP_3RD_PERSON_CAM 0x4C0474 + +#define COD3_IS_IN_GAME_CUTSCENE 0x49D858 +#define COD3_IS_PAUSED 0x4A5CD0 + +static uint8_t PS2_COD3_Status(void); +static void PS2_COD3_Inject(void); + +static const GAMEDRIVER GAMEDRIVER_INTERFACE = +{ + "Call of Duty 3", + PS2_COD3_Status, + PS2_COD3_Inject, + 1, // 1000 Hz tickrate + 0 // crosshair sway not supported for driver +}; + +const GAMEDRIVER *GAME_PS2_CALLOFDUTY3 = &GAMEDRIVER_INTERFACE; + +//========================================================================== +// Purpose: return 1 if game is detected +//========================================================================== +static uint8_t PS2_COD3_Status(void) +{ + // SLUS_214.26 + return (PS2_MEM_ReadWord(0x49C918) == 0x534C5553U && + PS2_MEM_ReadWord(0x49C91C) == 0x5F323134U && + PS2_MEM_ReadWord(0x49C920) == 0x2E32363BU); +} + +// static uint8_t PS2_COD3_DetectCam(void) +// { +// uint32_t tempCamBase = PS2_MEM_ReadUInt(RTCW_ACTUAL_CAMY_BASE_PTR); +// if (tempCamBase) +// { +// actualCamYBase = tempCamBase; +// return 1; +// } +// return 0; +// } + +static void PS2_COD3_Inject(void) +{ + // TODO: 3rd person jeep camera + // does move but only moved manually with controller button + // works for a bit and then it rebounds to center and locks + // TODO: charge plant mini-game with mouse + + // disable aim-assist + PS2_MEM_WriteUInt(COD3_AIM_ASSIST, 0x0); + + // PS2_MEM_WriteUInt(COD3_CAN_MOVE_JEEP_3RD_PERSON_CAM, 0x1); + + if (PS2_MEM_ReadUInt(COD3_IS_IN_GAME_CUTSCENE)) + return; + + if (PS2_MEM_ReadUInt(COD3_IS_PAUSED)) + return; + + if(xmouse == 0 && ymouse == 0) // if mouse is idle + return; + + // if (!PS2_RTCW_DetectCam()) + // return; + + float looksensitivity = (float)sensitivity / 40.f; + float scale = 6.f; + float fov = PS2_MEM_ReadFloat(COD3_FOV) / 65.f; + + float camX = PS2_MEM_ReadFloat(COD3_CAMX); + camX -= (float)xmouse * looksensitivity / scale * fov; + PS2_MEM_WriteFloat(COD3_CAMX, (float)camX); + + float camY = PS2_MEM_ReadFloat(COD3_CAMY); + camY += (float)(invertpitch ? -ymouse : ymouse) * looksensitivity / scale * fov; + // game clamps internally to actual camY + PS2_MEM_WriteFloat(COD3_CAMY, (float)camY); + +} \ No newline at end of file diff --git a/games/ps2_killzone.c b/games/ps2_killzone.c new file mode 100644 index 0000000..a1a0dda --- /dev/null +++ b/games/ps2_killzone.c @@ -0,0 +1,112 @@ +//=========================================================== +// Mouse Injector for Dolphin +//========================================================================== +// Copyright (C) 2019-2020 Carnivorous +// All rights reserved. +// +// Mouse Injector is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html +//========================================================================== +#include +#include "../main.h" +#include "../memory.h" +#include "../mouse.h" +#include "game.h" + +#define TAU 6.2831853f // 0x40C90FDB + +#define KZ_CAMX_BASE_PTR 0x12C1DA4 +// offset from camXBase +#define KZ_CAMX_SIN 0x88 +#define KZ_CAMX_COS 0x8C +#define KZ_ZOOM 0x44C + +#define KZ_CAMY_BASE_PTR 0x12C1DA8 +// offset from camYBase +#define KZ_CAMY 0x14C + +#define KZ_CAN_ACT 0x13FC00 + +static uint8_t PS2_KZ_Status(void); +static void PS2_KZ_Inject(void); + +static const GAMEDRIVER GAMEDRIVER_INTERFACE = +{ + "Killzone", + PS2_KZ_Status, + PS2_KZ_Inject, + 1, // 1000 Hz tickrate + 0 // crosshair sway not supported for driver +}; + +const GAMEDRIVER *GAME_PS2_KILLZONE = &GAMEDRIVER_INTERFACE; + +static uint32_t camXBase = 0; +static uint32_t camYBase = 0; + +//========================================================================== +// Purpose: return 1 if game is detected +//========================================================================== +static uint8_t PS2_KZ_Status(void) +{ + // SCUS_974.02 + return (PS2_MEM_ReadWord(0x55B58C) == 0x53435553U && + PS2_MEM_ReadWord(0x55B590) == 0x5F393734U && + PS2_MEM_ReadWord(0x55B594) == 0x2E30323BU); +} + +static void PS2_KZ_Inject(void) +{ + // TODO: disable while + // paused + // on objective list + // vault + // loading (may be prevented by canAct value already) + // TODO: camBase sanities + // TODO: gun sway + // TODO: ladder camera + + if(xmouse == 0 && ymouse == 0) // if mouse is idle + return; + + if (!PS2_MEM_ReadUInt(KZ_CAN_ACT)) + return; + + camXBase = PS2_MEM_ReadUInt(KZ_CAMX_BASE_PTR); + camYBase = PS2_MEM_ReadUInt(KZ_CAMY_BASE_PTR); + + float looksensitivity = (float)sensitivity / 40.f; + float scale = 250.f; + // float fov = PS2_MEM_ReadFloat(RTCW_FOV) / 106.5f; + // float fov = 1.f; + float zoom = 1.f / PS2_MEM_ReadFloat(camXBase + KZ_ZOOM); + + float camXSin = PS2_MEM_ReadFloat(camXBase + KZ_CAMX_SIN); + float camXCos = PS2_MEM_ReadFloat(camXBase + KZ_CAMX_COS); + float angle = atan(camXSin / camXCos); + if (camXCos < 0) + angle += TAU / 2.f; + + angle -= (float)xmouse * looksensitivity / scale * zoom; + camXSin = sin(angle); + camXCos = cos(angle); + + PS2_MEM_WriteFloat(camXBase + KZ_CAMX_SIN, camXSin); + PS2_MEM_WriteFloat(camXBase + KZ_CAMX_COS, camXCos); + + float camY = PS2_MEM_ReadFloat(camYBase + KZ_CAMY); + camY -= (float)(invertpitch ? -ymouse : ymouse) * looksensitivity / scale * zoom; + camY = ClampFloat(camY, -1.04719758f, 1.04719758f); + PS2_MEM_WriteFloat(camYBase + KZ_CAMY, (float)camY); + +} \ No newline at end of file diff --git a/games/ps2_timesplitters.c b/games/ps2_timesplitters.c new file mode 100644 index 0000000..5d1f754 --- /dev/null +++ b/games/ps2_timesplitters.c @@ -0,0 +1,139 @@ +//=========================================================== +// Mouse Injector for Dolphin +//========================================================================== +// Copyright (C) 2019-2020 Carnivorous +// All rights reserved. +// +// Mouse Injector is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 of the License, or (at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, visit http://www.gnu.org/licenses/gpl-2.0.html +//========================================================================== +#include +#include "../main.h" +#include "../memory.h" +#include "../mouse.h" +#include "game.h" + +#define TS_CAM_BASE_PTR 0x3AFA20 +#define TS_CAM_BASE_PTR_V110 0x3A40A0 +#define TS_CABASE_SANITY_1_VALUE 0x6666E63F +// offsets from camBase +#define TS_CABASE_SANITY_1 0x68 +#define TS_FOV 0x104 +#define TS_CAMY 0x11C +#define TS_CAMX 0x114 + +#define TS_IS_BUSY_V200 0x352DB4 +#define TS_IS_BUSY_V110 0x347BAC +#define TS_IS_BUSY_SANITY_VALUE 0x686F7374 +// offset from isBusy +#define TS_IS_BUSY_SANITY 0xAC + +static uint8_t PS2_TS_Status(void); +static uint8_t PS2_TS_DetectCamBase(void); +static uint8_t PS2_TS_IsBusy(void); +static void PS2_TS_Inject(void); + +static const GAMEDRIVER GAMEDRIVER_INTERFACE = +{ + "TimeSplitters v2.00", + PS2_TS_Status, + PS2_TS_Inject, + 1, // 1000 Hz tickrate + 0 // crosshair sway not supported for driver +}; + +const GAMEDRIVER *GAME_PS2_TIMESPLITTERS = &GAMEDRIVER_INTERFACE; + +static uint32_t CAM_BASE_PTR_ADDRESSES[] = { + TS_CAM_BASE_PTR, + TS_CAM_BASE_PTR_V110 +}; +static uint32_t IS_BUSY_ADDRESSES[] = { + TS_IS_BUSY_V110, + TS_IS_BUSY_V200 +}; +static uint32_t camBase = 0; + +//========================================================================== +// Purpose: return 1 if game is detected +//========================================================================== +static uint8_t PS2_TS_Status(void) +{ + // SLUS_200.90 + return (PS2_MEM_ReadWord(0x00093390) == 0x534C5553U && + PS2_MEM_ReadWord(0x00093394) == 0x5F323030U && + PS2_MEM_ReadWord(0x00093398) == 0x2E39303BU); +} + +static uint8_t PS2_TS_DetectCamBase(void) +{ + int i; + for (i = 0; i < 2; ++i) + { + uint32_t tempCamBase = PS2_MEM_ReadUInt(CAM_BASE_PTR_ADDRESSES[i]); + if (tempCamBase && + PS2_MEM_ReadWord(tempCamBase + TS_CABASE_SANITY_1) == TS_CABASE_SANITY_1_VALUE) + { + camBase = tempCamBase; + return 1; + } + } + + return 0; +} + +static uint8_t PS2_TS_IsBusy(void) +{ + int i; + for (i = 0; i < 2; ++i) + { + if (PS2_MEM_ReadWord(IS_BUSY_ADDRESSES[i] + TS_IS_BUSY_SANITY) == TS_IS_BUSY_SANITY_VALUE) + { + return PS2_MEM_ReadUInt(IS_BUSY_ADDRESSES[i]); + } + } + return 0; +} + +static void PS2_TS_Inject(void) +{ + // TODO: angle turret on camY extremes + // currently some enemies may be impossible to hit without using analog stick + + if(xmouse == 0 && ymouse == 0) // if mouse is idle + return; + + // if (PS2_MEM_ReadUInt(TS_IS_BUSY)) + // return; + + if (PS2_TS_IsBusy()) + return; + + if (!PS2_TS_DetectCamBase()) + return; + + float looksensitivity = (float)sensitivity / 40.f; + float scale = 5.f; + float fov = PS2_MEM_ReadFloat(camBase + TS_FOV) / 60.f; + // float fov = 1.f; + + float camX = PS2_MEM_ReadFloat(camBase + TS_CAMX); + camX -= (float)xmouse * looksensitivity * fov / scale; + PS2_MEM_WriteFloat(camBase + TS_CAMX, (float)camX); + + float camY = PS2_MEM_ReadFloat(camBase + TS_CAMY); + camY -= (float)(invertpitch ? -ymouse : ymouse) * looksensitivity * fov / scale; + camY = ClampFloat(camY, -50.f, 50.f); + PS2_MEM_WriteFloat(camBase + TS_CAMY, (float)camY); + +} \ No newline at end of file