mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 14:20:42 -07:00
Build a WinXP compatible version of Spice (#611)
This was a lot more background work than expected, but that is the nature of unnecessary hobbies I guess. Most things in here are obvious, so here's the non-obvious thoughts and notes: 1. All the XP stuff is optional, if the toolchain isn't available it won't even try 2. The docker build is the "known good" build and now has all the required tools for XP and checking binaries a. If you're OK with it, can add the XP_MUST_BUILD flag to build_docker.sh 4. New `SPICE_XP` flag to comment out blocks 5. We could technically build using the Docker image I've made for my XP compatible LLVM toolchain, but combining the binaries into a single zip at the end of it is somewhat tedious, so I've chosen to grab the binaries from my release 6. I also wrote a DLL checker to make sure the final binaries are _actually_ XP compatible, which found some issues on x86_64 (I don't know a single game that runs on 64 bit XP, but it wasn't too much effort so whatever). This also won't run if missing, just to save the trouble. 7. The build script is still pretty shit, I've made some minor improvements a. `/usr/bin/env bash` instead of `/bin/bash` as it's more correct b. Adding `-it` to the docker build, so Ctrl+C actually halts it c. Main issue is that failures don't halt, because of the custom error catching function. This has caused a lot of frustration, maybe we can change that ## Testing It runs on 32 and 64 bit installs of XP. My jubeat cab is on Win10 these days and I haven't got around to testing an actual game, but I've distributed test builds of this to people who *have* confirmed it works as expected.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# set to EN-US for consistency
|
||||
LANG=en_us_8859_1
|
||||
@@ -43,10 +43,16 @@ GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2> /dev/null || echo "none")
|
||||
GIT_HEAD=$(git rev-parse HEAD || echo "none")
|
||||
TOOLCHAIN_32="${TOOLCHAIN_32:-"/usr/share/mingw/toolchain-i686-w64-mingw32.cmake"}"
|
||||
TOOLCHAIN_64="${TOOLCHAIN_64:-"/usr/share/mingw/toolchain-x86_64-w64-mingw32.cmake"}"
|
||||
TOOLCHAIN_WINXP_32="${TOOLCHAIN_WINXP_32:-"/opt/llvm-mingw-xp/toolchain-files/cmake/i686-mingw32-clang.cmake"}"
|
||||
TOOLCHAIN_WINXP_64="${TOOLCHAIN_WINXP_64:-"/opt/llvm-mingw-xp/toolchain-files/cmake/x86_64-mingw32-clang.cmake"}"
|
||||
BUILDDIR_32_RELEASE="./cmake-build-release-32"
|
||||
BUILDDIR_32_DEBUG="./cmake-build-debug-32"
|
||||
BUILDDIR_64_RELEASE="./cmake-build-release-64"
|
||||
BUILDDIR_64_DEBUG="./cmake-build-debug-64"
|
||||
BUILDDIR_WINXP_32_RELEASE="./cmake-build-release-winxp-32"
|
||||
BUILDDIR_WINXP_32_DEBUG="./cmake-build-debug-winxp-32"
|
||||
BUILDDIR_WINXP_64_RELEASE="./cmake-build-release-winxp-64"
|
||||
BUILDDIR_WINXP_64_DEBUG="./cmake-build-debug-winxp-64"
|
||||
DEBUG=0
|
||||
OUTDIR="./bin/spice2x"
|
||||
OUTDIR_EXTRAS="./bin/spice2x/extras"
|
||||
@@ -69,14 +75,29 @@ TARGETS_64="spicetools_stubs_kbt64 spicetools_stubs_kld64 spicetools_stubs_nvEnc
|
||||
BUILD_TYPE="Release"
|
||||
BUILDDIR_32=${BUILDDIR_32_RELEASE}
|
||||
BUILDDIR_64=${BUILDDIR_64_RELEASE}
|
||||
BUILDDIR_WINXP_32=${BUILDDIR_WINXP_32_RELEASE}
|
||||
BUILDDIR_WINXP_64=${BUILDDIR_WINXP_64_RELEASE}
|
||||
if ((DEBUG > 0))
|
||||
then
|
||||
BUILD_TYPE="Debug"
|
||||
BUILDDIR_32=${BUILDDIR_32_DEBUG}
|
||||
BUILDDIR_64=${BUILDDIR_64_DEBUG}
|
||||
BUILDDIR_WINXP_32=${BUILDDIR_WINXP_32_DEBUG}
|
||||
BUILDDIR_WINXP_64=${BUILDDIR_WINXP_64_DEBUG}
|
||||
DIST_NAME=$(echo "${DIST_NAME}" | sed 's/\.[^.]*$/-dbg&/')
|
||||
fi
|
||||
|
||||
# is the XP-compatible toolchain installed?
|
||||
XP_MUST_BUILD=0
|
||||
BUILD_XP=0
|
||||
if [ -f "$TOOLCHAIN_WINXP_32" ] && [ -f "$TOOLCHAIN_WINXP_64" ]; then
|
||||
BUILD_XP=1;
|
||||
elif ((XP_MUST_BUILD > 0))
|
||||
then
|
||||
echo "WinXP toolchain not available, aborting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# determine number of cores
|
||||
CORES=$(nproc)
|
||||
|
||||
@@ -90,6 +111,13 @@ echo "Git Branch: $GIT_BRANCH"
|
||||
echo "Git Head: $GIT_HEAD"
|
||||
echo "Toolchain for 32bit targets: $TOOLCHAIN_32"
|
||||
echo "Toolchain for 64bit targets: $TOOLCHAIN_64"
|
||||
if ((BUILD_XP > 0))
|
||||
then
|
||||
echo "Toolchain for WinXP 32bit targets: $TOOLCHAIN_WINXP_32"
|
||||
echo "Toolchain for WinXP 64bit targets: $TOOLCHAIN_WINXP_64"
|
||||
else
|
||||
echo "WinXP toolchain not available, skipping WinXP builds"
|
||||
fi
|
||||
echo "Distribution Name: $DIST_NAME"
|
||||
echo "Build Type: $BUILD_TYPE"
|
||||
echo "Cores: $CORES"
|
||||
@@ -130,11 +158,58 @@ time (
|
||||
cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_64}
|
||||
popd > /dev/null
|
||||
|
||||
if ((BUILD_XP > 0))
|
||||
then
|
||||
# 32 bit Windows XP
|
||||
echo "Building 32bit targets (WinXP toolchain)..."
|
||||
echo "========================="
|
||||
if ((CLEAN_BUILD > 0))
|
||||
then
|
||||
rm -rf ${BUILDDIR_WINXP_32}
|
||||
fi
|
||||
mkdir -p ${BUILDDIR_WINXP_32}
|
||||
pushd ${BUILDDIR_WINXP_32} > /dev/null
|
||||
CXXFLAGS="$CXXFLAGS -DSPICE_XP=1" cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_WINXP_32} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_32}
|
||||
popd > /dev/null
|
||||
|
||||
# 64 bit Windows XP
|
||||
echo ""
|
||||
echo "Building 64bit targets (WinXP toolchain)..."
|
||||
echo "========================="
|
||||
if ((CLEAN_BUILD > 0))
|
||||
then
|
||||
rm -rf ${BUILDDIR_WINXP_64}
|
||||
fi
|
||||
mkdir -p ${BUILDDIR_WINXP_64}
|
||||
pushd ${BUILDDIR_WINXP_64} > /dev/null
|
||||
CXXFLAGS="$CXXFLAGS -DSPICE_XP=1" cmake -G "Ninja" -DCMAKE_TOOLCHAIN_FILE=${TOOLCHAIN_WINXP_64} -DCMAKE_BUILD_TYPE=${BUILD_TYPE} "$OLDPWD" && ninja ${TARGETS_64}
|
||||
popd > /dev/null
|
||||
else
|
||||
echo "Skipping WinXP builds, toolchain not specified"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Compilation process done :)"
|
||||
echo "==========================="
|
||||
)
|
||||
|
||||
if ((BUILD_XP > 0))
|
||||
then
|
||||
echo ""
|
||||
echo "Checking XP compatibility..."
|
||||
echo "============================="
|
||||
if ! command -v windows_dll_compat_checker &> /dev/null; then
|
||||
echo "WARNING: windows_dll_compat_checker not found, skipping XP compatibility check"
|
||||
else
|
||||
windows_dll_compat_checker -s PREMADE/winxp_x86_64.ini \
|
||||
${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe
|
||||
windows_dll_compat_checker -s PREMADE/winxp_x86_64_32bit_dlls.ini \
|
||||
${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe \
|
||||
${BUILDDIR_WINXP_32}/spicetools/32/spice.exe \
|
||||
${BUILDDIR_WINXP_32}/spicetools/32/spice_laa.exe
|
||||
fi
|
||||
fi
|
||||
|
||||
# generate PDBs
|
||||
if false # ((DEBUG > 0))
|
||||
then
|
||||
@@ -226,6 +301,12 @@ else
|
||||
cp ${BUILDDIR_64}/spicetools/64/nvcuda.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||
cp ${BUILDDIR_64}/spicetools/64/nvcuvid.dll ${OUTDIR}/stubs/64 2>/dev/null
|
||||
cp ${BUILDDIR_32}/spicetools/32/cpusbxpkm.dll ${OUTDIR}/stubs/32 2>/dev/null
|
||||
if ((BUILD_XP > 0))
|
||||
then
|
||||
cp ${BUILDDIR_WINXP_32}/spicetools/spicecfg.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
|
||||
cp ${BUILDDIR_WINXP_32}/spicetools/32/spice.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
|
||||
cp ${BUILDDIR_WINXP_64}/spicetools/64/spice64.exe ${OUTDIR_EXTRAS}/winxp 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
|
||||
# pack source files to output directory
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
#!/bin/bash
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
docker build --pull "$PWD/external/docker" -t spicetools/deps --platform linux/x86_64
|
||||
docker build --build-context gitroot="$PWD/../../.git" . -t spicetools/spice:latest
|
||||
docker run --rm -v "$PWD/dist:/src/src/spice2x/dist" -v "$PWD/bin:/src/src/spice2x/bin" -v "$PWD/.ccache:/src/src/spice2x/.ccache" spicetools/spice "$@"
|
||||
|
||||
# Interactive TTY if available, so docker build can be Ctrl+C'd
|
||||
DOCKER_FLAGS=""
|
||||
[ -t 0 ] && DOCKER_FLAGS="-it"
|
||||
|
||||
docker run $DOCKER_FLAGS --rm -v "$PWD/dist:/src/src/spice2x/dist" -v "$PWD/bin:/src/src/spice2x/bin" -v "$PWD/.ccache:/src/src/spice2x/.ccache" spicetools/spice "$@"
|
||||
|
||||
+8
@@ -15,3 +15,11 @@ RUN pacman --noconfirm -Syu git \
|
||||
ccache
|
||||
RUN useradd user -m && echo "ALL ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
|
||||
RUN su user -c "cd /tmp/ && git clone https://aur.archlinux.org/yay-bin.git --depth=1 && cd yay-bin && makepkg --noconfirm -si && yay --noconfirm -S mingw-w64-cmake"
|
||||
|
||||
RUN mkdir -p /opt/llvm-mingw-xp \
|
||||
&& curl -fsSL "https://github.com/mon/llvm-mingw-xp/releases/download/llvm-mingw-xp-22.1.0/llvm-mingw-llvm-mingw-xp-22.1.0-msvcrt-ubuntu-22.04-x86_64.tar.xz" \
|
||||
| tar -xJ --strip-components=1 -C /opt/llvm-mingw-xp
|
||||
ENV PATH="$PATH:/opt/llvm-mingw-xp/bin"
|
||||
|
||||
RUN curl -fsSL "https://github.com/mon/windows-dll-compat-checker/releases/download/v1.3/windows_dll_compat_checker-linux-x86_64.tar.xz" \
|
||||
| tar -xJ -C /usr/local/bin
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "camera.h"
|
||||
|
||||
#if SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
#include <d3d9.h>
|
||||
#include "mf_wrappers.h"
|
||||
@@ -84,7 +84,7 @@ namespace games::iidx {
|
||||
|
||||
bool find_camera_hooks() {
|
||||
std::string dll_name = avs::game::DLL_NAME;
|
||||
dll_path = MODULE_PATH / dll_name;
|
||||
dll_path = MODULE_PATH / dll_name;
|
||||
|
||||
iidx_module = libutils::try_module(dll_path);
|
||||
if (!iidx_module) {
|
||||
@@ -149,7 +149,7 @@ namespace games::iidx {
|
||||
"E800000000488BC8488BD34883C420",
|
||||
"X????XXXXXXXXXX",
|
||||
0, 0));
|
||||
|
||||
|
||||
if (addr_textures_ptr == nullptr) {
|
||||
log_warning("iidx:camhook", "failed to find hook: addr_textures (part 1)");
|
||||
return FALSE;
|
||||
@@ -232,7 +232,7 @@ namespace games::iidx {
|
||||
}
|
||||
|
||||
static void **__fastcall camera_hook_a(PBYTE a1) {
|
||||
std::call_once(hook_a_init, [&]{
|
||||
std::call_once(hook_a_init, [&]{
|
||||
device = *reinterpret_cast<LPDIRECT3DDEVICE9EX*>(a1 + addr_device_offset);
|
||||
auto const preview = *reinterpret_cast<LPDIRECT3DTEXTURE9**>((uint8_t*)iidx_module + addr_textures);
|
||||
auto const manager = reinterpret_cast<Camera::CCameraManager2*>((uint8_t*)iidx_module + addr_camera_manager);
|
||||
@@ -298,11 +298,11 @@ namespace games::iidx {
|
||||
// Ask for source type = video capture devices.
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = pAttributes->SetGUID(
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE,
|
||||
MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Enumerate devices.
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = WrappedMFEnumDeviceSources(pAttributes, &ppDevices, &numDevices);
|
||||
@@ -478,7 +478,7 @@ namespace games::iidx {
|
||||
init_mf_library();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#if SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
#include <vector>
|
||||
#include "games/iidx/local_camera.h"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "games/iidx/local_camera.h"
|
||||
|
||||
#if SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
#include "util/logging.h"
|
||||
#include "util/utils.h"
|
||||
@@ -128,7 +128,7 @@ namespace games::iidx {
|
||||
// TODO: Color space conversion
|
||||
// if (SUCCEEDED(hr)) {
|
||||
// hr = pAttributes->SetUINT32(MF_SOURCE_READER_ENABLE_ADVANCED_VIDEO_PROCESSING, TRUE);
|
||||
// }
|
||||
// }
|
||||
// if (SUCCEEDED(hr)) {
|
||||
// hr = pAttributes->SetUINT32(MF_READWRITE_DISABLE_CONVERTERS, FALSE);
|
||||
// }
|
||||
@@ -189,11 +189,11 @@ namespace games::iidx {
|
||||
&pType
|
||||
);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
if (hr != MF_E_NO_MORE_TYPES) {
|
||||
log_warning("iidx:camhook", "[{}] Cannot get media type {} {:#x}", m_name, i, (ULONG)hr);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
hr = TryMediaType(pType, &bestWidth, &bestFrameRate);
|
||||
@@ -246,7 +246,7 @@ namespace games::iidx {
|
||||
pSelectedMediaType = m_pAutoMediaType;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = ChangeMediaType(pSelectedMediaType);
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ namespace games::iidx {
|
||||
m_cameraHeight = info.height;
|
||||
UpdateDrawRect();
|
||||
}
|
||||
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
@@ -395,7 +395,7 @@ namespace games::iidx {
|
||||
|
||||
m_device->ColorFill(m_pDestSurf, &targetRect, D3DCOLOR_XRGB(0, 0, 0));
|
||||
}
|
||||
|
||||
|
||||
void IIDXLocalCamera::CreateThread() {
|
||||
// Create thread
|
||||
m_drawThread = new std::thread([this]() {
|
||||
@@ -411,7 +411,7 @@ namespace games::iidx {
|
||||
if (accumulator > 1.0) {
|
||||
accumulator -= 1.0;
|
||||
floorFrameTimeMicroSec += 1;
|
||||
}
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(floorFrameTimeMicroSec));
|
||||
}
|
||||
});
|
||||
@@ -430,12 +430,12 @@ namespace games::iidx {
|
||||
|
||||
log_misc("iidx:camhook", "[{}] Init camera control", m_name);
|
||||
|
||||
hr = m_pSource->QueryInterface(IID_IAMCameraControl, (void**)&m_pCameraControl);
|
||||
if (FAILED(hr)) {
|
||||
// The device does not support IAMCameraControl
|
||||
hr = m_pSource->QueryInterface(IID_IAMCameraControl, (void**)&m_pCameraControl);
|
||||
if (FAILED(hr)) {
|
||||
// The device does not support IAMCameraControl
|
||||
log_warning("iidx:camhook", "[{}] Camera control not supported", m_name);
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < CAMERA_CONTROL_PROP_SIZE; i++) {
|
||||
long minValue = 0;
|
||||
@@ -472,9 +472,9 @@ namespace games::iidx {
|
||||
CameraControlProp prop = m_controlProps.at(i);
|
||||
|
||||
log_misc(
|
||||
"iidx:camhook", "[{}] >> {} range=({}, {}) default={} delta={} dFlags={} value={} vFlags={}",
|
||||
"iidx:camhook", "[{}] >> {} range=({}, {}) default={} delta={} dFlags={} value={} vFlags={}",
|
||||
m_name,
|
||||
CAMERA_CONTROL_LABELS[i],
|
||||
CAMERA_CONTROL_LABELS[i],
|
||||
prop.minValue, prop.maxValue,
|
||||
prop.defaultValue,
|
||||
prop.delta,
|
||||
@@ -570,9 +570,9 @@ namespace games::iidx {
|
||||
|
||||
// Get frame rate
|
||||
hr = MFGetAttributeRatio(
|
||||
pType,
|
||||
MF_MT_FRAME_RATE,
|
||||
(UINT32*)&frameRate.Numerator,
|
||||
pType,
|
||||
MF_MT_FRAME_RATE,
|
||||
(UINT32*)&frameRate.Numerator,
|
||||
(UINT32*)&frameRate.Denominator
|
||||
);
|
||||
if (FAILED(hr)) { goto done; }
|
||||
@@ -580,7 +580,7 @@ namespace games::iidx {
|
||||
info.frameRate = frameRate.Numerator / frameRate.Denominator;
|
||||
|
||||
info.description = fmt::format(
|
||||
"{}x{} @{}FPS {}",
|
||||
"{}x{} @{}FPS {}",
|
||||
info.width,
|
||||
info.height,
|
||||
(int)info.frameRate,
|
||||
@@ -606,7 +606,7 @@ namespace games::iidx {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Return values:
|
||||
* S_OK: this is a "better" media type than the existing one
|
||||
* S_FALSE: valid media type, but not "better"
|
||||
@@ -620,17 +620,17 @@ namespace games::iidx {
|
||||
|
||||
hr = pType->GetGUID(MF_MT_SUBTYPE, &subtype);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
log_warning("iidx:camhook", "[{}] Failed to get subtype: {:#x}", m_name, (ULONG)hr);
|
||||
return hr;
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = MFGetAttributeSize(pType, MF_MT_FRAME_SIZE, &width, &height);
|
||||
if (FAILED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
log_warning("iidx:camhook", "[{}] Failed to get frame size: {:#x}", m_name, (ULONG)hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
// Only support format with converters
|
||||
// TODO: verify conversion support with DXVA
|
||||
if (subtype != MFVideoFormat_YUY2 && subtype != MFVideoFormat_NV12) {
|
||||
@@ -639,12 +639,12 @@ namespace games::iidx {
|
||||
|
||||
// Frame rate
|
||||
hr = MFGetAttributeRatio(
|
||||
pType,
|
||||
MF_MT_FRAME_RATE,
|
||||
(UINT32*)&frameRate.Numerator,
|
||||
pType,
|
||||
MF_MT_FRAME_RATE,
|
||||
(UINT32*)&frameRate.Numerator,
|
||||
(UINT32*)&frameRate.Denominator
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
if (FAILED(hr)) {
|
||||
log_warning("iidx:camhook", "[{}] Failed to get frame rate: {:#x}", m_name, (ULONG)hr);
|
||||
return hr;
|
||||
}
|
||||
@@ -667,7 +667,7 @@ namespace games::iidx {
|
||||
// Check if this format has better resolution / frame rate
|
||||
if ((width > *pBestWidth) || (width >= (UINT32)TARGET_SURFACE_WIDTH && frameRateValue >= *pBestFrameRate)) {
|
||||
// log_misc(
|
||||
// "iidx:camhook", "Better media type {} ({}x{}) @({} FPS)",
|
||||
// "iidx:camhook", "Better media type {} ({}x{}) @({} FPS)",
|
||||
// GetVideoFormatName(subtype),
|
||||
// width,
|
||||
// height,
|
||||
@@ -730,7 +730,7 @@ namespace games::iidx {
|
||||
|
||||
HRESULT IIDXLocalCamera::FlushDrawCommands() {
|
||||
IDirect3DQuery9* pEventQuery = nullptr;
|
||||
// It is necessary to flush the command queue
|
||||
// It is necessary to flush the command queue
|
||||
// or the data is not ready for the receiver to read.
|
||||
// Adapted from : https://msdn.microsoft.com/en-us/library/windows/desktop/bb172234%28v=vs.85%29.aspx
|
||||
// Also see : http://www.ogre3d.org/forums/viewtopic.php?f=5&t=50486
|
||||
@@ -784,8 +784,8 @@ namespace games::iidx {
|
||||
for (int y = 0; y < TARGET_SURFACE_HEIGHT; y++) {
|
||||
for (int x = 0; x < TARGET_SURFACE_WIDTH; x++) {
|
||||
memcpy(
|
||||
pDest + x * pixelSize,
|
||||
pSrc + (flip_h ? (TARGET_SURFACE_WIDTH - x - 1) : x) * pixelSize,
|
||||
pDest + x * pixelSize,
|
||||
pSrc + (flip_h ? (TARGET_SURFACE_WIDTH - x - 1) : x) * pixelSize,
|
||||
pixelSize
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#if SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
#include <d3d9.h>
|
||||
#include <dxva2api.h>
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// GetDisplayConfigBufferSizes etc is Vista+
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include <initguid.h>
|
||||
|
||||
#include "graphics.h"
|
||||
@@ -232,9 +235,9 @@ static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
|
||||
// This allows touches received on subscreen window to be translated correctly.
|
||||
update_spicetouch_window_dimensions(hWnd);
|
||||
// log_misc(
|
||||
// "graphics", "detected window change ({}x{} @ {}, {}), updating touch coord-space to match",
|
||||
// "graphics", "detected window change ({}x{} @ {}, {}), updating touch coord-space to match",
|
||||
// SPICETOUCH_TOUCH_WIDTH, SPICETOUCH_TOUCH_HEIGHT, SPICETOUCH_TOUCH_X, SPICETOUCH_TOUCH_Y);
|
||||
|
||||
|
||||
// Update SPICETOUCH window if present
|
||||
if (SPICETOUCH_TOUCH_HWND) {
|
||||
SetWindowPos(
|
||||
@@ -371,7 +374,7 @@ static HWND WINAPI CreateWindowExA_hook(DWORD dwExStyle, LPCSTR lpClassName, LPC
|
||||
if (is_tdj_sub_window) {
|
||||
// TDJ windowed mode: remember the subscreen window handle for later
|
||||
TDJ_SUBSCREEN_WINDOW = result;
|
||||
|
||||
|
||||
// hook for preventing the closing of subscreen window
|
||||
if (GRAPHICS_IIDX_WSUB) {
|
||||
graphics_hook_subscreen_window(TDJ_SUBSCREEN_WINDOW);
|
||||
@@ -530,7 +533,7 @@ static BOOL WINAPI MoveWindow_hook(HWND hWnd, int X, int Y, int nWidth, int nHei
|
||||
if (GRAPHICS_IIDX_WSUB) {
|
||||
// (Experimental) Show subscreen in windowed mode
|
||||
graphics_load_windowed_subscreen_parameters();
|
||||
|
||||
|
||||
RECT rect {};
|
||||
DWORD dwStyle;
|
||||
|
||||
@@ -1085,7 +1088,7 @@ static std::string get_dmdo_string(DWORD dmdo) {
|
||||
}
|
||||
|
||||
void change_primary_monitor(const std::string &monitor_name) {
|
||||
log_misc("graphics", "try changing primary monitor to {}...", monitor_name);
|
||||
log_misc("graphics", "try changing primary monitor to {}...", monitor_name);
|
||||
|
||||
// for WinXP, since these are Vista+ or 7+ APIs
|
||||
const auto user32 = LoadLibraryA("user32.dll");
|
||||
@@ -1116,7 +1119,7 @@ void change_primary_monitor(const std::string &monitor_name) {
|
||||
std::vector<DISPLAYCONFIG_PATH_INFO> paths;
|
||||
std::vector<DISPLAYCONFIG_MODE_INFO> modes;
|
||||
bool succeeded = false;
|
||||
|
||||
|
||||
// in a retry loop, try to query for display config
|
||||
// retry loop is needed because it can fail with ERROR_INSUFFICIENT_BUFFER
|
||||
for (int attempt = 0; attempt < 5; ++attempt) {
|
||||
@@ -1323,4 +1326,4 @@ void update_monitor_on_boot(std::optional<graphics_orientation> target_orientati
|
||||
|
||||
// sleep for a little bit after changing monitor settings to delay game launch
|
||||
Sleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -351,7 +351,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
GRAPHICS_FORCE_SINGLE_ADAPTER = true;
|
||||
GRAPHICS_PREVENT_SECONDARY_WINDOW = true;
|
||||
}
|
||||
if (options[launcher::Options::DXDisplayAdapter].is_active() &&
|
||||
if (options[launcher::Options::DXDisplayAdapter].is_active() &&
|
||||
options[launcher::Options::DXDisplayAdapter].value_uint32() != D3DADAPTER_DEFAULT) {
|
||||
D3D9_ADAPTER = options[launcher::Options::DXDisplayAdapter].value_uint32();
|
||||
|
||||
@@ -1227,7 +1227,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
acio::MDXF_BUFFER_FILL_MODE = acio::MDXFBufferFillMode::THREAD_MODE;
|
||||
} else if (options[launcher::Options::DDRP4IOBufferMode].value_text() == "backfill") {
|
||||
acio::MDXF_BUFFER_FILL_MODE = acio::MDXFBufferFillMode::BACKFILL_MODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options[launcher::Options::MidiAlgoVer].is_active()) {
|
||||
@@ -1294,7 +1294,19 @@ int main_implementation(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// log
|
||||
#ifndef SPICE_LINUX
|
||||
#if SPICE_LINUX
|
||||
#ifdef SPICE64
|
||||
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x) for Linux");
|
||||
#else
|
||||
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x) for Linux");
|
||||
#endif
|
||||
#elif SPICE_XP
|
||||
#ifdef SPICE64
|
||||
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x) for WinXP");
|
||||
#else
|
||||
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x) for WinXP");
|
||||
#endif
|
||||
#else
|
||||
#ifdef SPICE64
|
||||
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x)");
|
||||
#elif SPICE32_LARGE_ADDRESS_AWARE
|
||||
@@ -1302,12 +1314,6 @@ int main_implementation(int argc, char *argv[]) {
|
||||
#else
|
||||
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x)");
|
||||
#endif
|
||||
#else
|
||||
#ifdef SPICE64
|
||||
log_info("launcher", "SpiceTools Bootstrap (x64) (spice2x) for Linux");
|
||||
#else
|
||||
log_info("launcher", "SpiceTools Bootstrap (x32) (spice2x) for Linux");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
log_info("launcher", "{}", VERSION_STRING);
|
||||
@@ -1364,7 +1370,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
log_warning(
|
||||
"launcher",
|
||||
"multiple values for -{}, command line args take precedence: {}",
|
||||
option.get_definition().name,
|
||||
option.get_definition().name,
|
||||
value);
|
||||
} else {
|
||||
log_warning(
|
||||
@@ -1379,7 +1385,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
if (launcher::USE_CMD_OVERRIDE) {
|
||||
log_info(
|
||||
"launcher",
|
||||
"user specified -cmdoverride, therefore command line args took precedence over spicecfg");
|
||||
"user specified -cmdoverride, therefore command line args took precedence over spicecfg");
|
||||
} else {
|
||||
log_warning(
|
||||
"launcher",
|
||||
@@ -2226,7 +2232,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
game->attach();
|
||||
}
|
||||
|
||||
#ifdef SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
if (!cfg::CONFIGURATOR_STANDALONE) {
|
||||
if (games::iidx::TDJ_CAMERA) {
|
||||
games::iidx::init_camera_hooks();
|
||||
@@ -2507,7 +2513,7 @@ int main_implementation(int argc, char *argv[]) {
|
||||
// disable poke
|
||||
games::iidx::poke::disable();
|
||||
|
||||
#ifdef SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
games::iidx::camera_release();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ namespace overlay {
|
||||
}
|
||||
return ImVec2(apply_scaling(x), apply_scaling(y));
|
||||
}
|
||||
|
||||
|
||||
ImVec2 apply_scaling_to_vector(const ImVec2& input) {
|
||||
return apply_scaling_to_vector(input.x, input.y);
|
||||
}
|
||||
@@ -350,7 +350,7 @@ void overlay::SpiceOverlay::init() {
|
||||
this->window_add(window_config = new overlay::windows::Config(this));
|
||||
this->window_add(window_control = new overlay::windows::Control(this));
|
||||
this->window_add(window_log = new overlay::windows::Log(this));
|
||||
#ifdef SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
if (avs::game::is_model("LDJ")) {
|
||||
this->window_add(window_camera = new overlay::windows::CameraControl(this));
|
||||
}
|
||||
@@ -738,4 +738,4 @@ void overlay::SpiceOverlay::add_font(const char* font, ImFontConfig* config, con
|
||||
} else {
|
||||
log_misc("overlay", "font not found: {}", full_path.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "camera_control.h"
|
||||
|
||||
#if SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
#include <games/io.h>
|
||||
#include <strmif.h>
|
||||
@@ -193,7 +193,7 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
|
||||
// reset button
|
||||
if (ImGui::Button("Reset")) {
|
||||
selectedCamera->ResetCameraControlProps();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#if SPICE64
|
||||
#if SPICE64 && !SPICE_XP
|
||||
|
||||
#include "overlay/window.h"
|
||||
#include <strmif.h>
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace overlay::windows {
|
||||
" xxxx xxxx xxxx xxxx ");
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
|
||||
ImGui::PopID();
|
||||
return clicked;
|
||||
}
|
||||
@@ -152,8 +152,8 @@ namespace overlay::windows {
|
||||
void CardManager::open_card_editor() {
|
||||
if (this->current_card) {
|
||||
const auto card = this->current_card;
|
||||
strcpy_s(this->name_buffer, std::size(this->name_buffer), card->name.c_str());
|
||||
strcpy_s(this->card_buffer, std::size(this->card_buffer), card->id.c_str());
|
||||
snprintf(this->name_buffer, std::size(this->name_buffer), "%s", card->name.c_str());
|
||||
snprintf(this->card_buffer, std::size(this->card_buffer), "%s", card->id.c_str());
|
||||
this->color_buffer[0] = card->color[0];
|
||||
this->color_buffer[1] = card->color[1];
|
||||
this->color_buffer[2] = card->color[2];
|
||||
@@ -227,7 +227,7 @@ namespace overlay::windows {
|
||||
};
|
||||
generate_search_string(&card);
|
||||
this->cards.emplace_back(card);
|
||||
|
||||
|
||||
// mark this card as the selected one
|
||||
this->current_card = &this->cards.back();
|
||||
}
|
||||
@@ -301,7 +301,7 @@ namespace overlay::windows {
|
||||
|
||||
// search for card
|
||||
//
|
||||
// setting ImGuiInputTextFlags_CallbackCharFilter and pressing escape doesn't cause below
|
||||
// setting ImGuiInputTextFlags_CallbackCharFilter and pressing escape doesn't cause below
|
||||
// to return true, making it necessary to provide a callback...
|
||||
ImGui::SetNextItemWidth(overlay::apply_scaling(240));
|
||||
if (ImGui::InputTextWithHint("", "Type here to search..", &this->search_filter)) {
|
||||
@@ -399,11 +399,11 @@ namespace overlay::windows {
|
||||
|
||||
// cards from card manager JSON
|
||||
for (auto &card : this->cards) {
|
||||
|
||||
|
||||
if (!this->search_filter_in_lower_case.empty() && !card.search_string.empty()) {
|
||||
const bool matched =
|
||||
card.search_string.find(this->search_filter_in_lower_case) != std::string::npos;
|
||||
|
||||
|
||||
if (!matched) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace overlay::windows {
|
||||
constexpr ImVec4 TEXT_COLOR_GREEN(0.f, 1.f, 0.f, 1.f);
|
||||
constexpr ImVec4 TEXT_COLOR_RED(1.f, 0.f, 0.f, 1.f);
|
||||
constexpr uint32_t OPTION_INPUT_TEXT_WIDTH = 512;
|
||||
|
||||
|
||||
std::unique_ptr<AsioDriverList> asio_driver_list;
|
||||
|
||||
Config::Config(overlay::SpiceOverlay *overlay) : Window(overlay) {
|
||||
@@ -515,7 +515,7 @@ namespace overlay::windows {
|
||||
|
||||
ImGui::BeginChild("SearchOptions", ImVec2(
|
||||
0, ImGui::GetWindowContentRegionMax().y - page_offset), false);
|
||||
|
||||
|
||||
// search from all options
|
||||
ImGui::Spacing();
|
||||
ImGui::SetNextItemWidth(420.f);
|
||||
@@ -633,14 +633,14 @@ namespace overlay::windows {
|
||||
reset_button_to_default(&button, get_keypad_top_row(button));
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Remove All")) {
|
||||
for (auto &button : *buttons) {
|
||||
reset_button_to_default(&button, 0xFF);
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ImGui::Button("Yes")) {
|
||||
for (auto &button : *buttons) {
|
||||
@@ -789,7 +789,7 @@ namespace overlay::windows {
|
||||
// clear button
|
||||
if (button_display.size() > 0 || alt_index > 0) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::DeleteButton(button_display.size() > 0 ? "Unbind" : "Delete")) {
|
||||
if (ImGui::DeleteButton(button_display.size() > 0 ? "Unbind" : "Delete")) {
|
||||
clear_button(button, alt_index);
|
||||
}
|
||||
}
|
||||
@@ -1069,7 +1069,7 @@ namespace overlay::windows {
|
||||
{"P1 Keypad 00", VK_OEM_MINUS},
|
||||
{"P1 Keypad Decimal", VK_OEM_PLUS},
|
||||
{"P1 Keypad Insert Card", VK_BACK}};
|
||||
|
||||
|
||||
for (const auto &[key, value] : keypad_top_row_defaults) {
|
||||
if (button.getName() == key) {
|
||||
return value;
|
||||
@@ -1423,7 +1423,7 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
for (unsigned short ch = 0; ch < midi->pitch_bend.size(); ch++) {
|
||||
// check pitch bend down
|
||||
// check pitch bend down
|
||||
if (midi->pitch_bend[ch] < 0) {
|
||||
|
||||
// bind control
|
||||
@@ -1629,7 +1629,7 @@ namespace overlay::windows {
|
||||
if (ImGui::Selectable("Empty (Naive)", button->isNaive())) {
|
||||
button->setDeviceIdentifier("");
|
||||
dirty = true;
|
||||
}
|
||||
}
|
||||
if (button->isNaive()) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
@@ -1713,7 +1713,7 @@ namespace overlay::windows {
|
||||
button->setVelocityThreshold(0);
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
|
||||
type = button->getAnalogType();
|
||||
|
||||
int midi_channel = 0;
|
||||
@@ -1760,7 +1760,7 @@ namespace overlay::windows {
|
||||
} else if (0x20 <= midi_index && midi_index < 0x3F) {
|
||||
midi_index = 0x40;
|
||||
|
||||
// skip range [0x60, 0x65]
|
||||
// skip range [0x60, 0x65]
|
||||
} else if (midi_index == 0x65) {
|
||||
midi_index = 0x5F;
|
||||
} else if (0x60 <= midi_index && midi_index < 0x65) {
|
||||
@@ -1844,7 +1844,7 @@ namespace overlay::windows {
|
||||
ImGui::TextDisabled("Min. %d%%", velocity_threshold * 100 / 127);
|
||||
|
||||
} else if (type == ButtonAnalogType::BAT_MIDI_CTRL_PRECISION ||
|
||||
type == ButtonAnalogType::BAT_MIDI_CTRL_SINGLE) {
|
||||
type == ButtonAnalogType::BAT_MIDI_CTRL_SINGLE) {
|
||||
|
||||
ImGui::TextUnformatted("\n");
|
||||
ImGui::AlignTextToFramePadding();
|
||||
@@ -1912,7 +1912,7 @@ namespace overlay::windows {
|
||||
"Direction",
|
||||
is_up ? "Pitch Up" : "Pitch Down",
|
||||
ImGuiComboFlags_HeightSmall)) {
|
||||
|
||||
|
||||
if (ImGui::Selectable("Pitch Up", is_up)) {
|
||||
button->setAnalogType(ButtonAnalogType::BAT_MIDI_PITCH_UP);
|
||||
dirty = true;
|
||||
@@ -2213,7 +2213,7 @@ namespace overlay::windows {
|
||||
ImGui::SameLine();
|
||||
ImGui::HelpMarker(device->name.c_str());
|
||||
}
|
||||
|
||||
|
||||
switch (device->type) {
|
||||
case rawinput::MOUSE: {
|
||||
|
||||
@@ -2283,7 +2283,7 @@ namespace overlay::windows {
|
||||
if (device->midiInfo->pitch_bend_set[ch]) {
|
||||
control_names.push_back(fmt::format("Pitch Ch.{}", ch + 1));
|
||||
analogs_midi_indices.push_back(
|
||||
ch +
|
||||
ch +
|
||||
precision.size() +
|
||||
single.size() +
|
||||
onoff.size());
|
||||
@@ -2428,7 +2428,7 @@ namespace overlay::windows {
|
||||
if (invert != analog.getInvert()) {
|
||||
analog.setInvert(invert);
|
||||
}
|
||||
|
||||
|
||||
if (this->analogs_devices_selected >= 0) {
|
||||
const auto device = this->analogs_devices.at(this->analogs_devices_selected);
|
||||
if (device->type == rawinput::HID) {
|
||||
@@ -2783,7 +2783,7 @@ namespace overlay::windows {
|
||||
bool table_begin = false;
|
||||
for (size_t i = 0; i < lights->size(); i++) {
|
||||
auto &light = lights->at(i);
|
||||
|
||||
|
||||
if (current_section != light.getCategory()) {
|
||||
current_section = light.getCategory();
|
||||
if (table_begin) {
|
||||
@@ -2791,7 +2791,7 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
render_section_header(current_section.empty() ? "Uncategorized" : current_section);
|
||||
|
||||
|
||||
table_begin = begin_lights_table();
|
||||
if (!table_begin) {
|
||||
break;
|
||||
@@ -2813,7 +2813,7 @@ namespace overlay::windows {
|
||||
alt_index++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
if (table_begin) {
|
||||
ImGui::EndTable();
|
||||
@@ -2834,7 +2834,7 @@ namespace overlay::windows {
|
||||
|
||||
// progress bar
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
|
||||
// light name
|
||||
if (alt_index == 0) {
|
||||
ImGui::ProgressBar(light_state, ImVec2(32.f, 0));
|
||||
@@ -2865,7 +2865,7 @@ namespace overlay::windows {
|
||||
// clear light
|
||||
if (light_display.size() > 0 || alt_index > 0) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::DeleteButton(light_display.size() > 0 ? "Unbind" : "Delete")) {
|
||||
if (ImGui::DeleteButton(light_display.size() > 0 ? "Unbind" : "Delete")) {
|
||||
clear_light(light, alt_index);
|
||||
}
|
||||
}
|
||||
@@ -2948,7 +2948,7 @@ namespace overlay::windows {
|
||||
games_list[games_selected], *light,
|
||||
alt_index - 1);
|
||||
}
|
||||
|
||||
|
||||
void Config::edit_light_popup(Light &primary_light, Light *light, const int alt_index) {
|
||||
if (ImGui::BeginPopupModal("Light Binding", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
|
||||
|
||||
@@ -3748,7 +3748,7 @@ namespace overlay::windows {
|
||||
|
||||
return detected_controller;
|
||||
}
|
||||
|
||||
|
||||
void Config::build_cards() {
|
||||
|
||||
constexpr float TEXT_INPUT_WIDTH = 240.f;
|
||||
@@ -4078,12 +4078,12 @@ namespace overlay::windows {
|
||||
// verify card number
|
||||
this->keypads_card_file_contents_valid[player] = true;
|
||||
if (this->keypads_card_number[player][0] != 0) {
|
||||
this->keypads_card_file_contents_valid[player] =
|
||||
this->keypads_card_file_contents_valid[player] =
|
||||
validate_ea_card(this->keypads_card_number[player]);
|
||||
}
|
||||
|
||||
// card number box
|
||||
|
||||
|
||||
ImGui::SetNextItemWidth(TEXT_INPUT_WIDTH);
|
||||
ImGui::BeginDisabled();
|
||||
if (this->keypads_card_number[player][0] != 0) {
|
||||
@@ -4289,7 +4289,9 @@ namespace overlay::windows {
|
||||
ImGui::TextUnformatted("Requires restart! Showing all procs in Group 0.");
|
||||
ImGui::TextUnformatted("");
|
||||
ImGui::TextUnformatted("Pick CPU cores to use:");
|
||||
const uint64_t cpu_count = GetActiveProcessorCount(0);
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
const uint64_t cpu_count = info.dwNumberOfProcessors;
|
||||
uint64_t affinity = 0;
|
||||
if (!option.value.empty()) {
|
||||
try {
|
||||
@@ -4333,7 +4335,7 @@ namespace overlay::windows {
|
||||
option.value = fmt::format("0x{:X}", affinity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ImGui::EndChild();
|
||||
if (option.value.empty()) {
|
||||
ImGui::TextUnformatted("Using all CPUs (option default).");
|
||||
@@ -4499,7 +4501,7 @@ namespace overlay::windows {
|
||||
|
||||
void Config::build_options(
|
||||
std::vector<Option> *options, const std::string &category, const std::string *filter) {
|
||||
int options_count;
|
||||
int options_count;
|
||||
|
||||
// category name
|
||||
std::string cat = "Options";
|
||||
@@ -4525,19 +4527,19 @@ namespace overlay::windows {
|
||||
widget_col_width = overlay::apply_scaling(264);
|
||||
}
|
||||
ImGui::TableSetupColumn("Setting", ImGuiTableColumnFlags_WidthFixed, widget_col_width);
|
||||
|
||||
|
||||
// iterate options
|
||||
options_count = 0;
|
||||
for (auto &option : *options) {
|
||||
|
||||
|
||||
// get option definition
|
||||
auto &definition = option.get_definition();
|
||||
|
||||
|
||||
// check category
|
||||
if (!category.empty() && definition.category != category) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// check hidden option
|
||||
if (!this->options_show_hidden && option.value.empty()) {
|
||||
// skip hidden entries
|
||||
@@ -4552,7 +4554,7 @@ namespace overlay::windows {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// filter
|
||||
if (filter != nullptr) {
|
||||
if (filter->empty()) {
|
||||
@@ -4568,7 +4570,7 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
options_count += 1;
|
||||
|
||||
|
||||
// list entry
|
||||
ImGui::PushID(&option);
|
||||
ImGui::TableNextRow();
|
||||
@@ -4580,10 +4582,10 @@ namespace overlay::windows {
|
||||
if (definition.category.empty()) {
|
||||
ImGui::TextDisabled("-");
|
||||
} else {
|
||||
ImGui::TextDisabled(definition.category.c_str());
|
||||
ImGui::TextDisabled("%s", definition.category.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// option name
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
@@ -4763,7 +4765,7 @@ namespace overlay::windows {
|
||||
if (!element.second.empty()) {
|
||||
label += fmt::format(" ({})", element.second);
|
||||
}
|
||||
|
||||
|
||||
bool selected = current_item == label;
|
||||
if (ImGui::Selectable(label.c_str(), selected)) {
|
||||
this->options_dirty = true;
|
||||
@@ -4834,7 +4836,7 @@ namespace overlay::windows {
|
||||
ImGui::TextColored(ImVec4(1, 0.7f, 0, 1), "%s", definition.title.c_str());
|
||||
|
||||
ImGui::TextUnformatted("");
|
||||
|
||||
|
||||
ImGui::TextUnformatted("Current value:");
|
||||
ImGui::BeginDisabled();
|
||||
// keeping it read only; if you want to make this editable, we need to refactor the
|
||||
@@ -4856,7 +4858,7 @@ namespace overlay::windows {
|
||||
if (ImGui::Button("Save & Close")) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
this->options_dirty = true;
|
||||
::Config::getInstance().updateBinding(games_list[games_selected], option);
|
||||
::Config::getInstance().updateBinding(games_list[games_selected], option);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
@@ -4864,7 +4866,7 @@ namespace overlay::windows {
|
||||
|
||||
// row hover detection (invisible selectable that spans entire row)
|
||||
ImGui::InvisibleTableRowSelectable();
|
||||
|
||||
|
||||
// next item
|
||||
ImGui::PopID();
|
||||
}
|
||||
@@ -4900,14 +4902,19 @@ namespace overlay::windows {
|
||||
}
|
||||
|
||||
void Config::build_about() {
|
||||
#ifndef SPICE_LINUX
|
||||
#if SPICE_LINUX
|
||||
ImGui::TextUnformatted(std::string(
|
||||
"spice2x (a fork of SpiceTools)\r\n"
|
||||
"spice2x (a fork of SpiceTools) for Linux\r\n"
|
||||
"=========================\r\n" +
|
||||
to_string(VERSION_STRING)).c_str());
|
||||
#elif SPICE_XP
|
||||
ImGui::TextUnformatted(std::string(
|
||||
"spice2x (a fork of SpiceTools) for WinXP\r\n"
|
||||
"=========================\r\n" +
|
||||
to_string(VERSION_STRING)).c_str());
|
||||
#else
|
||||
ImGui::TextUnformatted(std::string(
|
||||
"spice2x (a fork of SpiceTools) for Linux\r\n"
|
||||
"spice2x (a fork of SpiceTools)\r\n"
|
||||
"=========================\r\n" +
|
||||
to_string(VERSION_STRING)).c_str());
|
||||
#endif
|
||||
@@ -4916,7 +4923,7 @@ namespace overlay::windows {
|
||||
if (ImGui::TextLink(PROJECT_URL)) {
|
||||
launch_shell(PROJECT_URL);
|
||||
}
|
||||
|
||||
|
||||
ImGui::TextUnformatted("");
|
||||
ImGui::TextUnformatted(resutil::load_file_string_crlf(IDR_README).c_str());
|
||||
ImGui::TextUnformatted("");
|
||||
@@ -5024,7 +5031,7 @@ namespace overlay::windows {
|
||||
const ImVec2 popup_pos(
|
||||
ImGui::GetIO().DisplaySize.x / 2 - popup_size.x / 2,
|
||||
ImGui::GetIO().DisplaySize.y / 2 - popup_size.y / 2);
|
||||
|
||||
|
||||
ImGui::SetNextWindowSize(popup_size, ImGuiCond_Appearing);
|
||||
ImGui::SetNextWindowPos(popup_pos, ImGuiCond_Appearing);
|
||||
bool unused_open2 = true;
|
||||
@@ -5691,7 +5698,7 @@ namespace overlay::windows {
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
|
||||
if (!apply_buttons && !apply_keypads && !apply_analogs && !apply_lights) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// GetDisplayConfigBufferSizes etc is Vista+
|
||||
#define _WIN32_WINNT 0x0601
|
||||
|
||||
#include "sysutils.h"
|
||||
|
||||
#include <cstdlib>
|
||||
@@ -20,7 +23,7 @@
|
||||
|
||||
namespace sysutils {
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
// from https://learn.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemfirmwaretable
|
||||
@@ -318,7 +321,7 @@ namespace sysutils {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static std::vector<MonitorEntry> enumerate_monitors_internal() {
|
||||
// for WinXP, since these are Vista+ or 7+ APIs
|
||||
const auto user32 = LoadLibraryA("user32.dll");
|
||||
@@ -372,7 +375,7 @@ namespace sysutils {
|
||||
for (const auto& path : paths) {
|
||||
MonitorEntry entry;
|
||||
|
||||
// device ID (\\.\DISPLAYn)
|
||||
// device ID (\\.\DISPLAYn)
|
||||
DISPLAYCONFIG_SOURCE_DEVICE_NAME source_name = {};
|
||||
source_name.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
|
||||
source_name.header.size = sizeof(source_name);
|
||||
|
||||
Reference in New Issue
Block a user