mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
popn: hook DisplayConfigGetDeviceInfo to allow for any GPU port to be used for monitor, get past I/O check (#622)
## Link to GitHub Issue or related Pull Request, if one exists #618 ## Description of change The game expects the main display to be *not* HDMI, and at port 2. Hooking DisplayConfigGetDeviceInfo allows us to boot the game on any monitor. Add basic I/O hook. It gets stuck in `USB I/O Checking...` for a couple minutes but it'll eventually skip and boot to title screen. ## Testing ugh.
This commit is contained in:
@@ -9,14 +9,85 @@
|
||||
#include "util/utils.h"
|
||||
#include "cfg/button.h"
|
||||
#include "cfg/api.h"
|
||||
#include "hooks/setupapihook.h"
|
||||
#include "hooks/sleephook.h"
|
||||
#include "launcher/launcher.h"
|
||||
#include "launcher/logger.h"
|
||||
#include "misc/eamuse.h"
|
||||
#include "util/sysutils.h"
|
||||
#include "io.h"
|
||||
|
||||
namespace games::popn {
|
||||
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
static decltype(DisplayConfigGetDeviceInfo) *DisplayConfigGetDeviceInfo_orig = nullptr;
|
||||
|
||||
static
|
||||
LONG
|
||||
WINAPI
|
||||
DisplayConfigGetDeviceInfo_hook(DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket)
|
||||
{
|
||||
if (requestPacket == nullptr) {
|
||||
return DisplayConfigGetDeviceInfo_orig(requestPacket);
|
||||
}
|
||||
const auto ret = DisplayConfigGetDeviceInfo_orig(requestPacket);
|
||||
log_misc(
|
||||
"popn",
|
||||
"DisplayConfigGetDeviceInfo returned {}, type={}, size={}, id={}, luid={}/{}",
|
||||
ret,
|
||||
static_cast<int>(requestPacket->type),
|
||||
requestPacket->size,
|
||||
requestPacket->id,
|
||||
requestPacket->adapterId.HighPart,
|
||||
requestPacket->adapterId.LowPart);
|
||||
if (ret == ERROR_SUCCESS) {
|
||||
if (requestPacket->type == DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME) {
|
||||
const auto sourceName = reinterpret_cast<DISPLAYCONFIG_SOURCE_DEVICE_NAME*>(requestPacket);
|
||||
log_misc(
|
||||
"popn",
|
||||
"... name={}",
|
||||
ws2s(sourceName->viewGdiDeviceName));
|
||||
} else if (requestPacket->type == DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME) {
|
||||
const auto targetName = reinterpret_cast<DISPLAYCONFIG_TARGET_DEVICE_NAME*>(requestPacket);
|
||||
log_misc(
|
||||
"popn",
|
||||
"... flags={}, outputTechnology: {}, connectorInstance={}, friendlyname={} path={}",
|
||||
targetName->flags.value,
|
||||
static_cast<int>(targetName->outputTechnology),
|
||||
targetName->connectorInstance,
|
||||
ws2s(targetName->monitorFriendlyDeviceName),
|
||||
ws2s(targetName->monitorDevicePath));
|
||||
|
||||
// need to fix up some values for the primary monitor...
|
||||
const auto monitors = sysutils::enumerate_monitors();
|
||||
for (const auto& monitor : monitors) {
|
||||
if (monitor.id == targetName->header.id &&
|
||||
monitor.adapter_id_HighPart == targetName->header.adapterId.HighPart &&
|
||||
monitor.adapter_id_LowPart == targetName->header.adapterId.LowPart) {
|
||||
|
||||
if (monitor.is_primary) {
|
||||
targetName->outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL;
|
||||
targetName->connectorInstance = 2;
|
||||
log_info(
|
||||
"popn",
|
||||
"... overriding primary monitor ({}) to pretend to be DP port #2",
|
||||
monitor.display_name);
|
||||
} else {
|
||||
// TODO: is this what the game expects for subscreen?
|
||||
// TODO: what if there are 3+ monitors?
|
||||
targetName->outputTechnology = DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static int __cdecl usbCheckAlive() {
|
||||
return 1;
|
||||
}
|
||||
@@ -320,5 +391,29 @@ namespace games::popn {
|
||||
detour::inline_hook((void *) usbWdtStartDone,
|
||||
libutils::try_proc(ezusb, "?usbWdtStartDone@@YAHXZ"));
|
||||
}
|
||||
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
if (is_pikapika_model()) {
|
||||
// monitor hook
|
||||
DisplayConfigGetDeviceInfo_orig = detour::iat_try("DisplayConfigGetDeviceInfo", DisplayConfigGetDeviceInfo_hook, avs::game::DLL_INSTANCE);
|
||||
|
||||
// TODO: io emulation
|
||||
SETUPAPI_SETTINGS settings{};
|
||||
settings.class_guid[0] = 0x86E0D1E0;
|
||||
settings.class_guid[1] = 0x11D08089;
|
||||
settings.class_guid[2] = 0x0008E49C;
|
||||
settings.class_guid[3] = 0x731F303E;
|
||||
const char property[] = "1CCF(8050)_000";
|
||||
const char property_hardwareid[] = "USB\\VID_1CCF&PID_8050&MI_00\\000";
|
||||
memcpy(settings.property_devicedesc, property, sizeof(property));
|
||||
memcpy(settings.property_hardwareid, property_hardwareid, sizeof(property_hardwareid));
|
||||
setupapihook_init(avs::game::DLL_INSTANCE);
|
||||
setupapihook_add(settings);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user