diff --git a/UnX/UnX.vcxproj b/UnX/UnX.vcxproj
index 947abb0..27a9a3c 100644
--- a/UnX/UnX.vcxproj
+++ b/UnX/UnX.vcxproj
@@ -79,6 +79,8 @@
false
C:\Program Files (x86)\Steam\steamapps\common\FINAL FANTASY FFX&FFX-2 HD Remaster\
unx
+ AllRules.ruleset
+ false
false
@@ -129,6 +131,7 @@
false
true
true
+ false
Windows
diff --git a/UnX/cheat.cpp b/UnX/cheat.cpp
index d033c25..b5390cc 100644
--- a/UnX/cheat.cpp
+++ b/UnX/cheat.cpp
@@ -32,44 +32,214 @@ enum unx_gametype_t {
GAME_FFX2 = 0x02
} game_type = GAME_INVALID;
-enum Offsets_FFX {
- OFFSET_PARTY_BASE = 0x0D32078,
- OFFSET_IN_BATTLE = 0x1F10EA0,
- OFFSET_GAINED_AP = 0x1F10EC4,
-
- OFFSET_PARTY_IS_MEMBER = 0x10
-};
-
-enum Sizes_FFX {
- SIZE_PARTY = 0x94
-};
-
-struct unx_debug_ffx2_s {
- uint8_t invincible_allies; // 0x9F78B8
- uint8_t invincible_enemies; // 0x9F78B9
- uint8_t unknown [4]; // 0x9F78BA
- uint8_t control_enemies; // 0x9F78BE
- uint8_t control_monsters; // 0x9F78BF
- uint8_t unknown1 [5]; // 0x9F78C0
- uint8_t mp_zero; // 0x9F78C5
- uint8_t unknown2 [5]; // 0x9F78C6
- uint8_t always_critical; // 0x9F78CC
- uint8_t critical; // 0x9F78CD
- uint8_t probability_100; // 0x9F78CE
- uint8_t unknown3 [2]; // 0x9F78CF
- uint8_t damage_random; // 0x9F78D1
- uint8_t damage_1; // 0x9F78D2
- uint8_t damage_9999; // 0x9F78D3
- uint8_t damage_99999; // 0x9F78D4
- uint8_t rare_drop_100; // 0x9F78D5
- uint8_t exp_100x; // 0x9F78D6
- uint8_t gil_100x; // 0x9F78D7
- uint8_t unknown4; // 0x9F78D8
- uint8_t always_oversoul; // 0x9F78D9
- uint8_t unknown5 [10]; // 0x9F78DA
- uint8_t first_attack; // 0x9F78E4 (0xFF = OFF)
-} *ffx2_debug_flags = nullptr;
+struct unx_ffx2_memory_s {
+ struct {
+ enum offset_t {
+ Debug = 0x9F78B8
+ };
+ } offsets;
+
+ struct debug_s {
+ struct {
+ uint8_t allies; // 0x9F78B8
+ uint8_t enemies; // 0x9F78B9
+ } invincible;
+
+ uint8_t unknown [4]; // 0x9F78BA
+
+ struct {
+ uint8_t enemies; // 0x9F78BE
+ uint8_t monsters; // 0x9F78BF
+ } control;
+
+ uint8_t unknown1 [5]; // 0x9F78C0
+
+ uint8_t mp_zero; // 0x9F78C5
+ uint8_t unknown2 [5]; // 0x9F78C6
+
+ struct {
+ uint8_t always_critical; // 0x9F78CC
+ uint8_t critical; // 0x9F78CD
+ uint8_t probability_100; // 0x9F78CE
+ uint8_t unknown3 [2]; // 0x9F78CF
+ uint8_t damage_random; // 0x9F78D1
+ uint8_t damage_1; // 0x9F78D2
+ uint8_t damage_9999; // 0x9F78D3
+ uint8_t damage_99999; // 0x9F78D4
+ } damage;
+
+ struct {
+ uint8_t always_drop_rare; // 0x9F78D5
+ uint8_t exp_100x; // 0x9F78D6
+ uint8_t gil_100x; // 0x9F78D7
+ } reward;
+
+ uint8_t unknown4; // 0x9F78D8
+
+ uint8_t always_oversoul; // 0x9F78D9
+
+ uint8_t unknown5 [10]; // 0x9F78DA
+
+ uint8_t first_attack; // 0x9F78E4 (0xFF = OFF)
+ } *debug_flags = nullptr;
+} ffx2;
+
+
+struct unx_ffx_memory_s {
+ struct {
+ enum offset_t {
+ PartyBase = 0x0D32060,
+ InBattle = 0x1F10EA0,
+ GainedAp = 0x1F10EC4,
+ Debug = 0x0D2A8F8
+ };
+ } offsets;
+
+ struct {
+ enum character_t {
+ Tidus = 0,
+ Yuna = 1,
+ Auron = 2,
+ Kimahri = 3,
+ Wakka = 4,
+ Lulu = 5,
+ Rikku = 6,
+ Seymour = 7
+ };
+ } characters;
+
+
+ struct debug_s {
+ struct {
+ uint8_t enemies;
+ uint8_t party;
+ } invincible;
+
+ struct {
+ uint8_t enemies;
+ uint8_t unk3;
+ uint8_t camera;
+ } control;
+
+ 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;
+
+ struct {
+ uint8_t always_overdrive;
+ uint8_t always_critical;
+ uint8_t always_deal_1;
+ uint8_t always_deal_10000;
+ uint8_t always_deal_99999;
+ } damage;
+
+ struct {
+ uint8_t always_rare_drop;
+ uint8_t ap_100x;
+ uint8_t gil_100x;
+ } reward;
+
+ uint8_t unk27;
+ uint8_t permanent_sensor;
+ uint8_t unk28;
+ uint8_t unk29;
+ } *debug_flags = nullptr;
+
+ struct party_s {
+ struct {
+ uint32_t HP;
+ uint32_t MP;
+ 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;
+ } base;
+
+ struct {
+ uint32_t total;
+ uint32_t current;
+ } AP;
+
+ struct {
+ struct {
+ uint32_t HP;
+ uint32_t MP;
+ } current;
+
+ struct {
+ uint32_t HP;
+ uint32_t MP;
+ } max;
+ } vitals;
+
+ uint8_t in_party;
+
+ struct {
+ uint8_t weapon;
+ uint8_t armor;
+ } equipment;
+
+ struct {
+ 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;
+ } current;
+
+ uint8_t unknown2;
+
+ struct {
+ uint8_t mode;
+ uint8_t level;
+ uint8_t max;
+ } overdrive;
+
+ struct {
+ uint8_t banked;
+ uint8_t total;
+ } sphere_level;
+
+ uint8_t unknown3;
+
+ uint32_t skill_flags;
+
+ struct {
+ uint32_t battles;
+ uint32_t kills;
+ } record;
+
+ uint8_t unknown_blob [76];
+ } *party = nullptr;
+
+ struct battle_s {
+ uint8_t participation;
+ } *battle = nullptr;
+
+ struct ap_s {
+ uint8_t earn;
+ } *ap = nullptr;
+} ffx;
extern wchar_t* UNX_GetExecutableName (void);
extern LPVOID __UNX_base_img_addr;
@@ -80,15 +250,41 @@ unx::CheatManager::Init (void)
wchar_t* pwszShortName =
UNX_GetExecutableName ();
+ //
+ // FFX
+ //
if (! lstrcmpiW (pwszShortName, L"ffx.exe")) {
game_type = GAME_FFX;
+
+ ffx.debug_flags =
+ (unx_ffx_memory_s::debug_s *)
+ ((intptr_t)__UNX_base_img_addr + ffx.offsets.Debug);
+
+ ffx.party =
+ (unx_ffx_memory_s::party_s *)
+ ((intptr_t)__UNX_base_img_addr + ffx.offsets.PartyBase);
+
+ ffx.battle =
+ (unx_ffx_memory_s::battle_s *)
+ ((intptr_t)__UNX_base_img_addr + ffx.offsets.InBattle);
+
+ ffx.ap =
+ (unx_ffx_memory_s::ap_s *)
+ ((intptr_t)__UNX_base_img_addr + ffx.offsets.GainedAp);
+
SetTimer (unx::window.hwnd, CHEAT_TIMER_FFX, 33, nullptr);
}
+ //
+ // FFX-2
+ //
else if (! lstrcmpiW (pwszShortName, L"ffx-2.exe")) {
game_type = GAME_FFX2;
- ffx2_debug_flags = (unx_debug_ffx2_s *)((uint8_t *)__UNX_base_img_addr + 0x9F78B8);
- //ffx2_debug_flags->always_critical = 1;
+
+ ffx2.debug_flags =
+ (unx_ffx2_memory_s::debug_s *)
+ ((intptr_t)__UNX_base_img_addr + ffx2.offsets.Debug);
+
SetTimer (unx::window.hwnd, CHEAT_TIMER_FFX2, 33, nullptr);
}
}
@@ -100,96 +296,21 @@ unx::CheatManager::Shutdown (void)
#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);
+ ffx.debug_flags->control.camera =
+ (! ffx.debug_flags->control.camera);
}
void
UNX_ToggleSensor (void)
{
- config.cheat.ffx.permanent_sensor = (! config.cheat.ffx.permanent_sensor);
+ config.cheat.ffx.permanent_sensor =
+ (! config.cheat.ffx.permanent_sensor);
}
bool
@@ -198,16 +319,11 @@ 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;
+ uint8_t state = ffx.party [i].in_party;
if (state != 0x00 && state != 0x10) {
- if (lpInBattle [i] == 1)
+ if (ffx.battle [i].participation == 1)
return true;
}
}
@@ -218,18 +334,25 @@ UNX_IsInBattle (void)
bool
UNX_KillMeNow (void)
{
- return false;
+ if (game_type != GAME_FFX)
+ return false;
- unx_party_s* party =
- (unx_party_s *)((uint8_t *)__UNX_base_img_addr + OFFSET_PARTY_BASE);
+ return false;
if (! UNX_IsInBattle ())
return false;
else {
+#if 0
+ std::queue suspended_tids =
+ UNX_SuspendAllOtherThreads ();
+
for (int i = 0; i < 8; i++) {
- party [i].HP_cur = 0UL;
+ ffx.party [i].vitals.current.HP = 0UL;
}
+
+ UNX_ResumeThreads (suspended_tids);
+#endif
}
return true;
@@ -241,54 +364,45 @@ unx::CheatTimer_FFX (void)
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;
-
- unx_debug_s*
- debug = (unx_debug_s *)((uint8_t *)__UNX_base_img_addr + unx_debug_offset);
-
- debug->permanent_sensor = config.cheat.ffx.permanent_sensor;
+ ffx.debug_flags->permanent_sensor =
+ config.cheat.ffx.permanent_sensor;
if (config.cheat.ffx.playable_seymour) {
- party [7].in_party = 0x11;
+ ffx.party [ffx.characters.Seymour].in_party = 0x11;
} else {
- party [7].in_party = 0x10;
+ ffx.party [ffx.characters.Seymour].in_party = 0x10;
}
if (config.cheat.ffx.entire_party_earns_ap && UNX_IsInBattle ()) {
- VirtualProtect (lpInBattle, 8, PAGE_READWRITE, &dwProtect);
+ VirtualProtect (&ffx.battle->participation, 8, PAGE_READWRITE, &dwProtect);
for (int i = 0; i < 7; i++) {
- uint8_t state = party [i].in_party;
+ uint8_t state = ffx.party [i].in_party;
if (state != 0x00 && state != 0x10) {
- if (lpInBattle [i] != 1)
- lpInBattle [i] = 2;
+ if (ffx.battle [i].participation != 1)
+ ffx.battle [i].participation = 2;
} else {
- lpInBattle [i] = 0;
+ ffx.battle [i].participation = 0;
}
}
- VirtualProtect (lpInBattle, 8, dwProtect, &dwProtect);
- VirtualProtect (lpGainedAp, 8, PAGE_READWRITE, &dwProtect);
+ VirtualProtect (&ffx.battle->participation, 8, dwProtect, &dwProtect);
+ VirtualProtect (&ffx.ap->earn, 8, PAGE_READWRITE, &dwProtect);
for (int i = 0; i < 7; i++) {
- uint8_t state = party [i].in_party;
+ uint8_t state = ffx.party [i].in_party;
if (state != 0x00 && state != 0x10)
- lpGainedAp [i] = 1;
+ ffx.ap [i].earn = 1;
else
- lpGainedAp [i] = 0;
+ ffx.ap [i].earn = 0;
}
- VirtualProtect (lpGainedAp, 8, dwProtect, &dwProtect);
+ VirtualProtect (&ffx.ap->earn, 8, dwProtect, &dwProtect);
}
}
@@ -297,4 +411,78 @@ unx::CheatTimer_FFX2 (void)
{
if (game_type != GAME_FFX2)
return;
+}
+
+
+
+
+
+
+#include
+#include
+#include
+
+std::queue
+UNX_SuspendAllOtherThreads (void)
+{
+ std::queue threads;
+
+ HANDLE hSnap =
+ CreateToolhelp32Snapshot (TH32CS_SNAPTHREAD, 0);
+
+ if (hSnap != INVALID_HANDLE_VALUE)
+ {
+ THREADENTRY32 tent;
+ tent.dwSize = sizeof THREADENTRY32;
+
+ if (Thread32First (hSnap, &tent))
+ {
+ do
+ {
+ if ( tent.dwSize >= FIELD_OFFSET (THREADENTRY32, th32OwnerProcessID) +
+ sizeof (tent.th32OwnerProcessID) )
+ {
+ if ( tent.th32ThreadID != GetCurrentThreadId () &&
+ tent.th32OwnerProcessID == GetCurrentProcessId () )
+ {
+ HANDLE hThread =
+ OpenThread (THREAD_ALL_ACCESS, FALSE, tent.th32ThreadID);
+
+ if (hThread != NULL)
+ {
+ threads.push (tent.th32ThreadID);
+ SuspendThread (hThread);
+ CloseHandle (hThread);
+ }
+ }
+ }
+
+ tent.dwSize = sizeof (tent);
+ } while (Thread32Next (hSnap, &tent));
+ }
+
+ CloseHandle (hSnap);
+ }
+
+ return threads;
+}
+
+void
+UNX_ResumeThreads (std::queue threads)
+{
+ while (! threads.empty ())
+ {
+ DWORD tid = threads.front ();
+
+ HANDLE hThread =
+ OpenThread (THREAD_ALL_ACCESS, FALSE, tid);
+
+ if (hThread != NULL)
+ {
+ ResumeThread (hThread);
+ CloseHandle (hThread);
+ }
+
+ threads.pop ();
+ }
}
\ No newline at end of file
diff --git a/UnX/input.cpp b/UnX/input.cpp
index 83e5521..d4b9ce2 100644
--- a/UnX/input.cpp
+++ b/UnX/input.cpp
@@ -199,7 +199,7 @@ IDirectInputDevice8_SetCooperativeLevel_pfn
struct di8_keyboard_s {
LPDIRECTINPUTDEVICE pDev = nullptr;
- uint8_t state [256];
+ uint8_t state [512];
} _dik;
struct di8_mouse_s {
@@ -518,20 +518,20 @@ typedef DWORD (WINAPI *XInputGetState_pfn)(
XInputGetState_pfn XInputGetState_Original = nullptr;
bool
-IsControllerPluggedIn (UINT uJoyID)
+IsControllerPluggedIn (INT iJoyID)
{
- if (uJoyID == (UINT)-1)
+ if (iJoyID == -1)
return true;
XINPUT_STATE xstate;
static DWORD last_poll = timeGetTime ();
- static DWORD dwRet = XInputGetState_Original (uJoyID, &xstate);
+ static DWORD dwRet = XInputGetState_Original (iJoyID, &xstate);
// This function is actually a performance hazzard when no controllers
// are plugged in, so ... throttle the sucker.
if (last_poll < timeGetTime () - 500UL)
- dwRet = XInputGetState_Original (uJoyID, &xstate);
+ dwRet = XInputGetState_Original (iJoyID, &xstate);
if (dwRet == ERROR_DEVICE_NOT_CONNECTED)
return false;
@@ -552,8 +552,8 @@ XInputGetState_Detour ( _In_ DWORD dwUserIndex,
DWORD dwRet = XInputGetState_Original (slot, pState);
- if (dwRet == ERROR_NOT_CONNECTED)
- dwRet = 0;
+ //if (dwRet == ERROR_NOT_CONNECTED)
+ //dwRet = 0;
return dwRet;
}
@@ -1404,7 +1404,7 @@ unx::InputManager::Hooker::MessagePump (LPVOID hook_ptr)
if (UNX_PollAxis (gamepad.remap.buttons.RS, joy_ex, caps) > 190)
xi_state.Gamepad.wButtons |= XINPUT_GAMEPAD_RIGHT_THUMB;
- if (joy_ex.dwPOV & JOY_POVFORWARD)
+ if (joy_ex.dwPOV == JOY_POVFORWARD)
xi_state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_UP;
if (joy_ex.dwPOV & JOY_POVBACKWARD)
xi_state.Gamepad.wButtons |= XINPUT_GAMEPAD_DPAD_DOWN;
@@ -1479,6 +1479,14 @@ unx::InputManager::Hooker::MessagePump (LPVOID hook_ptr)
}
if (esc.state) {
+/*
+FFX.exe+302C4F - 6A 01 - push 01 { 00000001 }
+FFX.exe+302C51 - 6A 00 - push 00 { 0 }
+FFX.exe+302C53 - 6A 00 - push 00 { 0 }
+FFX.exe+302C55 - 68 78CE8700 - push FFX.exe+74CE78 { ["showSaveLoad"] }
+FFX.exe+302C5A - 6A 00 - push 00 { 0 }
+FFX.exe+302C5C - E8 3F5F3200 - call FFX.exe+628BA0
+*/
#if 0
extern void*
UNX_Scan (const uint8_t* pattern, size_t len, const uint8_t* mask);
diff --git a/UnX/language.cpp b/UnX/language.cpp
index 6f59621..0523cae 100644
--- a/UnX/language.cpp
+++ b/UnX/language.cpp
@@ -155,12 +155,6 @@ 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;
}
diff --git a/UnX/timing.cpp b/UnX/timing.cpp
index d020b34..04dca9e 100644
--- a/UnX/timing.cpp
+++ b/UnX/timing.cpp
@@ -57,19 +57,36 @@ HMODULE NtDll = 0;
NtQueryTimerResolution_pfn NtQueryTimerResolution = nullptr;
NtSetTimerResolution_pfn NtSetTimerResolution = nullptr;
+typedef DWORD (WINAPI *SleepEx_pfn)(
+ _In_ DWORD dwMilliseconds,
+ _In_ BOOL bAlertable
+);
+
+SleepEx_pfn SleepEx_Original = nullptr;
+
+DWORD
+SleepEx_Detour (DWORD dwMilliseconds, BOOL bAlertable)
+{
+ if (dwMilliseconds > 5)
+ dwMilliseconds = 5;
+
+ return SleepEx_Original (dwMilliseconds, bAlertable);
+}
+
+
void
WINAPI
UNX_SE_FixFramerateLimiter (DWORD dwMilliseconds)
{
if (dwMilliseconds == 0) {
YieldProcessor ();
- //return;
+ return;
}
if (dwMilliseconds == 5) {
- YieldProcessor ();
- //return;
- dwMilliseconds = 0;
+ //YieldProcessor ();
+ return;
+ ////dwMilliseconds = 0;
}
return SK_Sleep (dwMilliseconds);
@@ -111,6 +128,11 @@ unx::TimingFix::Init (void)
"Sleep_Detour",
UNX_SE_FixFramerateLimiter,
(LPVOID *)&SK_Sleep );
+
+ UNX_CreateDLLHook ( L"kernel32.dll",
+ "SleepEx",
+ SleepEx_Detour,
+ (LPVOID *)&SleepEx_Original );
}
HMODULE hModKernel32 = LoadLibrary (L"kernel32.dll");
diff --git a/UnX/window.cpp b/UnX/window.cpp
index b0b22e8..a230433 100644
--- a/UnX/window.cpp
+++ b/UnX/window.cpp
@@ -91,30 +91,12 @@ UNX_IsWindowThread (void)
return false;
}
-void
-UNX_ClearD3D11DevCtx (IDXGISwapChain* pSwapChain)
-{
- CComPtr pDev;
-
- if (SUCCEEDED (pSwapChain->GetDevice (IID_PPV_ARGS (&pDev)))) {
- CComPtr pDevCtx;
-
- pDev->GetImmediateContext (&pDevCtx);
- pDevCtx->Flush ();
- pDevCtx->ClearState ();
- }
-}
-
-void
-UNX_ToggleFullscreen (void)
+DWORD
+WINAPI
+UNX_ToggleFullscreenThread (LPVOID user)
{
- // Mod is not yet fully initialized...
- if (! pGameSwapChain)
- return;
-
- BOOL fullscreen = FALSE;
-
- CComPtr pOutput = nullptr;
+ BOOL fullscreen = FALSE;
+ CComPtr pOutput = nullptr;
if (SUCCEEDED (pGameSwapChain->GetFullscreenState (&fullscreen, &pOutput))) {
if (fullscreen) {
@@ -123,18 +105,32 @@ UNX_ToggleFullscreen (void)
DXGI_SWAP_CHAIN_DESC swap_desc;
pGameSwapChain->GetDesc (&swap_desc);
- DXGI_MODE_DESC mode = swap_desc.BufferDesc;
+ DXGI_MODE_DESC mode = swap_desc.BufferDesc;
- pGameSwapChain->ResizeTarget (&mode);
+ pGameSwapChain->ResizeTarget (&mode);
pGameSwapChain->SetFullscreenState (TRUE, pOutput);
mode.RefreshRate.Denominator = 0;
mode.RefreshRate.Numerator = 0;
- pGameSwapChain->ResizeTarget (&mode);
+ pGameSwapChain->ResizeTarget (&mode);
pGameSwapChain->ResizeBuffers (0, 0, 0, DXGI_FORMAT_UNKNOWN, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
}
}
+
+ return 0;
+}
+
+void
+UNX_ToggleFullscreen (void)
+{
+ // Mod is not yet fully initialized...
+ if (! pGameSwapChain)
+ return;
+
+ // It is not safe to issue DXGI commands from the thread that drives
+ // the Windows message pump... so spawn a separate thread to do this.
+ CreateThread (nullptr, 0, UNX_ToggleFullscreenThread, nullptr, 0, nullptr);
}
@@ -145,8 +141,6 @@ UNX_SetFullscreenState (unx_fullscreen_op_t op)
{
static BOOL last_fullscreen = FALSE;
- UNX_ClearD3D11DevCtx (pGameSwapChain);
-
// Mod is not yet fully initialized...
if (pGameSwapChain == nullptr)
return;
@@ -196,28 +190,6 @@ DetourWindowProc ( _In_ HWND hWnd,
bool windowed = false;
-#include
-#pragma comment (lib, "dwmapi.lib")
-
-typedef BOOL (WINAPI *GetWindowInfo_pfn)(
- _In_ HWND hwnd,
- _Inout_ PWINDOWINFO pwi
-);
-
-GetWindowInfo_pfn GetWindowInfo_Original = nullptr;
-
-BOOL
-WINAPI
-GetWindowInfo_Detour ( _In_ HWND hWnd,
- _Inout_ PWINDOWINFO pwi )
-{
- BOOL ret =
- GetWindowInfo_Original (hWnd, pwi);
-
- return ret;
-}
-
-
typedef LRESULT (CALLBACK *DetourWindowProc_pfn)( _In_ HWND hWnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
@@ -256,6 +228,7 @@ DetourWindowProc ( _In_ HWND hWnd,
}
+
// This state is persistent and we do not want Alt+F4 to remember a muted
// state.
if (uMsg == WM_DESTROY || uMsg == WM_QUIT || (config.input.fast_exit && uMsg == WM_CLOSE)) {
@@ -303,8 +276,6 @@ DetourWindowProc ( _In_ HWND hWnd,
UNX_SetGameMute (bMute);
}
- //unx::window.active = (! deactivate);
-
dll_log.Log ( L"[Window Mgr] Activation: %s",
unx::window.active ? L"ACTIVE" :
L"INACTIVE" );
@@ -314,11 +285,9 @@ DetourWindowProc ( _In_ HWND hWnd,
//
if (pGameSwapChain != nullptr && config.display.enable_fullscreen) {
if (! deactivate) {
- if (unx::window.fullscreen)
- UNX_ToggleFullscreen ();
+ UNX_SetFullscreenState (Restore);
} else {
- if (unx::window.fullscreen)
- UNX_ToggleFullscreen ();
+ UNX_SetFullscreenState (Window);
}
}
}
@@ -365,9 +334,7 @@ DetourWindowProc ( _In_ HWND hWnd,
// Alt + Enter (Fullscreen toggle)
if (uMsg == WM_SYSKEYDOWN && wParam == VK_RETURN) {
-
- if (pGameSwapChain) {
- unx::window.fullscreen = (! unx::window.fullscreen);
+ if (pGameSwapChain && config.display.enable_fullscreen) {
UNX_ToggleFullscreen ();
return DefWindowProc (hWnd, uMsg, wParam, lParam);
}
@@ -380,7 +347,7 @@ DetourWindowProc ( _In_ HWND hWnd,
// What an ugly mess, this is crazy :)
if (config.input.cursor_mgmt) {
- extern bool IsControllerPluggedIn (UINT uJoyID);
+ extern bool IsControllerPluggedIn (INT iJoyID);
struct {
POINTS pos = { 0 }; // POINT (Short) - Not POINT plural ;)
@@ -493,14 +460,14 @@ DXGISwap_ResizeBuffers_Detour (
if (pGameSwapChain) {
if (SUCCEEDED (pGameSwapChain->GetFullscreenState (&fullscreen, nullptr))) {
- if (fullscreen)
+ if (fullscreen) // Moving the window in fullscreen mode is bad mojo
should_center = false;
}
}
}
- if (pGameSwapChain == This && config.display.enable_fullscreen) {
+ if (pGameSwapChain == This /*&& config.display.enable_fullscreen*/) {
//
// Allow Alt+Enter
//
@@ -515,32 +482,24 @@ DXGISwap_ResizeBuffers_Detour (
SUCCEEDED (pDevDXGI->GetAdapter (&pAdapter) ) &&
SUCCEEDED ( pAdapter->GetParent (IID_PPV_ARGS (&pFactory)) ) )
{
- DXGI_SWAP_CHAIN_DESC desc;
-
- if (SUCCEEDED (pGameSwapChain->GetDesc (&desc))) {
+ dll_log.Log ( L"[Fullscreen] Setting DXGI Window Association "
+ L"(HWND: Game=%X,SwapChain=%X - flags=DXGI_MWA_NO_WINDOW_CHANGES)",
+ SK_GetGameWindow (), desc.OutputWindow );
- dll_log.Log ( L"[Fullscreen] Setting DXGI Window Association "
- L"(HWND: Game=%X,SwapChain=%X - flags=DXGI_MWA_NO_WINDOW_CHANGES)",
- SK_GetGameWindow (), desc.OutputWindow );
-
- pFactory->MakeWindowAssociation (desc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES);
- }
+ pFactory->MakeWindowAssociation (desc.OutputWindow, DXGI_MWA_NO_WINDOW_CHANGES |
+ DXGI_MWA_NO_ALT_ENTER );
// Allow Fullscreen
- SwapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ if (config.display.enable_fullscreen)
+ SwapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ else
+ SwapChainFlags = 0x00;
}
}
HRESULT hr =
DXGISwap_ResizeBuffers_Original (This, BufferCount, Width, Height, NewFormat, SwapChainFlags);
-
- if ( pGameSwapChain == This && config.display.enable_fullscreen && BufferCount != 0 && Width != 0 && Height != 0)
- {
- if (UNX_IsRenderThread ()) {
- }
- }
-
if (should_center) {
MONITORINFO moninfo;
moninfo.cbSize = sizeof MONITORINFO;
@@ -550,38 +509,17 @@ DXGISwap_ResizeBuffers_Detour (
int mon_width = moninfo.rcMonitor.right - moninfo.rcMonitor.left;
int mon_height = moninfo.rcMonitor.bottom - moninfo.rcMonitor.top;
- if (Width < mon_width && Height < mon_height) {
+ if (Width <= mon_width && Height <= mon_height) {
SetWindowPos ( SK_GetGameWindow (), HWND_NOTOPMOST, (mon_width - Width) / 2,
(mon_height - Height) / 2,
Width, Height,
- SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_NOACTIVATE );
+ SWP_NOSIZE | SWP_NOSENDCHANGING );
}
}
return hr;
}
-HRESULT
-WINAPI
-DXGISwap_ResizeTarget_Detour (
- IDXGISwapChain *This,
- DXGI_MODE_DESC *desc )
-{
- if ( pGameSwapChain == This && config.display.enable_fullscreen &&
- ( desc->RefreshRate.Denominator != 0 || desc->RefreshRate.Numerator != 0 ) )
- {
- if (UNX_IsRenderThread ()) {
- ////mode_changes.push (Window);
- //UNX_SetFullscreenState (Window);
- }
- }
-
- HRESULT hr =
- DXGISwap_ResizeTarget_Original (This, desc);
-
- return hr;
-}
-
typedef HRESULT (WINAPI *SK_BeginBufferSwap_pfn)(void);
SK_BeginBufferSwap_pfn SK_BeginBufferSwap_Original = nullptr;
@@ -592,9 +530,14 @@ SK_BeginBufferSwap_Detour (void)
if (unx::window.render_thread == 0)
unx::window.render_thread = GetCurrentThreadId ();
- if (UNX_IsRenderThread ())
- {
+#if 0
+ CComPtr pOut;
+
+ if ( pGameSwapChain != nullptr &&
+ SUCCEEDED (pGameSwapChain->GetContainingOutput (&pOut)) ) {
+ pOut->WaitForVBlank ();
}
+#endif
return SK_BeginBufferSwap_Original ();
}
@@ -614,22 +557,10 @@ UNX_InstallWindowHook (HWND hWnd)
DetourWindowProc,
(LPVOID *)&DetourWindowProc_Original );
- //DwmEnableMMCSS (TRUE);
-
UNX_CreateDLLHook ( config.system.injector.c_str (),
"DXGISwap_ResizeBuffers_Override",
DXGISwap_ResizeBuffers_Detour,
(LPVOID *)&DXGISwap_ResizeBuffers_Original );
-
- UNX_CreateDLLHook ( config.system.injector.c_str (),
- "DXGISwap_ResizeTarget_Override",
- DXGISwap_ResizeTarget_Detour,
- (LPVOID *)&DXGISwap_ResizeTarget_Original );
-
- UNX_CreateDLLHook ( L"user32.dll",
- "GetWindowInfo",
- GetWindowInfo_Detour,
- (LPVOID *)&GetWindowInfo_Original );
}