mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a554c8f923 | |||
| 6592191624 | |||
| 164592b16d | |||
| 81f879e7ff |
@@ -1,3 +1,6 @@
|
|||||||
|
09/17/2025 [spice2x]
|
||||||
|
Polaris Chord I/O fixes, language shim
|
||||||
|
|
||||||
09/16/2025 [spice2x]
|
09/16/2025 [spice2x]
|
||||||
Add Polaris Chord support
|
Add Polaris Chord support
|
||||||
Tweak ImGUI theme
|
Tweak ImGUI theme
|
||||||
|
|||||||
@@ -246,52 +246,66 @@ namespace games::pc {
|
|||||||
memset(o_DevStatus, 0x00, sizeof(AIO_IOB2_BI2X_AC1__DEVSTATUS));
|
memset(o_DevStatus, 0x00, sizeof(AIO_IOB2_BI2X_AC1__DEVSTATUS));
|
||||||
|
|
||||||
auto &buttons = get_buttons();
|
auto &buttons = get_buttons();
|
||||||
o_DevStatus->Input.CN8_8 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Test]);
|
o_DevStatus->Input.CN8_8 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Test]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN8_9 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Service]);
|
o_DevStatus->Input.CN8_9 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Service]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN8_10 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::CoinMech]);
|
o_DevStatus->Input.CN8_10 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::CoinMech]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN15_10 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Headphone]);
|
o_DevStatus->Input.CN15_10 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Headphone]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN15_12 = 0xFF; // Recorder off
|
o_DevStatus->Input.CN15_12 = 0xFF; // Recorder off; present in I/O test menu but unused in game
|
||||||
|
|
||||||
o_DevStatus->Input.CN12_11 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button1]);
|
o_DevStatus->Input.CN12_11 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button1]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_12 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button2]);
|
o_DevStatus->Input.CN12_12 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button2]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_13 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button3]);
|
o_DevStatus->Input.CN12_13 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button3]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_14 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button4]);
|
o_DevStatus->Input.CN12_14 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button4]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_15 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button5]);
|
o_DevStatus->Input.CN12_15 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button5]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_16 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button6]);
|
o_DevStatus->Input.CN12_16 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button6]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_17 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button7]);
|
o_DevStatus->Input.CN12_17 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button7]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_18 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button8]);
|
o_DevStatus->Input.CN12_18 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button8]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_19 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button9]);
|
o_DevStatus->Input.CN12_19 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button9]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_20 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button10]);
|
o_DevStatus->Input.CN12_20 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button10]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_21 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button11]);
|
o_DevStatus->Input.CN12_21 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button11]) ? 0 : 0xFF;
|
||||||
o_DevStatus->Input.CN12_22 = !GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button12]);
|
o_DevStatus->Input.CN12_22 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::Button12]) ? 0 : 0xFF;
|
||||||
|
|
||||||
auto &analogs = get_analogs();
|
auto &analogs = get_analogs();
|
||||||
|
|
||||||
|
// FADER-L
|
||||||
|
float val = 0.f;
|
||||||
if (analogs[Analogs::FaderL].isSet()) {
|
if (analogs[Analogs::FaderL].isSet()) {
|
||||||
float val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderL]) - 0.5f) * 2;
|
val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderL]) - 0.5f) * 2;
|
||||||
o_DevStatus->Input.CN15_7 = val < 0.2f;
|
|
||||||
o_DevStatus->Input.CN15_6 = val > -0.85f && val < 0.35f;
|
|
||||||
o_DevStatus->Input.CN15_5 = val > -0.6f && val < 0.6f;
|
|
||||||
o_DevStatus->Input.CN15_4 = val > -0.35f && val < 0.85f;
|
|
||||||
o_DevStatus->Input.CN15_3 = val > -0.2f;
|
|
||||||
} else {
|
|
||||||
o_DevStatus->Input.CN15_7 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Left]);
|
|
||||||
o_DevStatus->Input.CN15_3 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Right]);
|
|
||||||
o_DevStatus->Input.CN15_5 = !o_DevStatus->Input.CN15_7 && !o_DevStatus->Input.CN15_3;
|
|
||||||
}
|
}
|
||||||
|
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Left]) &&
|
||||||
|
GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Right])) {
|
||||||
|
val = 0.f;
|
||||||
|
} else if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Left])) {
|
||||||
|
val = -1.0f;
|
||||||
|
} else if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderL_Right])) {
|
||||||
|
val = +1.0f;
|
||||||
|
}
|
||||||
|
o_DevStatus->Input.CN15_7 = (val < 0.2f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN15_6 = (val > -0.85f && val < 0.35f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN15_5 = (val > -0.6f && val < 0.6f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN15_4 = (val > -0.35f && val < 0.85f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN15_3 = (val > -0.2f) ? 0xFF : 0;
|
||||||
|
|
||||||
|
// FADER-R
|
||||||
|
val = 0.f;
|
||||||
if (analogs[Analogs::FaderR].isSet()) {
|
if (analogs[Analogs::FaderR].isSet()) {
|
||||||
float val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderR]) - 0.5f) * 2;
|
val = (GameAPI::Analogs::getState(RI_MGR, analogs[Analogs::FaderR]) - 0.5f) * 2;
|
||||||
o_DevStatus->Input.CN11_20 = val < 0.2f;
|
|
||||||
o_DevStatus->Input.CN11_19 = val > -0.85f && val < 0.35f;
|
|
||||||
o_DevStatus->Input.CN9_10 = val > -0.6f && val < 0.6f;
|
|
||||||
o_DevStatus->Input.CN9_9 = val > -0.35f && val < 0.85f;
|
|
||||||
o_DevStatus->Input.CN9_8 = val > -0.2f;
|
|
||||||
} else {
|
|
||||||
o_DevStatus->Input.CN11_20 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Left]);
|
|
||||||
o_DevStatus->Input.CN9_8 = GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Right]);
|
|
||||||
o_DevStatus->Input.CN9_10 = !o_DevStatus->Input.CN11_20 && !o_DevStatus->Input.CN9_8;
|
|
||||||
}
|
}
|
||||||
|
if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Left]) &&
|
||||||
|
GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Right])) {
|
||||||
|
val = 0.f;
|
||||||
|
} else if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Left])) {
|
||||||
|
val = -1.0f;
|
||||||
|
} else if (GameAPI::Buttons::getState(RI_MGR, buttons[Buttons::FaderR_Right])) {
|
||||||
|
val = +1.0f;
|
||||||
|
}
|
||||||
|
o_DevStatus->Input.CN11_20 = (val < 0.2f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN11_19 = (val > -0.85f && val < 0.35f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN9_10 = (val > -0.6f && val < 0.6f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN9_9 = (val > -0.35f && val < 0.85f) ? 0xFF : 0;
|
||||||
|
o_DevStatus->Input.CN9_8 = (val > -0.2f) ? 0xFF : 0;
|
||||||
|
|
||||||
|
// coin
|
||||||
o_DevStatus->Input.Coin1Count = eamuse_coin_get_stock();
|
o_DevStatus->Input.Coin1Count = eamuse_coin_get_stock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,12 +3,15 @@
|
|||||||
#include <format>
|
#include <format>
|
||||||
|
|
||||||
#include "bi2x_hook.h"
|
#include "bi2x_hook.h"
|
||||||
|
#include "util/detour.h"
|
||||||
|
#include "util/logging.h"
|
||||||
#include "util/fileutils.h"
|
#include "util/fileutils.h"
|
||||||
#include "util/unity_player.h"
|
#include "util/unity_player.h"
|
||||||
#include "util/execexe.h"
|
#include "util/execexe.h"
|
||||||
#include "acioemu/handle.h"
|
#include "acioemu/handle.h"
|
||||||
#include "misc/wintouchemu.h"
|
#include "misc/wintouchemu.h"
|
||||||
#include "hooks/graphics/graphics.h"
|
#include "hooks/graphics/graphics.h"
|
||||||
|
#include "rawinput/rawinput.h"
|
||||||
|
|
||||||
namespace games::pc {
|
namespace games::pc {
|
||||||
std::string PC_INJECT_ARGS = "";
|
std::string PC_INJECT_ARGS = "";
|
||||||
@@ -17,6 +20,24 @@ namespace games::pc {
|
|||||||
static acioemu::ACIOHandle *acioHandle = nullptr;
|
static acioemu::ACIOHandle *acioHandle = nullptr;
|
||||||
static std::wstring portName = L"COM1";
|
static std::wstring portName = L"COM1";
|
||||||
|
|
||||||
|
static decltype(RegisterRawInputDevices) *RegisterRawInputDevices_orig = nullptr;
|
||||||
|
|
||||||
|
static BOOL WINAPI RegisterRawInputDevices_hook(PCRAWINPUTDEVICE pRawInputDevices, UINT uiNumDevices, UINT cbSize) {
|
||||||
|
|
||||||
|
// if the caller is spice itself, then pass through.
|
||||||
|
if (pRawInputDevices &&
|
||||||
|
(uiNumDevices > 0) &&
|
||||||
|
(pRawInputDevices[0].hwndTarget == RI_MGR->input_hwnd)) {
|
||||||
|
|
||||||
|
return RegisterRawInputDevices_orig(pRawInputDevices, uiNumDevices, cbSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, it must be the game; prevent the game from registering for raw input
|
||||||
|
// and hijacking WM_INPUT messages.
|
||||||
|
SetLastError(0xDEADBEEF);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
void PCGame::attach() {
|
void PCGame::attach() {
|
||||||
Game::attach();
|
Game::attach();
|
||||||
|
|
||||||
@@ -39,6 +60,10 @@ namespace games::pc {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const auto user32Dll = "user32.dll";
|
||||||
|
detour::trampoline_try(user32Dll, "RegisterRawInputDevices",
|
||||||
|
RegisterRawInputDevices_hook, &RegisterRawInputDevices_orig);
|
||||||
|
|
||||||
|
|
||||||
if (GRAPHICS_SHOW_CURSOR) {
|
if (GRAPHICS_SHOW_CURSOR) {
|
||||||
unity_utils::force_show_cursor(true);
|
unity_utils::force_show_cursor(true);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ constexpr UINT CODEPAGE_SHIFT_JIS = 932;
|
|||||||
static decltype(GetACP) *GetACP_orig = nullptr;
|
static decltype(GetACP) *GetACP_orig = nullptr;
|
||||||
static decltype(GetOEMCP) *GetOEMCP_orig = nullptr;
|
static decltype(GetOEMCP) *GetOEMCP_orig = nullptr;
|
||||||
static decltype(MultiByteToWideChar) *MultiByteToWideChar_orig = nullptr;
|
static decltype(MultiByteToWideChar) *MultiByteToWideChar_orig = nullptr;
|
||||||
|
static decltype(GetLocaleInfoEx) *GetLocaleInfoEx_orig = nullptr;
|
||||||
|
|
||||||
#ifdef SPICE64
|
#ifdef SPICE64
|
||||||
static decltype(GetSystemDefaultLCID) *GetSystemDefaultLCID_orig = nullptr;
|
static decltype(GetSystemDefaultLCID) *GetSystemDefaultLCID_orig = nullptr;
|
||||||
@@ -119,6 +120,48 @@ static int WINAPI MultiByteToWideChar_hook(
|
|||||||
cchWideChar);
|
cchWideChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int WINAPI GetLocaleInfoEx_hook (
|
||||||
|
LPCWSTR lpLocaleName,
|
||||||
|
LCTYPE LCType,
|
||||||
|
LPWSTR lpLCData,
|
||||||
|
int cchData)
|
||||||
|
{
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (lpLocaleName == LOCALE_NAME_INVARIANT) {
|
||||||
|
log_misc("hooks::lang", "GetLocaleInfoEx_hook hit (LOCALE_NAME_INVARIANT), {}, {}", LCType, cchData);
|
||||||
|
} else if (lpLocaleName == LOCALE_NAME_SYSTEM_DEFAULT) {
|
||||||
|
log_misc("hooks::lang", "GetLocaleInfoEx_hook hit (LOCALE_NAME_SYSTEM_DEFAULT), {}, {}", LCType, cchData);
|
||||||
|
} else if (lpLocaleName == LOCALE_NAME_USER_DEFAULT) {
|
||||||
|
log_misc("hooks::lang", "GetLocaleInfoEx_hook hit (LOCALE_NAME_USER_DEFAULT), {}, {}", LCType, cchData);
|
||||||
|
} else {
|
||||||
|
log_misc("hooks::lang", "GetLocaleInfoEx_hook hit ({}), {}, {}", ws2s(lpLocaleName), LCType, cchData);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (lpLocaleName == LOCALE_NAME_USER_DEFAULT &&
|
||||||
|
LCType == LOCALE_SISO639LANGNAME &&
|
||||||
|
lpLCData != NULL &&
|
||||||
|
cchData >= 3) {
|
||||||
|
log_misc("hooks::lang",
|
||||||
|
"GetLocaleInfoEx_hook hit (LOCALE_NAME_USER_DEFAULT / LOCALE_SISO639LANGNAME), return `ja`");
|
||||||
|
wcscpy(lpLCData, L"ja");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpLocaleName == LOCALE_NAME_USER_DEFAULT &&
|
||||||
|
LCType == LOCALE_SISO3166CTRYNAME &&
|
||||||
|
lpLCData != NULL &&
|
||||||
|
cchData >= 3) {
|
||||||
|
log_misc("hooks::lang",
|
||||||
|
"GetLocaleInfoEx_hook hit (LOCALE_NAME_USER_DEFAULT / LOCALE_SISO3166CTRYNAME), return `JP`");
|
||||||
|
wcscpy(lpLCData, L"JP");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetLocaleInfoEx_orig(lpLocaleName, LCType, lpLCData, cchData);
|
||||||
|
}
|
||||||
|
|
||||||
void hooks::lang::early_init() {
|
void hooks::lang::early_init() {
|
||||||
log_info("hooks::lang", "early initialization");
|
log_info("hooks::lang", "early initialization");
|
||||||
|
|
||||||
@@ -138,6 +181,14 @@ void hooks::lang::early_init() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (avs::game::is_model("XIF")) {
|
||||||
|
log_info("hooks::lang", "hooking GetLocaleInfoEx");
|
||||||
|
detour::trampoline_try(
|
||||||
|
"kernel32.dll",
|
||||||
|
"GetLocaleInfoEx",
|
||||||
|
GetLocaleInfoEx_hook,
|
||||||
|
&GetLocaleInfoEx_orig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void hooks::lang::init() {
|
void hooks::lang::init() {
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ namespace rawinput {
|
|||||||
|
|
||||||
HotplugManager *hotplug;
|
HotplugManager *hotplug;
|
||||||
std::vector<Device> devices;
|
std::vector<Device> devices;
|
||||||
HWND input_hwnd = nullptr;
|
|
||||||
WNDCLASSEX input_hwnd_class {};
|
WNDCLASSEX input_hwnd_class {};
|
||||||
std::thread *input_thread = nullptr;
|
std::thread *input_thread = nullptr;
|
||||||
std::thread *flush_thread = nullptr;
|
std::thread *flush_thread = nullptr;
|
||||||
@@ -91,6 +90,8 @@ namespace rawinput {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
HWND input_hwnd = nullptr;
|
||||||
|
|
||||||
RawInputManager();
|
RawInputManager();
|
||||||
~RawInputManager();
|
~RawInputManager();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user