diff --git a/UnX/UnX.rc b/UnX/UnX.rc index 4371947..241336f 100644 Binary files a/UnX/UnX.rc and b/UnX/UnX.rc differ diff --git a/UnX/cheat.cpp b/UnX/cheat.cpp index f10b9bd..b3ed843 100644 --- a/UnX/cheat.cpp +++ b/UnX/cheat.cpp @@ -26,6 +26,12 @@ #include #include +enum unx_gametype_t { + GAME_INVALID = 0x0, + GAME_FFX = 0x01, + GAME_FFX2 = 0x02 +} game_type = GAME_INVALID; + extern wchar_t* UNX_GetExecutableName (void); extern LPVOID __UNX_base_img_addr; @@ -35,11 +41,15 @@ unx::CheatManager::Init (void) wchar_t* pwszShortName = UNX_GetExecutableName (); - if (! lstrcmpiW (pwszShortName, L"ffx.exe")) + if (! lstrcmpiW (pwszShortName, L"ffx.exe")) { + game_type = GAME_FFX; SetTimer (unx::window.hwnd, CHEAT_TIMER_FFX, 33, nullptr); + } - //else if (! lstrcmpiW (pwszShortName, L"ffx-2.exe")) + else if (! lstrcmpiW (pwszShortName, L"ffx-2.exe")) { + game_type = GAME_FFX2; //SetTimer (unx::window.hwnd, CHEAT_TIMER_FFX2, 33, nullptr); + } } void @@ -59,28 +69,195 @@ enum Sizes_FFX { SIZE_PARTY = 0x94 }; +#include "log.h" + +struct unx_party_s { + uint32_t HP_cur; + uint32_t MP_cur; + + uint32_t HP_max; + uint32_t MP_max; + + uint8_t in_party; + + uint8_t unknown0; + uint8_t unknown1; + + uint8_t strength; + uint8_t defense; + uint8_t magic; + uint8_t magic_defense; + uint8_t agility; + uint8_t luck; + uint8_t evasion; + uint8_t accuracy; + + uint8_t unknown2; + + uint8_t overdrive_mode; + uint8_t overdrive_level; + uint8_t overdrive_max; + + uint8_t sphere_level_banked; + uint8_t sphere_level_net; + + uint8_t unknown3; + + uint32_t skill_flags; + + uint8_t unknown_blob [108]; +}; + +const intptr_t unx_debug_offset = 0xD2A8F8; + +struct unx_debug_s { + uint8_t unk0; + uint8_t unk1; + uint8_t unk2; + uint8_t unk3; + uint8_t free_camera; + uint8_t unk4; + uint8_t unk5; + uint8_t unk6; + uint8_t unk7; + uint8_t unk8; + uint8_t unk9; + uint8_t unk10; + uint8_t unk11; + uint8_t unk12; + uint8_t unk13; + uint8_t unk14; + uint8_t unk15; + uint8_t unk16; + uint8_t unk17; + uint8_t unk18; + uint8_t unk19; + uint8_t unk20; + uint8_t unk21; + uint8_t unk22; + uint8_t unk23; + uint8_t unk24; + uint8_t unk25; + uint8_t unk26; + uint8_t unk27; + uint8_t permanent_sensor; + uint8_t unk28; + uint8_t unk29; +}; + +void +UNX_ToggleFreeLook (void) +{ + if (game_type != GAME_FFX) + return; + + unx_debug_s* + debug = (unx_debug_s *)((uint8_t *)__UNX_base_img_addr + unx_debug_offset); + + debug->free_camera = (! debug->free_camera); +} + +void +UNX_ToggleSensor (void) +{ + config.cheat.ffx.permanent_sensor = (! config.cheat.ffx.permanent_sensor); +} + +bool +UNX_IsInBattle (void) +{ + if (game_type != GAME_FFX) + return false; + + unx_party_s* party = + (unx_party_s *)((uint8_t *)__UNX_base_img_addr + OFFSET_PARTY_BASE); + + uint8_t* lpInBattle = (uint8_t *)__UNX_base_img_addr + OFFSET_IN_BATTLE; + + for (int i = 0; i < 7; i++) { + uint8_t state = party [i].in_party; + + if (state != 0x00 && state != 0x10) { + if (lpInBattle [i] == 1) + return true; + } + } + + return false; +} + +bool +UNX_KillMeNow (void) +{ + return false; + + unx_party_s* party = + (unx_party_s *)((uint8_t *)__UNX_base_img_addr + OFFSET_PARTY_BASE); + + if (! UNX_IsInBattle ()) + return false; + + else { + for (int i = 0; i < 8; i++) { + party [i].HP_cur = 0UL; + } + } + + return true; +} + void unx::CheatTimer_FFX (void) { - uint8_t* lpInParty = (uint8_t *)__UNX_base_img_addr + OFFSET_PARTY_BASE + OFFSET_PARTY_IS_MEMBER; + if (game_type != GAME_FFX) + return; + + unx_party_s* party = + (unx_party_s *)((uint8_t *)__UNX_base_img_addr + OFFSET_PARTY_BASE); + uint8_t* lpInBattle = (uint8_t *)__UNX_base_img_addr + OFFSET_IN_BATTLE; uint8_t* lpGainedAp = (uint8_t *)__UNX_base_img_addr + OFFSET_GAINED_AP; DWORD dwProtect; - if (config.cheat.ffx.entire_party_earns_ap) { + + unx_debug_s* + debug = (unx_debug_s *)((uint8_t *)__UNX_base_img_addr + unx_debug_offset); + + debug->permanent_sensor = config.cheat.ffx.permanent_sensor; + + + if (config.cheat.ffx.playable_seymour) { + party [7].in_party = 0x11; + } else { + party [7].in_party = 0x10; + } + + if (config.cheat.ffx.entire_party_earns_ap && UNX_IsInBattle ()) { VirtualProtect (lpInBattle, 8, PAGE_READWRITE, &dwProtect); - for (int i = 0; i < 8; i++) { - if (*(lpInParty + (i * SIZE_PARTY))) - lpInBattle [i] = 1; + for (int i = 0; i < 7; i++) { + uint8_t state = party [i].in_party; + + if (state != 0x00 && state != 0x10) { + if (lpInBattle [i] != 1) + lpInBattle [i] = 2; + } else { + lpInBattle [i] = 0; + } } VirtualProtect (lpInBattle, 8, dwProtect, &dwProtect); - VirtualProtect (lpGainedAp, 8, PAGE_READWRITE, &dwProtect); - memset (lpGainedAp, 1, 8); + for (int i = 0; i < 7; i++) { + uint8_t state = party [i].in_party; + + if (state != 0x00 && state != 0x10) + lpGainedAp [i] = 1; + else + lpGainedAp [i] = 0; + } VirtualProtect (lpGainedAp, 8, dwProtect, &dwProtect); } @@ -89,4 +266,6 @@ unx::CheatTimer_FFX (void) void unx::CheatTimer_FFX2 (void) { + if (game_type != GAME_FFX2) + return; } \ No newline at end of file diff --git a/UnX/compatibility.cpp b/UnX/compatibility.cpp index 1adb278..4c91033 100644 --- a/UnX/compatibility.cpp +++ b/UnX/compatibility.cpp @@ -70,6 +70,13 @@ BlacklistLibraryW (LPCWSTR lpFileName) return TRUE; } +#if 0 + if (StrStrIW (lpFileName, L"igdusc32")) { + dll_log.Log (L"[Black List] Intel D3D11 Driver Bypassed"); + return TRUE; + } +#endif + #if 0 if (StrStrIW (lpFileName, L"ig75icd32")) { dll_log.Log (L"[Black List] Preventing Intel Integrated OpenGL driver from activating..."); diff --git a/UnX/config.cpp b/UnX/config.cpp index 3cd71ff..49b9d60 100644 --- a/UnX/config.cpp +++ b/UnX/config.cpp @@ -38,7 +38,7 @@ static unx::INI::File* booster_ini = nullptr; -std::wstring UNX_VER_STR = L"0.5.0"; +std::wstring UNX_VER_STR = L"0.5.1"; unx_config_s config; typedef bool (WINAPI *SK_DXGI_EnableFlipMode_pfn) (bool); @@ -80,6 +80,8 @@ struct { struct { struct { unx::ParameterBool* entire_party_earns_ap; + unx::ParameterBool* playable_seymour; + unx::ParameterBool* permanent_sensor; } ffx; } booster; @@ -504,6 +506,26 @@ UNX_LoadConfig (std::wstring name) { L"Boost.FFX", L"EntirePartyEarnsAP" ); + booster.ffx.permanent_sensor = + static_cast + (g_ParameterFactory.create_parameter ( + L"Grant the Sensor ability no matter what weapon is equipped") + ); + booster.ffx.permanent_sensor->register_to_ini ( + booster_ini, + L"Boost.FFX", + L"GrantPermanentSensor" ); + + booster.ffx.playable_seymour = + static_cast + (g_ParameterFactory.create_parameter ( + L"Make Seymour a playable character") + ); + booster.ffx.playable_seymour->register_to_ini ( + booster_ini, + L"Fun.FFX", + L"PlayableSeymour" ); + sys.version = static_cast (g_ParameterFactory.create_parameter ( @@ -636,7 +658,8 @@ UNX_LoadConfig (std::wstring name) { booster.ffx.entire_party_earns_ap->load (config.cheat.ffx.entire_party_earns_ap); - + booster.ffx.permanent_sensor->load (config.cheat.ffx.permanent_sensor); + booster.ffx.playable_seymour->load (config.cheat.ffx.playable_seymour); sys.version->load (config.system.version); sys.injector->load (config.system.injector); @@ -707,6 +730,8 @@ UNX_SaveConfig (std::wstring name, bool close_config) { booster.ffx.entire_party_earns_ap->store (config.cheat.ffx.entire_party_earns_ap); + booster.ffx.permanent_sensor->store (config.cheat.ffx.permanent_sensor); + booster.ffx.playable_seymour->store (config.cheat.ffx.playable_seymour); sys.version->store (UNX_VER_STR); diff --git a/UnX/config.h b/UnX/config.h index c3029ad..fe31e3d 100644 --- a/UnX/config.h +++ b/UnX/config.h @@ -45,6 +45,8 @@ struct unx_config_s struct { struct { bool entire_party_earns_ap = false; + bool playable_seymour = false; + bool permanent_sensor = false; } ffx; } cheat; diff --git a/UnX/input.cpp b/UnX/input.cpp index add2ecb..78e7d00 100644 --- a/UnX/input.cpp +++ b/UnX/input.cpp @@ -83,10 +83,12 @@ struct unx_gamepad_s { static int indexToEnum (int idx) { // For Axes - if (idx < 0) { + if (idx <= 0) { idx = (16 - idx); } + // Possibility for sign-related problems exists if + // 0 is passed, but button 0 is not valid anyway. return 1 << (idx - 1); } @@ -197,7 +199,7 @@ IDirectInputDevice8_SetCooperativeLevel_pfn struct di8_keyboard_s { LPDIRECTINPUTDEVICE pDev = nullptr; - uint8_t state [256]; // Handle overrun just in case + uint8_t state [256]; } _dik; struct di8_mouse_s { @@ -224,7 +226,7 @@ IDirectInputDevice8_GetDeviceState_Detour ( LPDIRECTINPUTDEVICE This, DIJOYSTATE2* out = (DIJOYSTATE2 *)lpvData; // Fix Wonky Input Behavior When Window is Not In Foreground - if (GetForegroundWindow () != SK_GetGameWindow ()) { + if (! unx::window.active/*GetForegroundWindow () != SK_GetGameWindow ()*/) { memset (out, 0, sizeof DIJOYSTATE2); out->rgdwPOV [0] = -1; @@ -238,7 +240,7 @@ IDirectInputDevice8_GetDeviceState_Detour ( LPDIRECTINPUTDEVICE This, for (int i = 0; i < 12; i++) { // Negative values are for axes, we cannot remap those yet - if (gamepad.remap.map [ i ] > 0) { + if (gamepad.remap.map [ i ] >= 0) { out->rgbButtons [ i ] = in.rgbButtons [ gamepad.remap.map [ i ] ]; } @@ -247,6 +249,9 @@ IDirectInputDevice8_GetDeviceState_Detour ( LPDIRECTINPUTDEVICE This, } } + // + // Keyboard + // if (This == _dik.pDev) { if (unx::window.active) { memcpy (_dik.state, lpvData, cbData); @@ -257,38 +262,28 @@ IDirectInputDevice8_GetDeviceState_Detour ( LPDIRECTINPUTDEVICE This, ((uint8_t *)lpvData) [DIK_RALT] = 0x0; ((uint8_t *)lpvData) [DIK_TAB] = 0x0; ((uint8_t *)lpvData) [DIK_ESCAPE] = 0x0; + ((uint8_t *)lpvData) [DIK_UP] = 0x0; + ((uint8_t *)lpvData) [DIK_DOWN] = 0x0; + ((uint8_t *)lpvData) [DIK_LEFT] = 0x0; + ((uint8_t *)lpvData) [DIK_RIGHT] = 0x0; + ((uint8_t *)lpvData) [DIK_RETURN] = 0x0; + ((uint8_t *)lpvData) [DIK_LMENU] = 0x0; + ((uint8_t *)lpvData) [DIK_RMENU] = 0x0; } } -#if 0 - if (unx::window.active && This == _dim.pDev) { -// -// This is only for mouselook, etc. That stuff works fine without aspect ratio correction. -// -//#define FIX_DINPUT8_MOUSE -#ifdef FIX_DINPUT8_MOUSE - if (cbData == sizeof (DIMOUSESTATE) || cbData == sizeof (DIMOUSESTATE2)) { - POINT mouse_pos { ((DIMOUSESTATE *)lpvData)->lX, - ((DIMOUSESTATE *)lpvData)->lY }; - - unx::InputManager::CalcCursorPos (&mouse_pos); - ((DIMOUSESTATE *)lpvData)->lX = mouse_pos.x; - ((DIMOUSESTATE *)lpvData)->lY = mouse_pos.y; - } -#endif -dev + // + // Mouse + // + if (This == _dim.pDev) { + if (unx::window.active) { memcpy (&_dim.state, lpvData, cbData); - } - - else if (unx::window.active && This == _dik.pDev) { - memcpy (&_dik.state, lpvData, cbData); + } else { + memcpy (lpvData, &_dim.state, cbData); } } return hr; -#else - return hr; -#endif } HRESULT @@ -609,6 +604,18 @@ SK_UNX_PluginKeyPress ( BOOL Control, BOOL Alt, BYTE vkCode ) { + if (Control && Shift && vkCode == 'F') { + extern void UNX_ToggleFreeLook (void); + UNX_ToggleFreeLook (); + } + if (Control && Shift && vkCode == 'S') { + extern void UNX_ToggleSensor (void); + UNX_ToggleSensor (); + } + if (Control && Shift && vkCode == 'A') { + config.cheat.ffx.entire_party_earns_ap = (! config.cheat.ffx.entire_party_earns_ap); + } + if (Control && Shift && vkCode == 'V') { eTB_CommandResult result = SK_GetCommandProcessor ()->ProcessCommandLine ("PresentationInterval"); @@ -1459,7 +1466,14 @@ unx::InputManager::Hooker::MessagePump (LPVOID hook_ptr) pressed_scancodes.push (scancode); } if (four_finger) { - SendMessage (SK_GetGameWindow (), WM_CLOSE, 0, 0); + extern bool UNX_KillMeNow (void); + + // If in battle, trigger a Game Over screen, otherwise restart the + // entire game. + if (! UNX_KillMeNow ()) { + SendMessage (SK_GetGameWindow (), WM_CLOSE, 0, 0); + } + Sleep (100); continue; } diff --git a/UnX/language.cpp b/UnX/language.cpp index bf6bc2a..6f59621 100644 --- a/UnX/language.cpp +++ b/UnX/language.cpp @@ -155,6 +155,12 @@ UNX_PatchLanguageFFX (void) "/MetaMenu/GameData/PS3Data/Video/US/timestamp_%s.txt" ); } + extern LPVOID __UNX_base_img_addr; + DWORD dwProtect; + VirtualProtect ((LPVOID)((intptr_t)__UNX_base_img_addr + 0x8e9004), 4, PAGE_READWRITE, &dwProtect); + *(uint32_t *)((intptr_t)__UNX_base_img_addr + 0x8e9004) = 0; + VirtualProtect ((LPVOID)((intptr_t)__UNX_base_img_addr + 0x8e9004), 4, dwProtect, &dwProtect); + return true; } @@ -332,8 +338,9 @@ UNX_PatchLanguage (void) { wchar_t* pwszShortName = UNX_GetExecutableName (); - if (! lstrcmpiW (pwszShortName, L"ffx.exe")) + if (! lstrcmpiW (pwszShortName, L"ffx.exe")) { return UNX_PatchLanguageFFX (); + } else if (! lstrcmpiW (pwszShortName, L"ffx-2.exe")) return UNX_PatchLanguageFFX2 (); diff --git a/UnX/timing.cpp b/UnX/timing.cpp index c0dce4f..d020b34 100644 --- a/UnX/timing.cpp +++ b/UnX/timing.cpp @@ -66,8 +66,11 @@ UNX_SE_FixFramerateLimiter (DWORD dwMilliseconds) //return; } - if (dwMilliseconds == 5) - return; + if (dwMilliseconds == 5) { + YieldProcessor (); + //return; + dwMilliseconds = 0; + } return SK_Sleep (dwMilliseconds); } @@ -102,7 +105,7 @@ unx::TimingFix::Init (void) } if (config.stutter.reduce) { - SK_GetCommandProcessor ()->ProcessCommandFormatted ("MaxDeltaTime 0"); + //SK_GetCommandProcessor ()->ProcessCommandFormatted ("MaxDeltaTime 0"); UNX_CreateDLLHook ( config.system.injector.c_str (), "Sleep_Detour", diff --git a/UnX/window.cpp b/UnX/window.cpp index 8082a3a..0eb645e 100644 --- a/UnX/window.cpp +++ b/UnX/window.cpp @@ -63,18 +63,36 @@ enum unx_fullscreen_op_t { #include void -UNX_SetFullscreenState (unx_fullscreen_op_t op) +UNX_ClearD3D11DevCtx (IDXGISwapChain* pSwapChain) { - static BOOL last_fullscreen = FALSE; - - //pGameSwapChain->GetFullscreenState (&last_fullscreen, nullptr); CComPtr pDev; - if (SUCCEEDED (pGameSwapChain->GetDevice (IID_PPV_ARGS (&pDev)))) { + if (SUCCEEDED (pSwapChain->GetDevice (IID_PPV_ARGS (&pDev)))) { CComPtr pDevCtx; pDev->GetImmediateContext (&pDevCtx); + pDevCtx->Flush (); pDevCtx->ClearState (); + } +} + +void UNX_SetFullscreenState (unx_fullscreen_op_t op); + +DWORD +WINAPI +FullScreenThread (LPVOID user) +{ + unx_fullscreen_op_t op = + *(unx_fullscreen_op_t *)user; + + static BOOL last_fullscreen = FALSE; + + CComPtr pOut = nullptr; + + UNX_ClearD3D11DevCtx (pGameSwapChain); + + BOOL fs; + pGameSwapChain->GetFullscreenState (&fs, nullptr);//&pOut); #if 0 CComPtr pOutput; @@ -82,29 +100,86 @@ UNX_SetFullscreenState (unx_fullscreen_op_t op) pOutput->ReleaseOwnership (); #endif - if (op == Fullscreen) { - /* - DXGI_MODE_DESC mode = { 0 }; - mode.Width = 3840; - mode.Height = 2160; - mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - mode.RefreshRate = { 0 }; - pGameSwapChain->ResizeTarget (&mode); - pGameSwapChain->SetFullscreenState (TRUE, nullptr); - pGameSwapChain->ResizeBuffers (0, 0, 0, DXGI_FORMAT_UNKNOWN, 0x02); - */ - pGameSwapChain->SetFullscreenState (TRUE, nullptr); - } else { - if (op == Restore) { - UNX_SetFullscreenState (last_fullscreen ? Fullscreen : Window); - } + if (op == Fullscreen) { + /* + DXGI_MODE_DESC mode = { 0 }; + mode.Width = 3840; + mode.Height = 2160; + mode.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + mode.RefreshRate = { 0 }; + pGameSwapChain->ResizeTarget (&mode); + pGameSwapChain->SetFullscreenState (TRUE, nullptr); + pGameSwapChain->ResizeBuffers (0, 0, 0, DXGI_FORMAT_UNKNOWN, 0x02); + */ + + if (fs != TRUE) { + dll_log.Log (L"[Fullscreen] Transition: Window -> Full"); + + last_fullscreen = fs; + + UNX_ClearD3D11DevCtx (pGameSwapChain); + + INPUT keys [2]; - if (op == Window) { - pGameSwapChain->GetFullscreenState (&last_fullscreen, nullptr); - pGameSwapChain->SetFullscreenState (FALSE, nullptr); + keys [0].type = INPUT_KEYBOARD; + keys [0].ki.wVk = 0; + keys [0].ki.dwFlags = KEYEVENTF_SCANCODE; + keys [0].ki.time = 0; + keys [0].ki.dwExtraInfo = 0; + + keys [1].type = INPUT_KEYBOARD; + keys [1].ki.wVk = 0; + keys [1].ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP; + keys [1].ki.time = 0; + keys [1].ki.dwExtraInfo = 0; + + // Alt + keys [0].ki.wScan = 0x38; + SendInput (1, &keys [0], sizeof INPUT); + + // Enter + keys [0].ki.wScan = 0x1c; + SendInput (1, &keys [0], sizeof INPUT); + + Sleep (0); + + // Enter + keys [1].ki.wScan = 0x1c; + SendInput (1, &keys [1], sizeof INPUT); + + // Alt + keys [1].ki.wScan = 0x38; + SendInput (1, &keys [1], sizeof INPUT); + } + } else { + if (op == Restore) { + dll_log.Log (L"[Fullscreen] Operation: *Restore"); + UNX_SetFullscreenState (last_fullscreen ? Fullscreen : Window); + last_fullscreen = fs; + } + + if (op == Window) { + if (fs == TRUE) { + dll_log.Log (L"[Fullscreen] Transition: Full -> Window"); + + last_fullscreen = fs; + + UNX_ClearD3D11DevCtx (pGameSwapChain); + + pGameSwapChain->SetFullscreenState (FALSE, pOut); + //pGameSwapChain->ResizeBuffers (0, 0, 0, DXGI_FORMAT_UNKNOWN, 0x02); } } } + + return 0; +} + +void +UNX_SetFullscreenState (unx_fullscreen_op_t op) +{ + FullScreenThread (&op); + //CreateThread (nullptr, 0, FullScreenThread, &op, 0, nullptr); } @@ -225,7 +300,7 @@ DetourWindowProc ( _In_ HWND hWnd, //unx::window.active = (! deactivate); - dll_log.Log ( L"[ Window ] Activation: %s", + dll_log.Log ( L"[Window Mgr] Activation: %s", unx::window.active ? L"ACTIVE" : L"INACTIVE" );