Merge branch 'wine_fixes_overlay_image_display_support' into 'master'

Implement displaying images in the overlay, friend avatar support, fix overlay rendering glitches under wine, and some misc. fixes.

See merge request Mr_Goldberg/goldberg_emulator!57
This commit is contained in:
redpolline 2025-02-13 03:05:50 +00:00
commit dec6e8bdbe
87 changed files with 7173 additions and 677 deletions

13
.gitattributes vendored Normal file
View File

@ -0,0 +1,13 @@
# Set the default behavior.
* text=auto
# Unix shell files should always be LF.
*.sh text eol=lf
# Windows shell files should always be CRLF.
*.bat text eol=crlf
# Binary files.
*.jpg binary
*.png binary

35
.gitignore vendored
View File

@ -1,17 +1,18 @@
.vs/*
.vscode/*
*.bin
*.o
net.pb.*
*steam_api*
release/*
/build*/
*.obj
/dll/net.pb.cc
/dll/net.pb.h
base.exp
base.lib
rtlgenrandom*
steamclient.exp
steamclient.lib
out/*
.vs/*
.vscode/*
*.bin
*.o
net.pb.*
*steam_api*
release/*
debug/*
/build*/
*.obj
/dll/net.pb.cc
/dll/net.pb.h
base.exp
base.lib
rtlgenrandom*
steamclient.exp
steamclient.lib
out/*

View File

@ -59,25 +59,38 @@ build_windows:
image: fedora:35
script:
- dnf -y install wine wget p7zip sed dos2unix python
- dnf -y install wine wget p7zip sed dos2unix python cpio
- unix2dos *.txt
- unix2dos files_example/*.txt files_example/*/*.txt
- sed -i 's/..\\vcpkg\\installed\\/.\\protobuf_/g' build_set_protobuf_directories.bat
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/48db8f434a193aae872279dc4f5dde6a/sdk_standalone.7z'
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/0119304e030098b4821d73170fe52084/protobuf_x64-windows-static.7z'
- wget 'https://gitlab.com/Mr_Goldberg/goldberg_emulator/uploads/4185a97ab363ddc1859127e59ec68581/protobuf_x86-windows-static.7z'
- mkdir wine
# Ancient CI version of wine doesn't support the where.exe cmd. (It's a stub.) Use the version from wine-10.1.
# Note: This can use the fedora archive once f40 goes eol (~ 5/28/2025) and wine 10.x gets locked into their archive server.
# (Can't use it before then due to newer wine point releases changing the URL....)
#- wget 'https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/39/Everything/x86_64/os/Packages/w/wine-core-10.0-1.fc41.i686.rpm'
#- echo './usr/lib/wine/i386-windows/where.exe' > extract.txt; rpm2cpio wine-core-10.0-1.fc41.i686.rpm | cpio -ivdE extract.txt; rm -f extract.txt
#- /usr/bin/mv -f ./usr/lib/wine/i386-windows/where.exe wine/; rm -rf ./usr/
- wget 'https://dl.winehq.org/wine-builds/fedora/41/x86_64/wine-devel-10.0.0-1.1.x86_64.rpm'
- echo './opt/wine-devel/lib64/wine/i386-windows/where.exe' > extract.txt; rpm2cpio wine-devel-10.0.0-1.1.x86_64.rpm | cpio -ivdE extract.txt; rm -f extract.txt
- /usr/bin/mv -f ./opt/wine-devel/lib64/wine/i386-windows/where.exe wine/; rm -rf ./opt/
- /usr/bin/cp -f wine/where.exe /usr/lib/wine/i386-windows/where.exe; /usr/bin/cp -f wine/where.exe /usr/lib64/wine/x86_64-windows/where.exe
- 7za x protobuf_x86-windows-static.7z -oprotobuf_x86-windows-static
- 7za x protobuf_x64-windows-static.7z -oprotobuf_x64-windows-static
- 7za x sdk_standalone.7z -osdk_standalone
- DLL_FILES="$(ls dll/*.cpp | tr "\n" " ")"; sed "s|dll/\*.cpp|$DLL_FILES|g" -i *.bat
- DLL_FILES="$(ls dll/*.proto | tr "\n" " " | sed "s/.proto/.pb.cc/g")"; sed "s|dll/\*.cc|$DLL_FILES|g" -i *.bat
- sed "s| /MP12 | /MP4 |g" -i *.bat
- python generate_build_win_bat.py
# CI can't produce PDBs. Throws a bunch of errors, and skips building the PEs.
- touch CI_BUILD.TAG
- export WINEDEBUG=-all
- wine cmd /c build_win_release_test.bat
- WINEPATH=$PWD/wine wine cmd /c build_win_debug_experimental_steamclient.bat 8
- WINEPATH=$PWD/wine wine cmd /c build_win_release.bat 8
artifacts:
paths:
- release/
- debug/
expire_in: 1 day
build_cmake_linux:
@ -156,9 +169,9 @@ deploy_all:
- mv linux release/
- shopt -s extglob
- rm -rf .g*
- rm -rf !(release)
- mv release/* ./
- rm -rf release
- rm -rf !(release|debug)
# - mv release/* ./
# - rm -rf release
- echo $CI_JOB_ID > job_id
- tree
artifacts:

View File

@ -12,6 +12,8 @@ if exist "%VS_Base_Path%\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Bu
if exist "%VS_Base_Path%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat" goto vs2022
if exist "%VS_Base_Path%\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars64.bat" goto vs2022_bt
if exist ".\sdk_standalone\set_vars64.bat" goto gitlabci
if exist "vsinstallloc.txt" goto readloc
if exist "%VS_Base_Path%\Microsoft Visual Studio\Installer\vswhere.exe" goto wherevs
:vs2022
call "%VS_Base_Path%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars64.bat"
@ -44,4 +46,14 @@ goto batend
:gitlabci
call ".\sdk_standalone\set_vars64.bat"
goto batend
:wherevs
call "%VS_Base_Path%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath > vsinstallloc.txt
goto readloc
:readloc
set /p VS_LOCAL=<vsinstallloc.txt
call "%VS_LOCAL%\VC\Auxiliary\Build\vcvars64.bat"
goto batend
:batend

View File

@ -12,6 +12,8 @@ if exist "%VS_Base_Path%\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Bu
if exist "%VS_Base_Path%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars32.bat" goto vs2022
if exist "%VS_Base_Path%\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvars32.bat" goto vs2022_bt
if exist ".\sdk_standalone\set_vars32.bat" goto gitlabci
if exist "vsinstallloc.txt" goto readloc
if exist "%VS_Base_Path%\Microsoft Visual Studio\Installer\vswhere.exe" goto wherevs
:vs2022
call "%VS_Base_Path%\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvars32.bat"
@ -41,8 +43,17 @@ goto batend
call "%VS_Base_Path%\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars32.bat"
goto batend
:gitlabci
call ".\sdk_standalone\set_vars32.bat"
goto batend
:wherevs
call "%VS_Base_Path%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath > vsinstallloc.txt
goto readloc
:readloc
set /p VS_LOCAL=<vsinstallloc.txt
call "%VS_LOCAL%\VC\Auxiliary\Build\vcvars32.bat"
goto batend
:batend

View File

@ -1,2 +0,0 @@
protoc -I./dll/ --cpp_out=./dll/ ./dll/*.proto
clang++ -shared -fPIC -o libsteam_api.so dll/*.cpp dll/*.cc -g3 -Wno-return-type -fsanitize=address -lasan -lprotobuf-lite -std=c++14 && echo built

21
build_linux_debug.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
if [ ! -d "${PWD}/debug" ]; then
mkdir "${PWD}/debug"
fi
if [ ! -d "${PWD}/debug/experimental" ]; then
mkdir "${PWD}/debug/experimental"
fi
if [ ! -d "${PWD}/debug/lobby_connect" ]; then
mkdir "${PWD}/debug/lobby_connect"
fi
protoc -I"${PWD}/dll/" --cpp_out="${PWD}/dll/" "${PWD}"/dll/*.proto
rm -rf "${PWD}/debug/experimental"/*
pushd "${PWD}/debug/experimental" >/dev/null
echo "Building debug libsteam_api.so...."
clang++ -shared -fPIC -o libsteam_api.so ../../dll/*.cpp ../../dll/*.cc -g3 -Wno-return-type -fsanitize=address -shared-libasan -lprotobuf-lite -std=c++14 && echo built libsteam_api.so
popd >/dev/null
rm -rf "${PWD}/debug/lobby_connect"/*
pushd "${PWD}/debug/lobby_connect" >/dev/null
echo "Building debug lobby_connect...."
clang++ -DNO_DISK_WRITES=1 -DLOBBY_CONNECT=1 -fPIC -o lobby_connect ../../lobby_connect.cpp ../../dll/*.cpp ../../dll/*.cc -g3 -Wno-return-type -fsanitize=address -shared-libasan -lprotobuf-lite -std=c++14 && echo built lobby_connect
popd >/dev/null

27
build_linux_release.sh Normal file
View File

@ -0,0 +1,27 @@
#!/bin/bash
if [ ! -d "${PWD}/release" ]; then
mkdir "${PWD}/release"
fi
if [ ! -d "${PWD}/release/experimental" ]; then
mkdir "${PWD}/release/experimental"
fi
if [ ! -d "${PWD}/release/lobby_connect" ]; then
mkdir "${PWD}/release/lobby_connect"
fi
protoc -I"${PWD}/dll/" --cpp_out="${PWD}/dll/" "${PWD}"/dll/*.proto
rm -rf "${PWD}/release/experimental"/*
pushd "${PWD}/release/experimental" >/dev/null
echo "Building release libsteam_api.so...."
clang++ -DNDEBUG=1 -DEMU_RELEASE_BUILD=1 -shared -fPIC -o libsteam_api.so ../../dll/*.cpp ../../dll/*.cc -g3 -Wno-return-type -fsanitize=address -shared-libasan -lprotobuf-lite -std=c++14 && echo built libsteam_api.so
cp libsteam_api.so libsteam_api.so.dbg
strip --enable-deterministic-archives --strip-unneeded --remove-section=.comment --remove-section=.note libsteam_api.so
objcopy --add-gnu-debuglink=libsteam_api.so.dbg libsteam_api.so
popd >/dev/null
rm -rf "${PWD}/release/lobby_connect"/*
pushd "${PWD}/release/lobby_connect" >/dev/null
echo "Building release lobby_connect...."
clang++ -DNO_DISK_WRITES=1 -DLOBBY_CONNECT=1 -DNDEBUG=1 -DEMU_RELEASE_BUILD=1 -fPIC -o lobby_connect ../../lobby_connect.cpp ../../dll/*.cpp ../../dll/*.cc -g3 -Wno-return-type -fsanitize=address -shared-libasan -lprotobuf-lite -std=c++14 && echo built lobby_connect
cp lobby_connect lobby_connect.dbg
strip --enable-deterministic-archives --strip-unneeded --remove-section=.comment --remove-section=.note lobby_connect
objcopy --add-gnu-debuglink=lobby_connect.dbg lobby_connect
popd >/dev/null

View File

@ -1,7 +1,14 @@
@echo off
cd /d "%~dp0"
SET PROTOBUF_X86_DIRECTORY=..\vcpkg\installed\x86-windows-static
SET PROTOBUF_X64_DIRECTORY=..\vcpkg\installed\x64-windows-static
SET TEST_A=%cd%
REM CI doesn't like this var expansion of "%cd%\".
cd ..\vcpkg\installed\x86-windows-static
SET PROTOBUF_X86_DIRECTORY=%cd%
cd %TEST_A%
cd ..\vcpkg\installed\x64-windows-static
SET PROTOBUF_X64_DIRECTORY=%cd%
cd %TEST_A%
rem location of protoc in protobuf directories:
SET PROTOC_X86_EXE=%PROTOBUF_X86_DIRECTORY%\tools\protobuf\protoc.exe

View File

@ -1,14 +1,9 @@
@echo off
cd /d "%~dp0"
call build_set_protobuf_directories.bat
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /Z7 /LD /IImGui /I%PROTOBUF_X86_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /link /OUT:steam_api.dll
cl /LD steamclient.cpp /EHsc /MP12 /link /OUT:steamclient.dll
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /Z7 /LD /IImGui /I%PROTOBUF_X64_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /link /OUT:steam_api64.dll
cl /LD steamclient.cpp /EHsc /MP12 /link /OUT:steamclient64.dll
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
SET SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD=1
SET SKIP_STEAMCLIENT_LOADER=1
call build_win_debug_experimental_steamclient.bat

View File

@ -1,9 +1,141 @@
@echo off
cd /d "%~dp0"
call build_set_protobuf_directories.bat
SET OLD_DIR=%cd%
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT DEFINED BUILT_ALL_DEPS ( call generate_all_deps.bat )
IF EXIST build\experimental\steamclient\debug\x86\*.* ( DEL /F /S /Q build\experimental\steamclient\debug\x86\*.* )
IF EXIST build\experimental\steamclient\debug\x64\*.* ( DEL /F /S /Q build\experimental\steamclient\debug\x64\*.* )
IF EXIST debug\experimental_steamclient\*.* ( DEL /F /S /Q debug\experimental_steamclient\*.* )
setlocal
IF DEFINED SKIP_X86 GOTO LK_X64
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /IImGui /I%PROTOBUF_X86_DIRECTORY%\include\ /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_EXPERIMENTAL_BUILD /DEMU_OVERLAY /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /link /OUT:steamclient.dll
REM Non-STEAMCLIENT_DLL debug sc_deps.
cd "%OLD_DIR%\build\experimental_steamclient\debug\x86\sc_deps"
cl /c @%CDS_DIR%\DEBUG.BLD @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\SC_DEPS.BLD
IF EXIST %CDS_DIR%\DEBUG_SC_DEPS_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_SC_DEPS_X86.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_SC_DEPS_X86.LKS
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_EXP_STEAMCLIENT_DLL_X86
REM Link Non-STEAMCLIENT_DLL debug steam_api.dll.
cd "%OLD_DIR%\build\experimental\debug\x86\"
IF EXIST %CDS_DIR%\DEBUG_STEAMAPI_NON_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMAPI_NON_X86.LKS )
echo /link /OUT:%OLD_DIR%\debug\experimental\steam_api.dll > %CDS_DIR%\DEBUG_STEAMAPI_NON_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental\steam_api.pdb >> %CDS_DIR%\DEBUG_STEAMAPI_NON_X86.LKS )
cl /LD @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\PROTOBUF_X86.LKS @%CDS_DIR%\EXPERIMENTAL.BLD @%CDS_DIR%\EXPERIMENTAL.LKS @%CDS_DIR%\DEBUG_ALL_DEPS_X86.LKS @%CDS_DIR%\DEBUG_SC_DEPS_X86.LKS @%CDS_DIR%\DEBUG_STEAMAPI_NON_X86.LKS
:LK_EXP_STEAMCLIENT_DLL_X86
IF DEFINED SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD GOTO LK_STEAMCLIENT_DLL_X86
REM Link STEAMCLIENT_DLL debug steamclient.dll
cd "%OLD_DIR%\build\experimental_steamclient\debug\x86"
IF EXIST %CDS_DIR%\DEBUG_STEAMCLIENT_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMCLIENT_X86.LKS )
echo /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient.dll > %CDS_DIR%\DEBUG_STEAMCLIENT_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental_steamclient\steamclient.pdb >> %CDS_DIR%\DEBUG_STEAMCLIENT_X86.LKS )
cl /LD @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\PROTOBUF_X86.LKS @%CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS @%CDS_DIR%\DEBUG_ALL_DEPS_X86.LKS @%CDS_DIR%\DEBUG_SC_DEPS_X86.LKS @%CDS_DIR%\DEBUG_STEAMCLIENT_X86.LKS
:LK_STEAMCLIENT_DLL_X86
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_STEAMCLIENT_LOADER_X86
REM Link Non-STEAMCLIENT_DLL debug steamclient.dll.
cd "%OLD_DIR%\build\experimental\debug\x86\"
IF EXIST %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X86.LKS )
echo /link /OUT:%OLD_DIR%\debug\experimental\steamclient.dll > %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental\steamclient.pdb >> %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X86.LKS )
cl /LD @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\STEAMCLIENT.BLD @%CDS_DIR%\DEBUG_STEAMCLIENT_NON_X86.LKS
:LK_STEAMCLIENT_LOADER_X86
IF DEFINED SKIP_STEAMCLIENT_LOADER GOTO LK_X64
REM Build steamclient_loader debug x86.
cd "%OLD_DIR%\build\experimental_steamclient\steamclient_loader\debug\x86"
cl /c @%CDS_DIR%\DEBUG.BLD @%CDS_DIR%\STEAMCLIENT_LOADER.BLD
IF EXIST %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X86.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X86.LKS
echo /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x32.exe >> %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x32.pdb >> %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X86.LKS )
cl @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\STEAMCLIENT_LOADER.LKS @%CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X86.LKS
cd %OLD_DIR%
:LK_X64
endlocal
setlocal
IF DEFINED SKIP_X64 GOTO LK_END
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /IImGui /I%PROTOBUF_X64_DIRECTORY%\include\ /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_EXPERIMENTAL_BUILD /DEMU_OVERLAY /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /link /OUT:steamclient64.dll
REM Non-STEAMCLIENT_DLL debug sc_deps.
cd "%OLD_DIR%\build\experimental_steamclient\debug\x64\sc_deps"
cl /c @%CDS_DIR%\DEBUG.BLD @%CDS_DIR%\PROTOBUF_X64.BLD @%CDS_DIR%\SC_DEPS.BLD
IF EXIST %CDS_DIR%\DEBUG_SC_DEPS_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_SC_DEPS_X64.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_SC_DEPS_X64.LKS
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_EXP_STEAMCLIENT_DLL_X64
REM Link Non-STEAMCLIENT_DLL debug steam_api64.dll.
cd "%OLD_DIR%\build\experimental\debug\x64\"
IF EXIST %CDS_DIR%\DEBUG_STEAMAPI_NON_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMAPI_NON_X64.LKS )
echo /link /OUT:%OLD_DIR%\debug\experimental\steam_api64.dll > %CDS_DIR%\DEBUG_STEAMAPI_NON_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental\steam_api64.pdb >> %CDS_DIR%\DEBUG_STEAMAPI_NON_X64.LKS )
cl /LD @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\PROTOBUF_X64.LKS @%CDS_DIR%\EXPERIMENTAL.BLD @%CDS_DIR%\EXPERIMENTAL.LKS @%CDS_DIR%\DEBUG_ALL_DEPS_X64.LKS @%CDS_DIR%\DEBUG_SC_DEPS_X64.LKS @%CDS_DIR%\DEBUG_STEAMAPI_NON_X64.LKS
:LK_EXP_STEAMCLIENT_DLL_X64
IF DEFINED SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD GOTO LK_STEAMCLIENT_DLL_X64
REM Link STEAMCLIENT_DLL debug steamclient64.dll
cd "%OLD_DIR%\build\experimental_steamclient\debug\x64"
IF EXIST %CDS_DIR%\DEBUG_STEAMCLIENT_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMCLIENT_X64.LKS )
echo /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient64.dll > %CDS_DIR%\DEBUG_STEAMCLIENT_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental_steamclient\steamclient64.pdb >> %CDS_DIR%\DEBUG_STEAMCLIENT_X64.LKS )
cl /LD @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\PROTOBUF_X64.LKS @%CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS @%CDS_DIR%\DEBUG_ALL_DEPS_X64.LKS @%CDS_DIR%\DEBUG_SC_DEPS_X64.LKS @%CDS_DIR%\DEBUG_STEAMCLIENT_X64.LKS
:LK_STEAMCLIENT_DLL_X64
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_STEAMCLIENT_LOADER_X64
REM Link Non-STEAMCLIENT_DLL debug steamclient64.dll.
cd "%OLD_DIR%\build\experimental\debug\x64\"
IF EXIST %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X64.LKS )
echo /link /OUT:%OLD_DIR%\debug\experimental\steamclient64.dll > %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental\steamclient64.pdb >> %CDS_DIR%\DEBUG_STEAMCLIENT_NON_X64.LKS )
cl /LD @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\STEAMCLIENT.BLD @%CDS_DIR%\DEBUG_STEAMCLIENT_NON_X64.LKS
:LK_STEAMCLIENT_LOADER_X64
IF DEFINED SKIP_STEAMCLIENT_LOADER GOTO LK_END
REM Build steamclient_loader debug x64.
cd "%OLD_DIR%\build\experimental_steamclient\steamclient_loader\debug\x64"
cl /c @%CDS_DIR%\DEBUG.BLD @%CDS_DIR%\STEAMCLIENT_LOADER.BLD
IF EXIST %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X64.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X64.LKS
echo /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x64.exe >> %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x64.pdb >> %CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X64.LKS )
cl @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\STEAMCLIENT_LOADER.LKS @%CDS_DIR%\DEBUG_STEAMCLIENT_LOADER_X64.LKS
cd %OLD_DIR%
:LK_END
endlocal
copy Readme_experimental.txt debug\experimental\Readme.txt
copy steamclient_loader\ColdClientLoader.ini debug\experimental_steamclient\
copy Readme_experimental_steamclient.txt debug\experimental_steamclient\Readme.txt

View File

@ -0,0 +1,46 @@
@echo off
cd /d "%~dp0"
SET OLD_DIR=%cd%
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT DEFINED BUILT_ALL_DEPS ( call generate_all_deps.bat )
IF EXIST build\debug\lobby_connect\x86\*.* ( DEL /F /S /Q build\debug\lobby_connect\x86\*.* )
IF EXIST build\debug\lobby_connect\x64\*.* ( DEL /F /S /Q build\debug\lobby_connect\x64\*.* )
IF EXIST debug\lobby_connect\*.* ( DEL /F /S /Q debug\lobby_connect\*.* )
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cd %OLD_DIR%\build\lobby_connect\debug\x86
cl /c @%CDS_DIR%\DEBUG.BLD @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\LOBBY_CONNECT.BLD
IF EXIST %CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS
echo /link /OUT:%OLD_DIR%\debug\lobby_connect\lobby_connect_x32.exe >> %CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS
echo /link /IMPLIB:%cd%\lobby_connect_x32.lib >> %CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\lobby_connect\lobby_connect_x32.pdb >> %CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS )
cl @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\PROTOBUF_X86.LKS @%CDS_DIR%\LOBBY_CONNECT.LKS @%CDS_DIR%\DEBUG_LOBBY_CONNECT_X86.LKS
cd %OLD_DIR%
endlocal
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
cd %OLD_DIR%\build\lobby_connect\debug\x64
cl /c @%CDS_DIR%\DEBUG.BLD @%CDS_DIR%\PROTOBUF_X64.BLD @%CDS_DIR%\LOBBY_CONNECT.BLD
IF EXIST %CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS
echo /link /OUT:%OLD_DIR%\debug\lobby_connect\lobby_connect_x64.exe >> %CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS
echo /link /IMPLIB:%cd%\lobby_connect_x64.lib >> %CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\debug\lobby_connect\lobby_connect_x64.pdb >> %CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS )
cl @%CDS_DIR%\DEBUG.LKS @%CDS_DIR%\PROTOBUF_X64.BLD @%CDS_DIR%\PROTOBUF_X64.LKS @%CDS_DIR%\LOBBY_CONNECT.LKS @%CDS_DIR%\DEBUG_LOBBY_CONNECT_X64.LKS
cd %OLD_DIR%
endlocal
copy Readme_lobby_connect.txt debug\lobby_connect\Readme.txt

View File

@ -1,9 +1,39 @@
@echo off
cd /d "%~dp0"
mkdir release\tools
del /Q release\tools\*
SET OLD_DIR=%cd%
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT DEFINED BUILT_ALL_DEPS ( call generate_all_deps.bat )
IF EXIST build\tools\release\x86\*.* ( DEL /F /S /Q build\tools\release\x86\*.* )
IF EXIST build\tools\release\x64\*.* ( DEL /F /S /Q build\tools\release\x64\*.* )
IF EXIST release\tools\*.* ( DEL /F /S /Q release\tools\*.* )
setlocal
call build_env_x86.bat
cl generate_interfaces_file.cpp /EHsc /MP12 /Ox /link /debug:none /OUT:release\tools\generate_interfaces_file.exe
del /Q /S release\tools\*.lib
del /Q /S release\tools\*.exp
cd %OLD_DIR%\build\tools\release\x86
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\GENERATE_INTERFACES_FILE.BLD
IF EXIST %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X86.LKS )
where "generate_interfaces_file.obj" > %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X86.LKS
echo /link /OUT:%OLD_DIR%\release\tools\generate_interfaces_file_x32.exe >> %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\tools\generate_interfaces_file_x32.pdb >> %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X86.LKS )
cl @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\GENERATE_INTERFACES_FILE.LKS @%CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X86.LKS
cd %OLD_DIR%
endlocal
setlocal
call build_env_x64.bat
cd %OLD_DIR%\build\tools\release\x64
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\GENERATE_INTERFACES_FILE.BLD
IF EXIST %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X64.LKS )
where "generate_interfaces_file.obj" > %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X64.LKS
echo /link /OUT:%OLD_DIR%\release\tools\generate_interfaces_file_x64.exe >> %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\tools\generate_interfaces_file_x64.pdb >> %CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X64.LKS )
cl @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\GENERATE_INTERFACES_FILE.LKS @%CDS_DIR%\RELEASE_GENERATE_INTERFACES_FILE_X64.LKS
cd %OLD_DIR%
endlocal
copy Readme_generate_interfaces.txt release\tools\Readme_generate_interfaces.txt

View File

@ -1,12 +1,46 @@
@echo off
cd /d "%~dp0"
mkdir release\lobby_connect
del /Q release\lobby_connect\*
call build_set_protobuf_directories.bat
SET OLD_DIR=%cd%
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT DEFINED BUILT_ALL_DEPS ( call generate_all_deps.bat )
IF EXIST build\release\lobby_connect\x86\*.* ( DEL /F /S /Q build\release\lobby_connect\x86\*.* )
IF EXIST build\release\lobby_connect\x64\*.* ( DEL /F /S /Q build\release\lobby_connect\x64\*.* )
IF EXIST release\lobby_connect\*.* ( DEL /F /S /Q release\lobby_connect\*.* )
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /DNO_DISK_WRITES /DLOBBY_CONNECT /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ lobby_connect.cpp dll/*.cpp dll/*.cc "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Comdlg32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\lobby_connect\lobby_connect.exe
del /Q /S release\lobby_connect\*.lib
del /Q /S release\lobby_connect\*.exp
cd %OLD_DIR%\build\lobby_connect\release\x86
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\LOBBY_CONNECT.BLD
IF EXIST %CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS
echo /link /OUT:%OLD_DIR%\release\lobby_connect\lobby_connect_x32.exe >> %CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS
echo /link /IMPLIB:%cd%\lobby_connect_x32.lib >> %CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\lobby_connect\lobby_connect_x32.pdb >> %CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS )
cl @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\PROTOBUF_X86.LKS @%CDS_DIR%\LOBBY_CONNECT.LKS @%CDS_DIR%\RELEASE_LOBBY_CONNECT_X86.LKS
cd %OLD_DIR%
endlocal
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
cd %OLD_DIR%\build\lobby_connect\release\x64
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\PROTOBUF_X64.BLD @%CDS_DIR%\LOBBY_CONNECT.BLD
IF EXIST %CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS
echo /link /OUT:%OLD_DIR%\release\lobby_connect\lobby_connect_x64.exe >> %CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS
echo /link /IMPLIB:%cd%\lobby_connect_x64.lib >> %CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\lobby_connect\lobby_connect_x64.pdb >> %CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS )
cl @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\PROTOBUF_X64.BLD @%CDS_DIR%\PROTOBUF_X64.LKS @%CDS_DIR%\LOBBY_CONNECT.LKS @%CDS_DIR%\RELEASE_LOBBY_CONNECT_X64.LKS
cd %OLD_DIR%
endlocal
copy Readme_lobby_connect.txt release\lobby_connect\Readme.txt

View File

@ -1,24 +1,51 @@
@echo off
cd /d "%~dp0"
del /Q /S release\*
rmdir /S /Q release\experimental
rmdir /S /Q release\experimental_steamclient
rmdir /S /Q release\lobby_connect
rmdir /S /Q release
mkdir release
call build_set_protobuf_directories.bat
SET OLD_DIR=%cd%
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT DEFINED BUILT_ALL_DEPS ( call generate_all_deps.bat )
IF EXIST build\release\x86\*.* ( DEL /F /S /Q build\release\x86\*.* )
IF EXIST build\release\x64\*.* ( DEL /F /S /Q build\release\x64\*.* )
IF EXIST release\steam_settings.EXAMPLE ( DEL /F /S /Q release\steam_settings.EXAMPLE )
IF EXIST release\*.dll ( DEL /F /Q release\*.dll )
IF EXIST release\*.txt ( DEL /F /Q release\*.txt )
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc "%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\steam_api.dll
cd %OLD_DIR%\build\release\x86
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\DLL_MAIN_CPP.BLD
IF EXIST %CDS_DIR%\RELEASE_BASE_DLL_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_BASE_DLL_X86.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_BASE_DLL_X86.LKS
echo /link /OUT:%OLD_DIR%\release\steam_api.dll >> %CDS_DIR%\RELEASE_BASE_DLL_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\steam_api.pdb >> %CDS_DIR%\RELEASE_BASE_DLL_X86.LKS )
cl /LD @%CDS_DIR%/RELEASE.LKS @%CDS_DIR%/PROTOBUF_X86.LKS @%CDS_DIR%/DLL_MAIN_CPP.LKS @%CDS_DIR%\RELEASE_BASE_DLL_X86.LKS
cd %OLD_DIR%
endlocal
setlocal
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ dll/*.cpp dll/*.cc "%PROTOBUF_X64_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\steam_api64.dll
cd %OLD_DIR%\build\release\x64
cl /c @%CDS_DIR%/RELEASE.BLD @%CDS_DIR%/PROTOBUF_X64.BLD @%CDS_DIR%/DLL_MAIN_CPP.BLD
IF EXIST %CDS_DIR%\RELEASE_BASE_DLL_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_BASE_DLL_X64.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_BASE_DLL_X64.LKS
echo /link /OUT:%OLD_DIR%\release\steam_api64.dll >> %CDS_DIR%\RELEASE_BASE_DLL_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\steam_api64.pdb >> %CDS_DIR%\RELEASE_BASE_DLL_X64.LKS )
cl /LD @%CDS_DIR%/RELEASE.LKS @%CDS_DIR%/PROTOBUF_X64.LKS @%CDS_DIR%/DLL_MAIN_CPP.LKS @%CDS_DIR%\RELEASE_BASE_DLL_X64.LKS
cd %OLD_DIR%
endlocal
copy Readme_release.txt release\Readme.txt
xcopy /s files_example\* release\
call build_win_release_experimental.bat
call build_win_release_experimental_steamclient.bat
call build_win_lobby_connect.bat
call build_win_find_interfaces.bat

View File

@ -1,17 +1,9 @@
@echo off
cd /d "%~dp0"
mkdir release\experimental
del /Q release\experimental\*
call build_set_protobuf_directories.bat
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /DNDEBUG /IImGui /I%PROTOBUF_X86_DIRECTORY%\include\ /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental\steam_api.dll
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG steamclient.cpp /EHsc /MP4 /Ox /link /OUT:release\experimental\steamclient.dll
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /DNDEBUG /IImGui /I%PROTOBUF_X64_DIRECTORY%\include\ /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental\steam_api64.dll
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG steamclient.cpp /EHsc /MP4 /Ox /link /OUT:release\experimental\steamclient64.dll
copy Readme_experimental.txt release\experimental\Readme.txt
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
SET SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD=1
SET SKIP_STEAMCLIENT_LOADER=1
call build_win_release_experimental_steamclient.bat

View File

@ -1,16 +1,141 @@
@echo off
cd /d "%~dp0"
mkdir release\experimental_steamclient
del /Q release\experimental_steamclient\*
call build_set_protobuf_directories.bat
SET OLD_DIR=%cd%
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT DEFINED BUILT_ALL_DEPS ( call generate_all_deps.bat )
IF EXIST build\experimental\steamclient\release\x86\*.* ( DEL /F /S /Q build\experimental\steamclient\release\x86\*.* )
IF EXIST build\experimental\steamclient\release\x64\*.* ( DEL /F /S /Q build\experimental\steamclient\release\x64\*.* )
IF EXIST release\experimental_steamclient\*.* ( DEL /F /S /Q release\experimental_steamclient\*.* )
setlocal
IF DEFINED SKIP_X86 GOTO LK_X64
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_OVERLAY /IImGui /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient.dll
REM Non-STEAMCLIENT_DLL release sc_deps.
cd "%OLD_DIR%\build\experimental_steamclient\release\x86\sc_deps"
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\PROTOBUF_X86.BLD @%CDS_DIR%\SC_DEPS.BLD
IF EXIST %CDS_DIR%\RELEASE_SC_DEPS_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_SC_DEPS_X86.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_SC_DEPS_X86.LKS
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_EXP_STEAMCLIENT_DLL_X86
REM Link Non-STEAMCLIENT_DLL release steam_api.dll.
cd "%OLD_DIR%\build\experimental\release\x86\"
IF EXIST %CDS_DIR%\RELEASE_STEAMAPI_NON_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMAPI_NON_X86.LKS )
echo /link /OUT:%OLD_DIR%\release\experimental\steam_api.dll > %CDS_DIR%\RELEASE_STEAMAPI_NON_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental\steam_api.pdb >> %CDS_DIR%\RELEASE_STEAMAPI_NON_X86.LKS )
cl /LD @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\PROTOBUF_X86.LKS @%CDS_DIR%\EXPERIMENTAL.BLD @%CDS_DIR%\EXPERIMENTAL.LKS @%CDS_DIR%\RELEASE_ALL_DEPS_X86.LKS @%CDS_DIR%\RELEASE_SC_DEPS_X86.LKS @%CDS_DIR%\RELEASE_STEAMAPI_NON_X86.LKS
:LK_EXP_STEAMCLIENT_DLL_X86
IF DEFINED SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD GOTO LK_STEAMCLIENT_DLL_X86
REM Link STEAMCLIENT_DLL release steamclient.dll
cd "%OLD_DIR%\build\experimental_steamclient\release\x86"
IF EXIST %CDS_DIR%\RELEASE_STEAMCLIENT_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMCLIENT_X86.LKS )
echo /link /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient.dll > %CDS_DIR%\RELEASE_STEAMCLIENT_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental_steamclient\steamclient.pdb >> %CDS_DIR%\RELEASE_STEAMCLIENT_X86.LKS )
cl /LD @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\PROTOBUF_X86.LKS @%CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS @%CDS_DIR%\RELEASE_ALL_DEPS_X86.LKS @%CDS_DIR%\RELEASE_SC_DEPS_X86.LKS @%CDS_DIR%\RELEASE_STEAMCLIENT_X86.LKS
:LK_STEAMCLIENT_DLL_X86
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_STEAMCLIENT_LOADER_X86
REM Link Non-STEAMCLIENT_DLL release steamclient.dll.
cd "%OLD_DIR%\build\experimental\release\x86\"
IF EXIST %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X86.LKS )
echo /link /OUT:%OLD_DIR%\release\experimental\steamclient.dll > %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental\steamclient.pdb >> %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X86.LKS )
cl /LD @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\STEAMCLIENT.BLD @%CDS_DIR%\RELEASE_STEAMCLIENT_NON_X86.LKS
:LK_STEAMCLIENT_LOADER_X86
IF DEFINED SKIP_STEAMCLIENT_LOADER GOTO LK_X64
REM Build steamclient_loader release x86.
cd "%OLD_DIR%\build\experimental_steamclient\steamclient_loader\release\x86"
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\STEAMCLIENT_LOADER.BLD
IF EXIST %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X86.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X86.LKS
echo /link /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient_loader_x32.exe >> %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X86.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental_steamclient\steamclient_loader_x32.pdb >> %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X86.LKS )
cl @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\STEAMCLIENT_LOADER.LKS @%CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X86.LKS
cd %OLD_DIR%
:LK_X64
endlocal
setlocal
IF DEFINED SKIP_X64 GOTO LK_END
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
cl steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient_loader.exe
copy steamclient_loader\ColdClientLoader.ini release\experimental_steamclient\
call build_env_x64.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_OVERLAY /IImGui /DNDEBUG /I%PROTOBUF_X64_DIRECTORY%\include\ /Ioverlay_experimental dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/backends/imgui_impl_dx*.cpp ImGui/backends/imgui_impl_win32.cpp ImGui/backends/imgui_impl_vulkan.cpp ImGui/backends/imgui_impl_opengl3.cpp ImGui/backends/imgui_win_shader_blobs.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp overlay_experimental/System/*.cpp "%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient64.dll
REM Non-STEAMCLIENT_DLL release sc_deps.
cd "%OLD_DIR%\build\experimental_steamclient\release\x64\sc_deps"
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\PROTOBUF_X64.BLD @%CDS_DIR%\SC_DEPS.BLD
IF EXIST %CDS_DIR%\RELEASE_SC_DEPS_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_SC_DEPS_X64.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_SC_DEPS_X64.LKS
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_EXP_STEAMCLIENT_DLL_X64
REM Link Non-STEAMCLIENT_DLL release steam_api64.dll.
cd "%OLD_DIR%\build\experimental\release\x64\"
IF EXIST %CDS_DIR%\RELEASE_STEAMAPI_NON_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMAPI_NON_X64.LKS )
echo /link /OUT:%OLD_DIR%\release\experimental\steam_api64.dll > %CDS_DIR%\RELEASE_STEAMAPI_NON_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental\steam_api64.pdb >> %CDS_DIR%\RELEASE_STEAMAPI_NON_X64.LKS )
cl /LD @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\PROTOBUF_X64.LKS @%CDS_DIR%\EXPERIMENTAL.BLD @%CDS_DIR%\EXPERIMENTAL.LKS @%CDS_DIR%\RELEASE_ALL_DEPS_X64.LKS @%CDS_DIR%\RELEASE_SC_DEPS_X64.LKS @%CDS_DIR%\RELEASE_STEAMAPI_NON_X64.LKS
:LK_EXP_STEAMCLIENT_DLL_X64
IF DEFINED SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD GOTO LK_STEAMCLIENT_DLL_X64
REM Link STEAMCLIENT_DLL release steamclient64.dll
cd "%OLD_DIR%\build\experimental_steamclient\release\x64"
IF EXIST %CDS_DIR%\RELEASE_STEAMCLIENT_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMCLIENT_X64.LKS )
echo /link /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient64.dll > %CDS_DIR%\RELEASE_STEAMCLIENT_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental_steamclient\steamclient64.pdb >> %CDS_DIR%\RELEASE_STEAMCLIENT_X64.LKS )
cl /LD @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\PROTOBUF_X64.LKS @%CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS @%CDS_DIR%\RELEASE_ALL_DEPS_X64.LKS @%CDS_DIR%\RELEASE_SC_DEPS_X64.LKS @%CDS_DIR%\RELEASE_STEAMCLIENT_X64.LKS
:LK_STEAMCLIENT_DLL_X64
IF DEFINED SKIP_EXPERIMENTAL_BUILD GOTO LK_STEAMCLIENT_LOADER_X64
REM Link Non-STEAMCLIENT_DLL release steamclient64.dll.
cd "%OLD_DIR%\build\experimental\release\x64\"
IF EXIST %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X64.LKS )
echo /link /OUT:%OLD_DIR%\release\experimental\steamclient64.dll > %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental\steamclient64.pdb >> %CDS_DIR%\RELEASE_STEAMCLIENT_NON_X64.LKS )
cl /LD @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\STEAMCLIENT.BLD @%CDS_DIR%\RELEASE_STEAMCLIENT_NON_X64.LKS
:LK_STEAMCLIENT_LOADER_X64
IF DEFINED SKIP_STEAMCLIENT_LOADER GOTO LK_END
REM Build steamclient_loader release x64.
cd "%OLD_DIR%\build\experimental_steamclient\steamclient_loader\release\x64"
cl /c @%CDS_DIR%\RELEASE.BLD @%CDS_DIR%\STEAMCLIENT_LOADER.BLD
IF EXIST %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X64.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X64.LKS
echo /link /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient_loader_x64.exe >> %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X64.LKS
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /PDB:%OLD_DIR%\release\experimental_steamclient\steamclient_loader_x64.pdb >> %CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X64.LKS )
cl @%CDS_DIR%\RELEASE.LKS @%CDS_DIR%\STEAMCLIENT_LOADER.LKS @%CDS_DIR%\RELEASE_STEAMCLIENT_LOADER_X64.LKS
cd %OLD_DIR%
:LK_END
endlocal
copy Readme_experimental.txt release\experimental\Readme.txt
copy steamclient_loader\ColdClientLoader.ini release\experimental_steamclient\
copy Readme_experimental_steamclient.txt release\experimental_steamclient\Readme.txt

View File

@ -1,4 +1,7 @@
#ifndef APPTICKET_H
#define APPTICKET_H
struct AppTicketV1
{
// Total ticket size - 16
@ -297,4 +300,6 @@ public:
return buffer;
}
};
};
#endif // APPTICKET_H

View File

@ -19,14 +19,37 @@
#ifdef __WINDOWS__
HMODULE hadvapi32 = NULL;
BOOLEAN (NTAPI *real_RtlGenRandom)(PVOID,ULONG) = NULL;
static void
randombytes(char * const buf, const size_t size)
{
while (!RtlGenRandom((PVOID) buf, (ULONG) size)) {
PRINT_DEBUG("RtlGenRandom ERROR\n");
Sleep(100);
PRINT_DEBUG("%s %p %" PRI_ZU ".\n", "mine_RtlGenRandom() called.", buf, size);
if (hadvapi32 == NULL) {
hadvapi32 = GetModuleHandleW(L"advapi32.dll");
if (hadvapi32 == NULL) {
PRINT_DEBUG("%s.\n", "GetModuleHandle() failed for advapi32.dll");
}
PRINT_DEBUG("advapi32.dll handle: 0x%p.\n", hadvapi32);
}
if (hadvapi32 != NULL &&
real_RtlGenRandom == NULL) {
real_RtlGenRandom = (BOOLEAN(NTAPI *)(PVOID,ULONG))GetProcAddress(hadvapi32, "SystemFunction036");
if (real_RtlGenRandom == NULL) {
PRINT_DEBUG("%s.\n", "GetProcAddress() failed for RtlGenRandom()");
}
PRINT_DEBUG("real_RtlGenRandom address: 0x%p.\n", real_RtlGenRandom);
}
if (real_RtlGenRandom != NULL) {
PRINT_DEBUG("%s.\n", "Calling real_RtlGenRandom");
while (!real_RtlGenRandom((PVOID) buf, (ULONG) size)) {
PRINT_DEBUG("RtlGenRandom ERROR\n");
Sleep(100);
}
PRINT_DEBUG("%s.\n", "real_RtlGenRandom returned");
}
return;
}
std::string get_env_variable(std::string name)
@ -818,16 +841,55 @@ HINTERNET WINAPI Mine_WinHttpOpenRequest(
return Real_WinHttpOpenRequest(hConnect, pwszVerb, pwszObjectName, pwszVersion, pwszReferrer, ppwszAcceptTypes, dwFlags);
}
static bool network_functions_attached = false;
std::vector<HANDLE> detours_threads;
BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
switch ( dwReason ) {
case DLL_PROCESS_ATTACH:
if (!file_exists(get_full_program_path() + "disable_lan_only.txt") && !file_exists(get_full_program_path() + "\\steam_settings\\disable_lan_only.txt")) {
PRINT_DEBUG("Hooking lan only functions\n");
DetourTransactionBegin();
DetourUpdateThread( GetCurrentThread() );
HANDLE toolHelp = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (toolHelp != INVALID_HANDLE_VALUE) {
THREADENTRY32 te;
te.dwSize = sizeof(THREADENTRY32);
if (Thread32First(toolHelp, &te)) {
bool bUpdatedThread = false;
DWORD myPID = GetCurrentProcessId();
DWORD myTID = GetCurrentThreadId();
HANDLE tHandle;
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) + sizeof(te.th32OwnerProcessID)) {
if (te.th32OwnerProcessID == myPID) {
if (te.th32ThreadID != myTID) {
tHandle = OpenThread(THREAD_ALL_ACCESS, false, te.th32ThreadID);
if (tHandle != NULL) {
PRINT_DEBUG("Hooking thread %d\n", te.th32ThreadID);
detours_threads.push_back( tHandle );
DetourUpdateThread( tHandle );
bUpdatedThread = true;
} else {
PRINT_DEBUG("Unable to hook thread %d\n", te.th32ThreadID);
}
} else {//hooking non-pseudo current thread handle is unsupported.
PRINT_DEBUG("Hooking thread %d\n", myTID);
DetourUpdateThread( GetCurrentThread() );
bUpdatedThread = true;
}
}
}
te.dwSize = sizeof(THREADENTRY32);
} while (Thread32Next(toolHelp, &te));
} else {
PRINT_DEBUG("Unable to iterate thread list, only hooking current thread\n");
DetourUpdateThread( GetCurrentThread() );
}
CloseHandle(toolHelp);
} else {
PRINT_DEBUG("Unable to get thread list, only hooking current thread\n");
DetourUpdateThread( GetCurrentThread() );
}
DetourAttach( &(PVOID &)Real_SendTo, Mine_SendTo );
DetourAttach( &(PVOID &)Real_Connect, Mine_Connect );
DetourAttach( &(PVOID &)Real_WSAConnect, Mine_WSAConnect );
@ -848,8 +910,12 @@ BOOL WINAPI DllMain( HINSTANCE, DWORD dwReason, LPVOID ) {
break;
case DLL_PROCESS_DETACH:
std::vector<HANDLE>::iterator it;
if (network_functions_attached) {
DetourTransactionBegin();
for (it = detours_threads.begin(); it != detours_threads.end(); it++) {
DetourUpdateThread( *it );
}
DetourUpdateThread( GetCurrentThread() );
DetourDetach( &(PVOID &)Real_SendTo, Mine_SendTo );
DetourDetach( &(PVOID &)Real_Connect, Mine_Connect );

View File

@ -325,12 +325,12 @@ public:
if (std::find(callbacks[iCallback].callbacks.begin(), callbacks[iCallback].callbacks.end(), cb) == callbacks[iCallback].callbacks.end()) {
callbacks[iCallback].callbacks.push_back(cb);
CCallbackMgr::SetRegister(cb, iCallback);
for (auto & res: callbacks[iCallback].results) {
//TODO: timeout?
SteamAPICall_t api_id = results->addCallResult(iCallback, &(res[0]), res.size(), 0.0, false);
results->addCallBack(api_id, cb);
}
CCallbackMgr::SetRegister(cb, iCallback);
}
}

View File

@ -65,6 +65,18 @@
#include <ntsecapi.h>
#undef SystemFunction036
#ifdef _MSC_VER
#ifndef PRIu64
#define PRIu64 "I64u"
#endif
#ifndef PRIuPTR
#define PRIuPTR "Iu"
#endif
#define PRI_ZU "Iu" // Format specifier for size_t.
#else
#include <inttypes.h>
#endif
#ifndef EMU_RELEASE_BUILD
#define PRINT_DEBUG(a, ...) do {FILE *t = fopen("STEAM_LOG.txt", "a"); fprintf(t, "%u " a, GetCurrentThreadId(), __VA_ARGS__); fclose(t); WSASetLastError(0);} while (0)
#endif
@ -74,6 +86,7 @@
#ifdef EMU_EXPERIMENTAL_BUILD
#include <winhttp.h>
#include <tlhelp32.h>
#include "../detours/detours.h"
#endif
@ -127,6 +140,15 @@ inline void reset_LastError()
#include <dlfcn.h>
#include <utime.h>
#include <inttypes.h>
#ifndef PRIu64
#define PRIu64 "I64u"
#endif
#ifndef PRIuPTR
#define PRIuPTR "Iu"
#endif
#define PRI_ZU "zu"
#define PATH_MAX_STRING_SIZE 512
#ifndef EMU_RELEASE_BUILD
@ -152,6 +174,7 @@ inline void reset_LastError()
#include <fstream>
#include <sstream>
#include <iterator>
#include <typeinfo>
#include <vector>
#include <map>
@ -203,6 +226,10 @@ inline std::string ascii_to_lowercase(std::string data) {
#define DEFAULT_LANGUAGE "english"
#define DEFAULT_UI_NOTIFICATION_POSITION "top right"
#define LOBBY_CONNECT_APPID ((uint32)-2)
#endif//__INCLUDED_COMMON_INCLUDES__
#define FRIEND_AVATAR_MAX_IMAGE_LENGTH (5 * 1024 * 1024)
#endif//__INCLUDED_COMMON_INCLUDES__

View File

@ -17,7 +17,9 @@
#define STEAM_API_FUNCTIONS_IMPL
#include "dll.h"
#ifdef STEAM_WIN32
#include <DbgHelp.h>
#endif
static char old_client[128] = "SteamClient017";
static char old_gameserver[128] = "SteamGameServer012";
@ -140,6 +142,16 @@ Steam_Client *get_steam_client()
return steamclient_instance;
}
Steam_Client *try_get_steam_client()
{
Steam_Client * ret = NULL;
if (global_mutex.try_lock() == true) {
ret = steamclient_instance;
global_mutex.unlock();
}
return ret;
}
void destroy_client()
{
std::lock_guard<std::recursive_mutex> lock(global_mutex);
@ -234,6 +246,40 @@ STEAMAPI_API void * S_CALLTYPE SteamInternal_ContextInit( void *pContextInitData
return &contextInitData->ctx;
}
static std::mutex minidump_global_mutex;
static bool minidump_enable = true;
static bool minidump_comment_enable = true;
static std::string minidump_comment;
static std::string minidump_path;
static std::string start_time;
bool get_minidump_enable() {
std::lock_guard<std::mutex> lock(minidump_global_mutex);
return minidump_enable;
}
bool get_minidump_comment_enable() {
std::lock_guard<std::mutex> lock(minidump_global_mutex);
return minidump_comment_enable;
}
void set_minidump_enable(bool enable) {
std::lock_guard<std::mutex> lock(minidump_global_mutex);
minidump_enable = enable;
return;
}
void set_minidump_comment_enable(bool enable) {
std::lock_guard<std::mutex> lock(minidump_global_mutex);
minidump_comment_enable = enable;
return;
}
std::string get_start_time() {
std::lock_guard<std::mutex> lock(minidump_global_mutex);
return start_time;
}
//steam_api.h
// SteamAPI_Init must be called before using any other API functions. If it fails, an
// error message will be output to the debugger (or stderr) with further information.
@ -242,6 +288,11 @@ STEAMAPI_API steam_bool S_CALLTYPE SteamAPI_Init()
{
PRINT_DEBUG("SteamAPI_Init called\n");
if (user_steam_pipe) return true;
{
std::lock_guard<std::mutex> lock(minidump_global_mutex);
if (start_time.length() <= 0) start_time = std::to_string((std::chrono::duration_cast<std::chrono::seconds>(((std::chrono::system_clock::now()).time_since_epoch()))).count());
if (minidump_path.length() <= 0) minidump_path = Local_Storage::get_user_appdata_path().append(PATH_SEPARATOR).append("minidumps").append(PATH_SEPARATOR).append("steam_minidump_").append(start_time).append(".mdmp");
}
#ifdef EMU_EXPERIMENTAL_BUILD
crack_SteamAPI_Init();
#endif
@ -330,6 +381,11 @@ STEAMAPI_API void S_CALLTYPE SteamAPI_Shutdown()
STEAMAPI_API steam_bool S_CALLTYPE SteamAPI_RestartAppIfNecessary( uint32 unOwnAppID )
{
PRINT_DEBUG("SteamAPI_RestartAppIfNecessary %u\n", unOwnAppID);
{
std::lock_guard<std::mutex> lock(minidump_global_mutex);
if (start_time.length() <= 0) start_time = std::to_string((std::chrono::duration_cast<std::chrono::seconds>(((std::chrono::system_clock::now()).time_since_epoch()))).count());
if (minidump_path.length() <= 0) minidump_path = Local_Storage::get_user_appdata_path().append(PATH_SEPARATOR).append("minidumps").append(PATH_SEPARATOR).append("steam_minidump_").append(start_time).append(".mdmp");
}
#ifdef EMU_EXPERIMENTAL_BUILD
crack_SteamAPI_RestartAppIfNecessary(unOwnAppID);
#endif
@ -350,11 +406,93 @@ STEAMAPI_API void S_CALLTYPE SteamAPI_ReleaseCurrentThreadMemory()
STEAMAPI_API void S_CALLTYPE SteamAPI_WriteMiniDump( uint32 uStructuredExceptionCode, void* pvExceptionInfo, uint32 uBuildID )
{
PRINT_DEBUG("SteamAPI_WriteMiniDump\n");
#ifdef STEAM_WIN32
if (!get_minidump_enable())
return;
std::lock_guard<std::mutex> lock(minidump_global_mutex);
MINIDUMP_EXCEPTION_INFORMATION mei;
memset(&mei, '\0', sizeof(MINIDUMP_EXCEPTION_INFORMATION));
mei.ThreadId = GetCurrentThreadId();
mei.ExceptionPointers = (EXCEPTION_POINTERS*)pvExceptionInfo;
mei.ClientPointers = false;
char expCode[40] = {'S', 't', 'r', 'u', 'c', 't', 'u', 'r', 'e', 'd', ' ',
'E', 'x', 'c', 'e', 'p', 't', 'i', 'o', 'n', ' ',
'C', 'o', 'd', 'e', ':', ' ',
'4', '2', '9', '4', '9', '6', '7', '2', '9', '5', '\0', '\0'};
char * printExpCode = &expCode[26];
snprintf(printExpCode, (39 - 26), "%u", uStructuredExceptionCode);
char buildId[25] = { 'B', 'u', 'i', 'l', 'd', ' ',
'I', 'D', ':', ' ',
'4', '2', '9', '4', '9', '6', '7', '2', '9', '5', '\0', '\0', '\0', '\0', '\0'};
char * printBuildId = &expCode[10];
snprintf(printBuildId, (24 - 10), "%u", uBuildID);
MINIDUMP_USER_STREAM mus[3];
memset(&mus, '\0', sizeof(MINIDUMP_USER_STREAM) * 3);
mus[0].Type = CommentStreamA;
mus[0].BufferSize = 40;
mus[0].Buffer = (void*)&expCode;
mus[1].Type = CommentStreamA;
mus[1].BufferSize = 25;
mus[1].Buffer = (void*)&buildId;
mus[2].BufferSize = minidump_comment.length();
if (minidump_comment.length() > 0) {
mus[2].Type = CommentStreamA;
mus[2].BufferSize = minidump_comment.length();
if (mus[2].BufferSize > 0) {
mus[2].Buffer = (void*)minidump_comment.c_str();
}
}
MINIDUMP_USER_STREAM_INFORMATION musi;
memset(&musi, '\0', sizeof(MINIDUMP_USER_STREAM_INFORMATION));
musi.UserStreamCount = (minidump_comment.length() > 0) ? 3 : 2;
musi.UserStreamArray = (MINIDUMP_USER_STREAM*)&mus;
if (minidump_path.length() > 0) {
HANDLE hFile = CreateFile(minidump_path.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hFile != INVALID_HANDLE_VALUE) {
MiniDumpWriteDump(GetCurrentProcess(),
GetCurrentProcessId(),
hFile,
(MINIDUMP_TYPE)(MiniDumpWithFullMemory | MiniDumpWithProcessThreadData | MiniDumpWithThreadInfo | MiniDumpWithUnloadedModules | MiniDumpWithTokenInformation),
((pvExceptionInfo != NULL) ? &mei : NULL),
&musi,
NULL);
CloseHandle(hFile);
}
}
#endif
return;
}
STEAMAPI_API void S_CALLTYPE SteamAPI_SetMiniDumpComment( const char *pchMsg )
{
PRINT_DEBUG("SteamAPI_SetMiniDumpComment: %s\n", pchMsg);
if (get_minidump_enable() == false || get_minidump_comment_enable() == false)
return;
std::lock_guard<std::mutex> lock(minidump_global_mutex);
if (pchMsg != NULL) {
PRINT_DEBUG("SteamAPI_SetMiniDumpComment: %s\n", pchMsg);
minidump_comment = std::string(pchMsg);
} else {
PRINT_DEBUG("SteamAPI_SetMiniDumpComment: Empty string.\n");
minidump_comment.clear();
}
return;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------------//

141
dll/dll.h
View File

@ -27,8 +27,149 @@
Steam_Client *get_steam_client();
bool steamclient_has_ipv6_functions();
Steam_Client *try_get_steam_client();
bool get_minidump_enable();
bool get_minidump_comment_enable();
void set_minidump_enable(bool enable);
void set_minidump_comment_enable(bool enable);
std::string get_start_time();
HSteamUser flat_hsteamuser();
HSteamPipe flat_hsteampipe();
HSteamUser flat_gs_hsteamuser();
HSteamPipe flat_gs_hsteampipe();
#define GOLDBERG_CALLBACK_INTERNAL(parent, fname, cb_type) \
struct GB_CCallbackInternal_ ## fname : private GB_CCallbackInterImp< sizeof(cb_type) > { \
public: \
GB_CCallbackInternal_ ## fname () { \
PRINT_DEBUG("GB_CCallbackInternal_%s::%s %s 0x%p.\n", \
#fname, \
#fname, \
"Default constructor", \
this); \
this->reg_thread_has_run = false; \
std::thread th = std::thread(GB_CCallbackInterImp::_register, this, cb_type::k_iCallback); \
th.detach(); \
} \
GB_CCallbackInternal_ ## fname ( const GB_CCallbackInternal_ ## fname & a ) { \
PRINT_DEBUG("GB_CCallbackInternal_%s::%s %s 0x%p.\n", \
#fname, \
#fname, \
"Copy constructor", \
this); \
this->reg_thread_has_run = false; \
std::thread th = std::thread(GB_CCallbackInterImp::_register, this, cb_type::k_iCallback); \
th.detach(); \
} \
GB_CCallbackInternal_ ## fname & operator=(const GB_CCallbackInternal_ ## fname &) { \
PRINT_DEBUG("GB_CCallbackInternal_%s::%s %s 0x%p.\n", \
#fname, \
#fname, \
"Assignment = operator", \
this); \
return *this; \
} \
virtual void Run(void *callback) { \
PRINT_DEBUG("GB_CCallbackInternal_%s::Run 0x%p Callback argument: 0x%p.\n", \
#fname, \
this, \
callback); \
if (m_nCallbackFlags & k_ECallbackFlagsRegistered) { \
parent *obj = reinterpret_cast<parent*>(reinterpret_cast<char*>(this) - offsetof(parent, m_steamcallback_ ## fname)); \
obj->fname(reinterpret_cast<cb_type*>(callback)); \
} \
} \
bool isRegistered() { \
return ( m_nCallbackFlags & k_ECallbackFlagsRegistered ); \
} \
private: \
} m_steamcallback_ ## fname ; \
void fname(cb_type *callback) ; \
bool cb_type ## _is_registered() { \
return m_steamcallback_ ## fname.isRegistered(); \
}
template<int sizeof_cb_type>
class GB_CCallbackInterImp : protected CCallbackBase
{
public:
virtual ~GB_CCallbackInterImp() {
_unregister(this);
return;
}
void SetGameserverFlag() {
m_nCallbackFlags |= k_ECallbackFlagsGameServer;
return;
}
protected:
friend class CCallbackMgr;
std::atomic<bool> reg_thread_has_run;
virtual void Run(void *callback) = 0;
virtual void Run(void *callback, bool io_failure, SteamAPICall_t api_fp) {
Run(callback);
return;
}
virtual int GetCallbackSizeBytes() {
return sizeof_cb_type;
}
static void _register(void * arg, int callback) {
GB_CCallbackInterImp * gb = (GB_CCallbackInterImp *)arg;
if (gb != NULL) {
PRINT_DEBUG("GB_CCallbackInterImp::_register Begin registration thread for 0x%p callback %d.\n",
gb,
callback);
if (!(gb->m_nCallbackFlags & k_ECallbackFlagsRegistered)) {
bool ready = false;
do {
if (global_mutex.try_lock() == true) {
Steam_Client * client = try_get_steam_client();
if (client != NULL) {
client->RegisterCallback(gb, callback);
ready = true;
gb->reg_thread_has_run = true;
PRINT_DEBUG("GB_CCallbackInterImp::_register Registration complete for 0x%p callback %d.\n",
gb,
callback);
}
global_mutex.unlock();
}
} while (!ready);
}
PRINT_DEBUG("GB_CCallbackInterImp::_register Exiting registration thread for 0x%p callback %d.\n",
gb,
callback);
}
return;
}
static void _unregister(void * arg) {
GB_CCallbackInterImp * gb = (GB_CCallbackInterImp *)arg;
if (gb != NULL) {
PRINT_DEBUG("GB_CCallbackInterImp::_unregister Begin deregistration thread for 0x%p.\n",
gb);
bool can_dereg = false;
do {
can_dereg = gb->reg_thread_has_run;
} while (!can_dereg);
if (gb->m_nCallbackFlags & k_ECallbackFlagsRegistered) {
bool ready = false;
do {
if (global_mutex.try_lock() == true) {
Steam_Client * client = try_get_steam_client();
if (client != NULL) {
client->UnregisterCallback(gb);
ready = true;
PRINT_DEBUG("GB_CCallbackInterImp::_unregister Deregistration complete for 0x%p.\n",
gb);
}
global_mutex.unlock();
}
} while (!ready);
PRINT_DEBUG("GB_CCallbackInterImp::_unregister Exiting deregistration thread for 0x%p.\n",
gb);
}
}
return;
}
};

View File

@ -34,18 +34,180 @@ struct File_Data {
std::string name;
};
std::string convert_vector_image_pixel_t_to_std_string(std::vector<image_pixel_t> in) {
std::string out;
for (auto i : in) {
out += i.channels.r;
out += i.channels.g;
out += i.channels.b;
out += i.channels.a;
}
return out;
}
struct our_stbi_buffer {
uint8 * target;
size_t target_length;
size_t current_offset;
};
void our_stbi_write_func(void *context, void *data, int size) {
struct our_stbi_buffer * con = (struct our_stbi_buffer *)context;
uint8 * in_data = (uint8 *)data;
if (in_data != NULL &&
con != NULL &&
con->target != NULL &&
con->target_length > 0 &&
con->current_offset < con->target_length &&
(con->current_offset + size) < con->target_length) {
for (size_t x = 0; (x < size && (con->current_offset + x) < con->target_length); x++) {
con->target[(con->current_offset + x)] = in_data[x];
}
con->current_offset += size;
}
return;
}
std::string convert_raw_uint8_to_png_std_string(uint8 * in, int width, int height, int components) {
struct our_stbi_buffer buf;
std::string out;
out.clear();
if (in != NULL && width > 0 && height > 0 && components > 0 && components <= 4) {
buf.target_length = (width * height * components);
buf.current_offset = 0;
buf.target = new uint8[(width * height * components)];
if (buf.target != NULL) {
if (stbi_write_png_to_func(our_stbi_write_func, &buf, width, height, components, in, 0) == 1) {
for (size_t x = 0; x < (width * height * components); x++) {
char a = (char)buf.target[x];
out += a;
}
}
delete buf.target;
buf.target = NULL;
}
buf.target_length = 0;
buf.current_offset = 0;
}
return out;
}
std::string convert_raw_uint8_to_jpg_std_string(uint8 * in, int width, int height, int components) {
struct our_stbi_buffer buf;
std::string out;
out.clear();
if (in != NULL && width > 0 && height > 0 && components > 0 && components <= 4) {
buf.target_length = (width * height * components);
buf.current_offset = 0;
buf.target = new uint8[(width * height * components)];
if (buf.target != NULL) {
if (stbi_write_jpg_to_func(our_stbi_write_func, &buf, width, height, components, in, 0) == 1) {
for (size_t x = 0; x < (width * height * components); x++) {
char a = (char)buf.target[x];
out += a;
}
}
delete buf.target;
buf.target = NULL;
}
buf.target_length = 0;
buf.current_offset = 0;
}
return out;
}
std::string convert_imgbuf_std_string_to_std_string_uint8(std::string in,
int * out_width,
int * out_height,
int * out_components,
int desired_components) {
std::string out;
out.clear();
int w = 0;
int h = 0;
int c = 0;
if (in.length() > 0 &&
desired_components > 0 &&
desired_components <= 4) {
uint8 * buf = (uint8*)stbi_load_from_memory((stbi_uc *)in.c_str(), in.length(), &w, &h, &c, desired_components);
if (buf != NULL) {
if (w > 0 && h > 0 && desired_components > 0) {
for (size_t x = 0; x < (w * h * desired_components); x++) {
char a = buf[x];
out += a;
}
}
if (out_width != NULL) {
*out_width = w;
}
if (out_height != NULL) {
*out_height = h;
}
if (out_components != NULL) {
*out_components = c;
}
stbi_image_free(buf);
} else {
out.clear();
if (out_width != NULL) {
*out_width = 0;
}
if (out_height != NULL) {
*out_height = 0;
}
if (out_components != NULL) {
*out_components = 0;
}
PRINT_DEBUG("%s %p. reason: %s\n", "Failed to decode image at", &in, stbi_failure_reason());
}
}
return out;
}
std::string convert_png_buffer_std_string_to_std_string_uint8(std::string in, int * width, int * height, int * components, int desired_components) {
return convert_imgbuf_std_string_to_std_string_uint8(in, width, height, components, desired_components);
}
std::string convert_jpg_buffer_std_string_to_std_string_uint8(std::string in, int * width, int * height, int * components, int desired_components) {
return convert_imgbuf_std_string_to_std_string_uint8(in, width, height, components, desired_components);
}
#ifdef NO_DISK_WRITES
std::string Local_Storage::get_program_path()
{
return " ";
}
std::string Local_Storage::get_user_pictures_path()
{
return " ";
}
std::string Local_Storage::get_user_appdata_path()
{
return " ";
}
bool Local_Storage::is_directory(std::string &path)
{
return false;
}
std::string Local_Storage::get_parent_directory(std::string &path)
{
return " ";
}
std::string Local_Storage::get_game_settings_path()
{
return " ";
@ -71,7 +233,7 @@ void Local_Storage::setAppId(uint32 appid)
}
int Local_Storage::store_file_data(std::string folder, std::string file, char *data, unsigned int length)
int Local_Storage::store_file_data(std::string folder, std::string file, const char *data, unsigned int length)
{
return -1;
}
@ -81,7 +243,7 @@ int Local_Storage::store_data(std::string folder, std::string file, char *data,
return -1;
}
int Local_Storage::store_data_settings(std::string file, char *data, unsigned int length)
int Local_Storage::store_data_settings(std::string file, const char *data, unsigned int length)
{
return -1;
}
@ -111,6 +273,11 @@ bool Local_Storage::file_exists(std::string folder, std::string file)
return false;
}
bool Local_Storage::data_settings_exists(std::string file)
{
return false;
}
unsigned int Local_Storage::file_size(std::string folder, std::string file)
{
return 0;
@ -121,6 +288,11 @@ bool Local_Storage::file_delete(std::string folder, std::string file)
return false;
}
bool Local_Storage::delete_data_settings(std::string file)
{
return false;
}
uint64_t Local_Storage::file_timestamp(std::string folder, std::string file)
{
return 0;
@ -156,7 +328,7 @@ std::vector<std::string> Local_Storage::get_filenames_path(std::string path)
return std::vector<std::string>();
}
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path)
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path, uint32_t * out_width, uint32_t * out_height)
{
return std::vector<image_pixel_t>();
}
@ -272,6 +444,29 @@ static std::vector<struct File_Data> get_filenames_recursive(std::string base_pa
#else
static bool DirectoryExists(const char *path) {
char tmp[PATH_MAX_STRING_SIZE];
struct stat sb;
size_t len;
/* copy path */
len = strnlen (path, PATH_MAX_STRING_SIZE);
if (len == 0 || len == PATH_MAX_STRING_SIZE) {
return false;
}
memcpy (tmp, path, len);
tmp[len] = '\0';
/* check if path exists and is a directory */
if (stat (tmp, &sb) == 0) {
if (S_ISDIR (sb.st_mode)) {
return true;
}
}
return false;
}
/* recursive mkdir */
static int mkdir_p(const char *dir, const mode_t mode) {
char tmp[PATH_MAX_STRING_SIZE];
@ -410,6 +605,26 @@ std::string Local_Storage::get_game_settings_path()
return get_program_path().append(game_settings_folder).append(PATH_SEPARATOR);
}
std::string Local_Storage::get_user_pictures_path() {
std::string user_pictures_path = "Pictures";
#if defined(STEAM_WIN32)
WCHAR szPath[MAX_PATH] = {};
HRESULT hr = SHGetFolderPathW(NULL, CSIDL_MYPICTURES, NULL, 0, szPath);
if (SUCCEEDED(hr)) {
user_pictures_path = utf8_encode(szPath);
}
#else
char *datadir = getenv("HOME");
if (datadir) {
user_pictures_path = datadir;
}
#endif
return user_pictures_path;
}
std::string Local_Storage::get_user_appdata_path()
{
std::string user_appdata_path = "SAVE";
@ -492,12 +707,77 @@ Local_Storage::Local_Storage(std::string save_directory)
}
}
std::string Local_Storage::get_parent_directory(std::string &path)
{
std::string ret = "";
std::string temp = "";
ret = sanitize_file_name(path);
if (ret.length() > 1) {
temp = ret[(ret.length() - 1)];
if (temp == PATH_SEPARATOR) {
ret.erase((ret.length() - 1), 1);
}
}
if (ret.length() > 1) {
size_t last_pos = 0;
size_t count = 0;
for (auto i : ret) {
temp = i;
if (temp == PATH_SEPARATOR) {
last_pos = count;
}
count = count + 1;
}
if ((last_pos > 0) && (last_pos < (count - 1))) {
ret.erase(last_pos, (count - 1));
}
}
ret = desanitize_file_name(ret);
return ret;
}
bool Local_Storage::is_directory(std::string &path)
{
bool ret = false;
#if defined(STEAM_WIN32)
std::wstring strPath = utf8_decode(path);
ret = DirectoryExists(strPath.c_str());
#else
ret = DirectoryExists(path.c_str());
#endif
return ret;
}
std::vector<std::string> Local_Storage::get_drive_list()
{
std::vector<std::string> ret;
#if defined(STEAM_WIN32)
DWORD drives = GetLogicalDrives();
if (drives != 0) {
for (unsigned int x = 0; x < 26; x++) {
if (drives & (((DWORD)0x1) << x)) {
char tmp[2] = { 'A' + (char)x, '\0' };
ret.push_back(std::string(tmp) + ":");
}
}
}
#else
//TODO: Parse /proc/self/mountinfo
ret.push_back("/");
#endif
return ret;
}
void Local_Storage::setAppId(uint32 appid)
{
this->appid = std::to_string(appid) + PATH_SEPARATOR;
}
int Local_Storage::store_file_data(std::string folder, std::string file, char *data, unsigned int length)
int Local_Storage::store_file_data(std::string folder, std::string file, const char *data, unsigned int length)
{
if (folder.back() != *PATH_SEPARATOR) {
folder.append(PATH_SEPARATOR);
@ -556,11 +836,62 @@ int Local_Storage::store_data(std::string folder, std::string file, char *data,
return store_file_data(save_directory + appid + folder, file, data, length);
}
int Local_Storage::store_data_settings(std::string file, char *data, unsigned int length)
int Local_Storage::store_data_settings(std::string file, const char *data, unsigned int length)
{
return store_file_data(get_global_settings_path(), file, data, length);
}
int Local_Storage::copy_file_data(std::string src_full_path, std::string dest_full_path)
{
std::ifstream srcfile;
std::ofstream destfile;
char * buf = NULL;
size_t readcount = 0;
const size_t bufsize = 1024;
bool fail = false;
buf = new char[bufsize];
if (buf == NULL) return -1;
srcfile.open(utf8_decode(src_full_path), std::ios::binary | std::ios::in);
if (!srcfile.is_open()) {
delete buf;
buf = NULL;
return -1;
}
destfile.open(utf8_decode(dest_full_path), std::ios::binary | std::ios::out);
if (!destfile.is_open()) {
delete buf;
buf = NULL;
srcfile.close();
return -1;
}
srcfile.seekg(0, std::ios::beg);
destfile.seekp(0, std::ios::beg);
do {
buf[readcount] = srcfile.get();
if (srcfile.eof() || (readcount + 1) == bufsize) {
destfile.write(buf, (readcount + 1));
readcount = 0;
} else {
readcount++;
}
if (srcfile.fail() || destfile.fail()) {
fail = true;
}
} while (srcfile.eof() == false && srcfile.fail() == false && destfile.fail() == false);
srcfile.close();
destfile.close();
reset_LastError();
delete buf;
buf = NULL;
return (!fail) ? 1 : 0;
}
int Local_Storage::get_file_data(std::string full_path, char *data, unsigned int max_length, unsigned int offset)
{
std::ifstream myfile;
@ -612,6 +943,14 @@ bool Local_Storage::file_exists(std::string folder, std::string file)
return file_exists_(full_path);
}
bool Local_Storage::data_settings_exists(std::string file)
{
file = sanitize_file_name(file);
std::string full_path = get_global_settings_path() + file;
return file_exists_(full_path);
}
unsigned int Local_Storage::file_size(std::string folder, std::string file)
{
file = sanitize_file_name(file);
@ -623,6 +962,23 @@ unsigned int Local_Storage::file_size(std::string folder, std::string file)
return file_size_(full_path);
}
unsigned int Local_Storage::data_settings_size(std::string file)
{
file = sanitize_file_name(file);
std::string full_path = get_global_settings_path() + file;
return file_size_(full_path);
}
bool _internal_file_delete(std::string & full_path)
{
#if defined(STEAM_WIN32)
return _wremove(utf8_decode(full_path).c_str()) == 0;
#else
return remove(full_path.c_str()) == 0;
#endif
}
bool Local_Storage::file_delete(std::string folder, std::string file)
{
file = sanitize_file_name(file);
@ -631,11 +987,15 @@ bool Local_Storage::file_delete(std::string folder, std::string file)
}
std::string full_path = save_directory + appid + folder + file;
#if defined(STEAM_WIN32)
return _wremove(utf8_decode(full_path).c_str()) == 0;
#else
return remove(full_path.c_str()) == 0;
#endif
return _internal_file_delete(full_path);
}
bool Local_Storage::delete_data_settings(std::string file)
{
file = sanitize_file_name(file);
std::string full_path = get_global_settings_path() + file;
return _internal_file_delete(full_path);
}
uint64_t Local_Storage::file_timestamp(std::string folder, std::string file)
@ -717,7 +1077,7 @@ bool Local_Storage::load_json(std::string full_path, nlohmann::json& json)
try {
json = std::move(nlohmann::json::parse(buffer));
PRINT_DEBUG("Loaded json \"%s\". Loaded %u items.\n", full_path.c_str(), json.size());
PRINT_DEBUG("Loaded json \"%s\". Loaded %" PRI_ZU " items.\n", full_path.c_str(), json.size());
return true;
} catch (std::exception& e) {
PRINT_DEBUG("Error while parsing \"%s\" json: %s\n", full_path.c_str(), e.what());
@ -766,10 +1126,11 @@ bool Local_Storage::write_json_file(std::string folder, std::string const&file,
return false;
}
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path)
std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_path, uint32_t * out_width, uint32_t * out_height)
{
std::vector<image_pixel_t> res;
int width, height;
int32_t width = 0;
int32_t height = 0;
image_pixel_t* img = (image_pixel_t*)stbi_load(image_path.c_str(), &width, &height, nullptr, 4);
if (img != nullptr)
{
@ -777,12 +1138,76 @@ std::vector<image_pixel_t> Local_Storage::load_image(std::string const& image_pa
std::copy(img, img + width * height, res.begin());
stbi_image_free(img);
} else {
width = 0;
height = 0;
PRINT_DEBUG("%s %s. reason: %s\n", "Failed to load image at", image_path.c_str(), stbi_failure_reason());
}
if (out_width != nullptr) {
if (width > 0) {
*out_width = static_cast<uint32_t>(width);
} else {
*out_width = 0;
}
}
if (out_height != nullptr) {
if (height > 0) {
*out_height = static_cast<uint32_t>(height);
} else {
*out_height = 0;
}
}
reset_LastError();
return res;
}
int32_t Local_Storage::save_avatar_image(int32_t eAvatarSize, int32_t width, int32_t height, uint8_t * img_ptr)
{
int32_t ret = 0;
std::string image_path = "";
switch (eAvatarSize) {
case k_EAvatarSize32x32:
if (width > 0 &&
width <= 32 &&
height > 0 &&
height <= 32) {
image_path += "avatar_small.";
}
break;
case k_EAvatarSize64x64:
if (width > 32 &&
width <= 64 &&
height > 32 &&
height <= 64) {
image_path += "avatar_medium.";
}
break;
case k_EAvatarSize184x184:
if (width > 64 &&
width <= 184 &&
height > 64 &&
height <= 184) {
image_path += "avatar_large.";
}
break;
case k_EAvatarSizeMAX:
default:
image_path.clear();
break;
};
if (image_path.length() > 0 && img_ptr != NULL) {
delete_data_settings(image_path + "jpg");
image_path += "png";
delete_data_settings(image_path);
image_path = get_global_settings_path() + image_path;
ret = (stbi_write_png(image_path.c_str(), width, height, 4, img_ptr, 0) == 1);
}
return ret;
}
bool Local_Storage::save_screenshot(std::string const& image_path, uint8_t* img_ptr, int32_t width, int32_t height, int32_t channels)
{
std::string screenshot_path = std::move(save_directory + appid + screenshots_folder + PATH_SEPARATOR);

View File

@ -41,6 +41,13 @@ struct image_t
std::vector<image_pixel_t> pix_map;
};
std::string convert_vector_image_pixel_t_to_std_string(std::vector<image_pixel_t> in);
std::string convert_raw_uint8_to_png_std_string(uint8 * in, int width, int height, int components);
std::string convert_raw_uint8_to_jpg_std_string(uint8 * in, int width, int height, int components);
std::string convert_png_buffer_std_string_to_std_string_uint8(std::string in, int * width, int * height, int * components, int desired_components);
std::string convert_jpg_buffer_std_string_to_std_string_uint8(std::string in, int * width, int * height, int * components, int desired_components);
class Local_Storage {
public:
static constexpr auto inventory_storage_folder = "inventory";
@ -58,22 +65,30 @@ private:
public:
static std::string get_program_path();
static std::string get_game_settings_path();
static std::string get_user_pictures_path();
static std::string get_user_appdata_path();
static std::string get_parent_directory(std::string &path);
static std::vector<std::string> get_drive_list();
static bool is_directory(std::string &path);
Local_Storage(std::string save_directory);
static int get_file_data(std::string full_path, char *data, unsigned int max_length, unsigned int offset=0);
static int copy_file_data(std::string src_full_path, std::string dest_full_path);
void setAppId(uint32 appid);
static int store_file_data(std::string folder, std::string file, char *data, unsigned int length);
static int store_file_data(std::string folder, std::string file, const char *data, unsigned int length);
static std::vector<std::string> get_filenames_path(std::string path);
int store_data(std::string folder, std::string file, char *data, unsigned int length);
int store_data_settings(std::string file, char *data, unsigned int length);
int store_data_settings(std::string file, const char *data, unsigned int length);
int get_data(std::string folder, std::string file, char *data, unsigned int max_length, unsigned int offset=0);
int get_data_settings(std::string file, char *data, unsigned int max_length);
int count_files(std::string folder);
bool iterate_file(std::string folder, int index, char *output_filename, int32 *output_size);
bool file_exists(std::string folder, std::string file);
bool data_settings_exists(std::string file);
unsigned int file_size(std::string folder, std::string file);
unsigned int data_settings_size(std::string file);
bool file_delete(std::string folder, std::string file);
bool delete_data_settings(std::string file);
uint64_t file_timestamp(std::string folder, std::string file);
std::string get_global_settings_path();
std::string get_path(std::string folder);
@ -84,7 +99,8 @@ public:
bool load_json_file(std::string folder, std::string const& file, nlohmann::json& json);
bool write_json_file(std::string folder, std::string const& file, nlohmann::json const& json);
std::vector<image_pixel_t> load_image(std::string const& image_path);
std::vector<image_pixel_t> load_image(std::string const& image_path, uint32_t * out_width, uint32_t * out_height);
int32_t save_avatar_image(int32_t eAvatarSize, int32_t width, int32_t height, uint8_t * img_ptr);
bool save_screenshot(std::string const& image_path, uint8_t* img_ptr, int32_t width, int32_t height, int32_t channels);
};

View File

@ -179,6 +179,31 @@ message Friend {
uint64 lobby_id = 5;
}
message Image {
enum MessageTypes {
REQUEST = 0;
NOTIFY = 1;
}
enum ImgTypes {
RAW = 0;
JPG = 1;
PNG = 2;
GIF = 3;
}
MessageTypes type = 1;
ImgTypes img_type = 2;
uint32 img_width = 3;
uint32 img_height = 4;
uint32 img_components = 5;
bytes img_data = 6;
}
message Friend_Avatar {
Image img = 1;
}
message Auth_Ticket {
uint32 number = 1;
@ -230,6 +255,7 @@ message Common_Message {
Networking_Sockets networking_sockets = 13;
Steam_Messages steam_messages = 14;
Networking_Messages networking_messages = 15;
Friend_Avatar friend_avatar = 16;
}
uint32 source_ip = 128;

View File

@ -513,7 +513,7 @@ std::set<IP_PORT> Networking::resolve_ip(std::string dns)
if (getaddrinfo(dns.c_str(), NULL, NULL, &result) == 0) {
for (struct addrinfo *res = result; res != NULL; res = res->ai_next) {
PRINT_DEBUG("%u %u\n", res->ai_addrlen, res->ai_family);
PRINT_DEBUG("%" PRI_ZU " %u\n", res->ai_addrlen, res->ai_family);
if (res->ai_family == AF_INET) {
struct sockaddr_in *ipv4 = (struct sockaddr_in *)res->ai_addr;
uint32 ip;
@ -524,6 +524,7 @@ std::set<IP_PORT> Networking::resolve_ip(std::string dns)
ips.insert(addr);
}
}
freeaddrinfo(result);
}
return ips;
@ -580,6 +581,11 @@ void Networking::do_callbacks_message(Common_Message *msg)
PRINT_DEBUG("has_networking_messages\n");
run_callbacks(CALLBACK_ID_NETWORKING_MESSAGES, msg);
}
if (msg->has_friend_avatar()) {
PRINT_DEBUG("has_friend_avatar\n");
run_callbacks(CALLBACK_ID_FRIEND_AVATAR, msg);
}
}
bool Networking::handle_tcp(Common_Message *msg, struct TCP_Socket &socket)

View File

@ -61,6 +61,7 @@ enum Callback_Ids {
CALLBACK_ID_NETWORKING_SOCKETS,
CALLBACK_ID_STEAM_MESSAGES,
CALLBACK_ID_NETWORKING_MESSAGES,
CALLBACK_ID_FRIEND_AVATAR,
CALLBACK_IDS_MAX
};

View File

@ -1,4 +0,0 @@
#include <windows.h>
#define RtlGenRandom SystemFunction036
#define DLLEXPORT __declspec(dllexport)
DLLEXPORT BOOLEAN WINAPI RtlGenRandom(PVOID in, ULONG len) {}

View File

@ -1,3 +0,0 @@
LIBRARY advapi32.dll
EXPORTS
SystemFunction036

View File

@ -16,7 +16,7 @@
<http://www.gnu.org/licenses/>. */
#include "settings.h"
#include "dll.h"
std::string Settings::sanitize(std::string name)
{
@ -45,6 +45,10 @@ Settings::Settings(CSteamID steam_id, CGameID game_id, std::string name, std::st
this->name = this->name + " ";
}
this->settings_parser_done = false;
this->ui_notification_position = "";
auto lang = sanitize(language);
std::transform(lang.begin(), lang.end(), lang.begin(), ::tolower);
lang.erase(std::remove(lang.begin(), lang.end(), ' '), lang.end());
@ -54,6 +58,28 @@ Settings::Settings(CSteamID steam_id, CGameID game_id, std::string name, std::st
this->offline = offline;
this->create_unknown_leaderboards = true;
this->next_free = 1;
this->preferred_network_image_type = Image::JPG;
this->background_thread_exit = false;
PRINT_DEBUG("%s.\n", "Settings::Settings Creating new background_monitor thread");
background_monitor_thread = std::thread(Settings::background_monitor_entry, this);
}
Settings::~Settings()
{
bool wait = false;
{
std::lock_guard<std::recursive_mutex> lock(background_thread_mutex);
if (background_monitor_thread.joinable()) {
background_thread_exit = true;
wait = true;
}
}
if (wait) {
background_monitor_thread.join();
}
}
CSteamID Settings::get_local_steam_id()
@ -214,13 +240,305 @@ void Settings::setLeaderboard(std::string leaderboard, enum ELeaderboardSortMeth
leaderboards[leaderboard] = leader;
}
int Settings::find_next_free_image_ref() {
int ret = 0;
std::lock_guard<std::recursive_mutex> lock(images_mutex);
if (images.size() == 0) {
ret = 1;
} else {
for (auto x : images) {
auto y = images.upper_bound(x.first);
if (y == images.end()) {
if ((x.first + 1) == 0) {
ret = 1;
break;
} else {
ret = x.first + 1;
break;
}
} else {
if ((x.first + 1) < y->first) {
if ((x.first + 1) != 0) {
ret = x.first + 1;
break;
}
}
}
}
}
next_free = ret;
return ret;
}
int Settings::remove_image(int ref) {
int ret = 0;
std::lock_guard<std::recursive_mutex> lock(images_mutex);
auto x = images.find(ref);
if (x != images.end()) {
images.erase(x);
ret = find_next_free_image_ref();
} else {
ret = next_free;
}
return ret;
}
int Settings::replace_image(int ref, std::string data, uint32 width, uint32 height)
{
std::lock_guard<std::recursive_mutex> lock(images_mutex);
int ret = 0;
if (ref == 0) {
ret = add_image(data, width, height);
} else {
auto t = images.find(ref);
if (t != images.end()) {
ret = t->first;
t->second.data = data;
t->second.width = width;
t->second.height = height;
} else {
ret = add_image(data, width, height);
}
}
return ret;
}
int Settings::add_image(std::string data, uint32 width, uint32 height)
{
int last = images.size() + 1;
struct Image_Data dt;
dt.width = width;
dt.height = height;
dt.data = data;
images[last] = dt;
int last = 0;
std::lock_guard<std::recursive_mutex> lock(images_mutex);
if (next_free != 0) {
last = next_free;
struct Image_Data dt;
dt.width = width;
dt.height = height;
dt.data = data;
images[last] = dt;
find_next_free_image_ref();
} else {
PRINT_DEBUG("%s.\n",
"Settings::add_image failed. Buffer is full");
}
return last;
}
int Settings::get_image(int ref, std::string * data, uint32 * width, uint32 * height)
{
std::lock_guard<std::recursive_mutex> lock(images_mutex);
int ret = 0;
auto t = images.find(ref);
if (t != images.end()) {
ret = t->first;
if (data != NULL) {
*data = t->second.data;
}
if (width != NULL) {
*width = t->second.width;
}
if (height != NULL) {
*height = t->second.height;
}
} else {
ret = 0;
if (width != NULL) {
*width = 0;
}
if (height != NULL) {
*height = 0;
}
}
return ret;
}
int Settings::get_profile_image(int eAvatarSize)
{
std::lock_guard<std::recursive_mutex> lock(images_mutex);
int ret = 0;
for (auto i : profile_images) {
if (i.first == eAvatarSize) {
ret = i.second;
break;
}
}
return ret;
}
void Settings::background_monitor_entry(Settings * settings) {
PRINT_DEBUG("%s.\n", "Settings::background_monitor_entry thread starting");
if (settings != NULL) {
settings->background_monitor();
}
PRINT_DEBUG("%s.\n", "Settings::background_monitor_entry thread exiting");
return;
}
#define BACKGROUND_MONITOR_RATE 200
void Settings::background_monitor() {
bool exit = false;
do {
{
std::lock_guard<std::recursive_mutex> lock(background_thread_mutex);
exit = background_thread_exit;
if (!exit) {
if (background_tasks.size() > 0) {
for (auto x = background_tasks.begin(); x != background_tasks.end(); x++) {
bool task_done = false;
Steam_Client * client = try_get_steam_client();
if (client != NULL) {
switch (x->id) {
case Settings_Background_Task_IDs::NOTIFY_AVATAR_IMAGE:
{
PRINT_DEBUG("%s.\n", "Settings::background_monitor Got NOTIFY_AVATAR_IMAGE task");
if (client != NULL && client->steam_friends != NULL) {
if (disable_overlay == true ||
(client->steam_overlay != NULL &&
client->steam_overlay->RegisteredInternalCallbacks() == true)) {
client->steam_friends->GetFriendAvatar(this->steam_id, k_EAvatarSize32x32);
client->steam_friends->GetFriendAvatar(this->steam_id, k_EAvatarSize64x64);
client->steam_friends->GetFriendAvatar(this->steam_id, k_EAvatarSize184x184);
task_done = true;
}
}
}
break;
default:
PRINT_DEBUG("%s %d.\n", "Settings::background_monitor Unknown task", x->id);
task_done = true;
break;
};
if (task_done) {
background_tasks.erase(x);
break;
}
}
}
}
std::this_thread::sleep_for(std::chrono::milliseconds(BACKGROUND_MONITOR_RATE));
}
}
} while(!exit);
return;
}
void Settings::create_background_notify_task(Settings_Background_Task_IDs id, void *arg = NULL) {
std::lock_guard<std::recursive_mutex> lock(background_thread_mutex);
background_tasks.push_back(Settings_Background_Task{id, arg});
return;
}
int Settings::set_profile_image(int eAvatarSize, Image_Data * image)
{
bool size_ok = false;
int ref = 0;
if (image != NULL) {
if (eAvatarSize == k_EAvatarSize32x32 && image->width > 0 && image->width <= 32 && image->height > 0 && image->height <= 32)
size_ok = true;
if (eAvatarSize == k_EAvatarSize64x64 && image->width > 32 && image->width <= 64 && image->height > 32 && image->height <= 64)
size_ok = true;
if (eAvatarSize == k_EAvatarSize184x184 && image->width > 64 && image->width <= 184 && image->height > 64 && image->height <= 184)
size_ok = true;
if (size_ok == true && image->data.length() > 0) {
ref = this->add_image(image->data, image->width, image->height);
PRINT_DEBUG("Settings::set_profile_image %d -> %d.\n", eAvatarSize, ref);
std::lock_guard<std::recursive_mutex> lock(images_mutex);
profile_images[eAvatarSize] = ref;
create_background_notify_task(Settings_Background_Task_IDs::NOTIFY_AVATAR_IMAGE, NULL);
} else {
PRINT_DEBUG("%s %d %dx%d %" PRI_ZU ".\n",
"Settings::set_profile_image failed",
eAvatarSize,
image->width,
image->height,
image->data.length());
}
}
return ref;
}
int Settings::set_profile_image(int eAvatarSize, int reference, bool notify = true)
{
bool size_ok = false;
int ref = 0;
std::lock_guard<std::recursive_mutex> lock(images_mutex);
auto t = images.find(reference);
if (reference != 0 &&
t != images.end()) {
ref = t->first;
if (eAvatarSize == k_EAvatarSize32x32 && t->second.width > 0 && t->second.width <= 32 && t->second.height > 0 && t->second.height <= 32)
size_ok = true;
if (eAvatarSize == k_EAvatarSize64x64 && t->second.width > 32 && t->second.width <= 64 && t->second.height > 32 && t->second.height <= 64)
size_ok = true;
if (eAvatarSize == k_EAvatarSize184x184 && t->second.width > 64 && t->second.width <= 184 && t->second.height > 64 && t->second.height <= 184)
size_ok = true;
if (size_ok == true) {
PRINT_DEBUG("Settings::set_profile_image %d -> %d.\n", eAvatarSize, ref);
profile_images[eAvatarSize] = ref;
if (notify == true) {
create_background_notify_task(Settings_Background_Task_IDs::NOTIFY_AVATAR_IMAGE, NULL);
}
} else {
PRINT_DEBUG("%s %d ref: %d.\n",
"Settings::set_profile_image failed invalid size. size:",
eAvatarSize,
reference);
}
} else {
PRINT_DEBUG("%s %d ref: %d.\n",
"Settings::set_profile_image failed invalid reference. size:",
eAvatarSize,
reference);
}
return ref;
}
void Settings::set_preferred_network_image_type(int new_type)
{
switch (new_type) {
case Image::RAW:
case Image::PNG:
case Image::JPG:
this->preferred_network_image_type = new_type;
break;
default:
PRINT_DEBUG("%s %d.\n",
"Settings::set_preferred_network_image_type failed. Requested type",
new_type);
break;
};
return;
}
std::string Settings::get_ui_notification_position()
{
return this->ui_notification_position;
}
void Settings::set_ui_notification_position(char * pos)
{
PRINT_DEBUG("%s 0x%p.\n",
"Settings::set_ui_notification_position",
pos);
if (pos != NULL) {
size_t len = strlen(pos);
if (len > 0) {
this->ui_notification_position = "";
for (size_t x = 0; x < len && pos[x] != '\0'; x++) {
this->ui_notification_position += pos[x];
}
}
}
}

View File

@ -65,21 +65,45 @@ struct Controller_Settings {
std::map<std::string, std::map<std::string, std::pair<std::set<std::string>, std::string>>> action_set_layers;
};
enum Settings_Background_Task_IDs {
NOTIFY_AVATAR_IMAGE = 0
};
struct Settings_Background_Task {
enum Settings_Background_Task_IDs id;
void * arg;
};
class Settings {
CSteamID steam_id;
CGameID game_id;
std::string name, language;
std::string name, language, ui_notification_position;
CSteamID lobby_id;
uint32 preferred_network_image_type;
bool background_thread_exit;
std::vector<Settings_Background_Task> background_tasks;
std::thread background_monitor_thread;
std::recursive_mutex background_thread_mutex;
std::atomic<bool> settings_parser_done;
bool unlockAllDLCs;
bool offline;
bool showAchievementDescOnUnlock;
bool showAchievementHiddenUnearned;
std::vector<struct DLC_entry> DLCs;
std::vector<struct Mod_entry> mods;
std::map<AppId_t, std::string> app_paths;
std::map<std::string, Leaderboard_config> leaderboards;
std::map<std::string, Stat_config> stats;
std::map<int, int> profile_images;
bool create_unknown_leaderboards;
uint16 port;
int next_free;
int find_next_free_image_ref();
void create_background_notify_task(Settings_Background_Task_IDs id, void *arg);
static void background_monitor_entry(Settings * settings);
void background_monitor();
public:
#ifdef LOBBY_CONNECT
@ -87,8 +111,10 @@ public:
#else
static const bool is_lobby_connect = false;
#endif
static std::string sanitize(std::string name);
Settings(CSteamID steam_id, CGameID game_id, std::string name, std::string language, bool offline);
~Settings();
CSteamID get_local_steam_id();
CGameID get_local_game_id();
const char *get_local_name();
@ -103,6 +129,9 @@ public:
uint16 get_port() {return port;}
void set_port(uint16 port) { this->port = port;}
bool is_settings_parser_done() { return this->settings_parser_done; }
void set_settings_parser_done(const bool done) { this->settings_parser_done = done; }
//DLC stuff
void unlockAllDLC(bool value);
void addDLC(AppId_t appID, std::string name, bool available);
@ -132,6 +161,9 @@ public:
//custom broadcasts
std::set<IP_PORT> custom_broadcasts;
//custom master server
std::set<IP_PORT> custom_master_server;
//stats
std::map<std::string, Stat_config> getStats() { return stats; }
void setStatDefiniton(std::string name, struct Stat_config stat_config) {stats[ascii_to_lowercase(name)] = stat_config; }
@ -140,8 +172,17 @@ public:
std::set<uint64> subscribed_groups;
//images
std::recursive_mutex images_mutex;
std::map<int, struct Image_Data> images;
int remove_image(int ref);
int replace_image(int ref, std::string data, uint32 width, uint32 height);
int add_image(std::string data, uint32 width, uint32 height);
int get_image(int ref, std::string * data, uint32 * width, uint32 * height);
int get_profile_image(int eAvatarSize);
int set_profile_image(int eAvatarSize, Image_Data * image);
int set_profile_image(int eAvatarSize, int reference, bool notify);
int get_preferred_network_image_type() { return this->preferred_network_image_type; }
void set_preferred_network_image_type(int new_type);
//controller
struct Controller_Settings controller_settings;
@ -167,6 +208,16 @@ public:
//warn people who use local save
bool warn_local_save = false;
//achievements
bool get_show_achievement_desc_on_unlock() { return showAchievementDescOnUnlock; }
void set_show_achievement_desc_on_unlock(bool set) { this->showAchievementDescOnUnlock = set; }
bool get_show_achievement_hidden_unearned() { return showAchievementHiddenUnearned; }
void set_show_achievement_hidden_unearned(bool set) { this->showAchievementHiddenUnearned = set; }
//UI
std::string get_ui_notification_position();
void set_ui_notification_position(char * pos);
};
#endif

View File

@ -110,7 +110,7 @@ static void load_gamecontroller_settings(Settings *settings)
}
settings->controller_settings.action_sets[action_set_name] = button_pairs;
PRINT_DEBUG("Added %u action names to %s\n", button_pairs.size(), action_set_name.c_str());
PRINT_DEBUG("Added %" PRI_ZU " action names to %s\n", button_pairs.size(), action_set_name.c_str());
}
}
@ -211,10 +211,45 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
load_custom_broadcasts(local_storage->get_global_settings_path() + "custom_broadcasts.txt", custom_broadcasts);
load_custom_broadcasts(Local_Storage::get_game_settings_path() + "custom_broadcasts.txt", custom_broadcasts);
// Custom master server
std::set<IP_PORT> custom_master_server;
load_custom_broadcasts(local_storage->get_global_settings_path() + "custom_master_server.txt", custom_master_server);
load_custom_broadcasts(Local_Storage::get_game_settings_path() + "custom_master_server.txt", custom_master_server);
// Acount name
char name[32] = {};
char name[32] = { '\0' };
if (local_storage->get_data_settings("account_name.txt", name, sizeof(name) - 1) <= 0) {
strcpy(name, DEFAULT_NAME);
PRINT_DEBUG("%s.\n", "Attempting to set steam user name from system user name");
#if defined(STEAM_WIN32)
DWORD username_dword = 32;
wchar_t username[32] = { '\0' };
if (GetUserNameW((wchar_t*)&username, &username_dword) == TRUE) {
std::wstring username_wstr(username);
std::string username_str = utf8_encode(username_wstr);
size_t username_len = username_str.length();
if (username_len > 0 &&
username_len < 31) {
memcpy(&name, username_str.c_str(), username_len);
name[31] = '\0';
}
}
#else
char * env_username = getenv("USER");
if (env_username != NULL) {
size_t username_len = strlen(env_username);
if (username_len > 0 &&
username_len < 31) {
memcpy(&name, env_username, username_len);
name[31] = '\0';
}
}
#endif
char empty_name[32] = { '\0' };
if (memcmp(name, empty_name, 32) == 0) {
PRINT_DEBUG("%s %s.\n", "Setting steam user name to", DEFAULT_NAME);
strcpy(name, DEFAULT_NAME);
}
PRINT_DEBUG("Username: %s.\n", name);
local_storage->store_data_settings("account_name.txt", name, strlen(name));
}
@ -225,6 +260,13 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
local_storage->store_data_settings("language.txt", language, strlen(language));
}
// UI Notification Position.
char notification_position[32] = {};
if (local_storage->get_data_settings("ui_notification_position.txt", notification_position, sizeof(notification_position) - 1) <= 0) {
strcpy(notification_position, DEFAULT_UI_NOTIFICATION_POSITION);
local_storage->store_data_settings("ui_notification_position.txt", notification_position, strlen(notification_position));
}
// Steam ID
char array_steam_id[32] = {};
CSteamID user_id;
@ -260,6 +302,12 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
local_storage->store_data_settings("user_steam_id.txt", temp_text, strlen(temp_text));
}
if (Local_Storage::is_directory(Local_Storage::get_user_appdata_path().append(PATH_SEPARATOR).append("minidumps")) == false) {
local_storage->store_data_settings(std::string("minidumps").append(PATH_SEPARATOR).append("dummy.txt"),
" ",
sizeof(" ") / sizeof(char));
}
std::set<std::string> supported_languages;
{
@ -299,10 +347,42 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
bool disable_networking = false;
bool disable_overlay = false;
bool disable_lobby_creation = false;
bool enable_achievement_desc_on_unlock = false;
bool enable_displaying_hidden_achievements = false;
int build_id = 10;
bool warn_forced = false;
Image_Data profile_small {0, 0, std::string()};
Image_Data profile_medium {0, 0, std::string()};
Image_Data profile_large {0, 0, std::string()};
{
std::string steam_settings_path = local_storage->get_global_settings_path();
std::vector<std::string> paths = local_storage->get_filenames_path(steam_settings_path);
for (auto & p: paths) {
PRINT_DEBUG("global settings path %s\n", p.c_str());
if (p == "enable_achievement_desc_on_unlock.txt") {
enable_achievement_desc_on_unlock = true;
} else if (p == "enable_displaying_hidden_achievements.txt") {
enable_displaying_hidden_achievements = true;
} else if (p == "avatar_small.jpg") {
profile_small.data = convert_vector_image_pixel_t_to_std_string(local_storage->load_image(steam_settings_path + p, &profile_small.width, &profile_small.height));
} else if (p == "avatar_medium.jpg") {
profile_medium.data = convert_vector_image_pixel_t_to_std_string(local_storage->load_image(steam_settings_path + p, &profile_medium.width, &profile_medium.height));
} else if (p == "avatar_large.jpg") {
profile_large.data = convert_vector_image_pixel_t_to_std_string(local_storage->load_image(steam_settings_path + p, &profile_large.width, &profile_large.height));
} else if (p == "avatar_small.png") {
profile_small.data = convert_vector_image_pixel_t_to_std_string(local_storage->load_image(steam_settings_path + p, &profile_small.width, &profile_small.height));
} else if (p == "avatar_medium.png") {
profile_medium.data = convert_vector_image_pixel_t_to_std_string(local_storage->load_image(steam_settings_path + p, &profile_medium.width, &profile_medium.height));
} else if (p == "avatar_large.png") {
profile_large.data = convert_vector_image_pixel_t_to_std_string(local_storage->load_image(steam_settings_path + p, &profile_large.width, &profile_large.height));
}
}
}
{
std::string steam_settings_path = Local_Storage::get_game_settings_path();
@ -317,12 +397,22 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
disable_overlay = true;
} else if (p == "disable_lobby_creation.txt") {
disable_lobby_creation = true;
} else if (p == "enable_achievement_desc_on_unlock.txt") {
enable_achievement_desc_on_unlock = true;
} else if (p == "enable_displaying_hidden_achievements.txt") {
enable_displaying_hidden_achievements = true;
} else if (p == "force_language.txt") {
int len = Local_Storage::get_file_data(steam_settings_path + "force_language.txt", language, sizeof(language) - 1);
if (len > 0) {
language[len] = 0;
warn_forced = true;
}
} else if (p == "force_ui_notification_position.txt") {
int len = Local_Storage::get_file_data(steam_settings_path + "force_ui_notification_position.txt", notification_position, sizeof(notification_position) - 1);
if (len > 0) {
notification_position[len] = 0;
warn_forced = true;
}
} else if (p == "force_steamid.txt") {
char steam_id_text[32] = {};
if (Local_Storage::get_file_data(steam_settings_path + "force_steamid.txt", steam_id_text, sizeof(steam_id_text) - 1) > 0) {
@ -359,6 +449,8 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
settings_server->set_port(port);
settings_client->custom_broadcasts = custom_broadcasts;
settings_server->custom_broadcasts = custom_broadcasts;
settings_client->custom_master_server = custom_master_server;
settings_server->custom_master_server = custom_master_server;
settings_client->disable_networking = disable_networking;
settings_server->disable_networking = disable_networking;
settings_client->disable_overlay = disable_overlay;
@ -373,6 +465,30 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
settings_server->warn_local_save = local_save;
settings_client->supported_languages = supported_languages;
settings_server->supported_languages = supported_languages;
settings_client->set_show_achievement_desc_on_unlock(enable_achievement_desc_on_unlock);
settings_server->set_show_achievement_desc_on_unlock(enable_achievement_desc_on_unlock);
settings_client->set_show_achievement_hidden_unearned(enable_displaying_hidden_achievements);
settings_server->set_show_achievement_hidden_unearned(enable_displaying_hidden_achievements);
settings_client->set_ui_notification_position(notification_position);
settings_server->set_ui_notification_position(notification_position);
if (profile_small.data.length() > 0 && profile_small.width > 0 && profile_small.height > 0) {
settings_client->set_profile_image(k_EAvatarSize32x32, &profile_small);
settings_server->set_profile_image(k_EAvatarSize32x32, &profile_small);
} else {
PRINT_DEBUG("%s %" PRI_ZU " %d %d\n", "Small user avatar image not defined.", profile_small.data.length(), profile_small.width, profile_small.height);
}
if (profile_medium.data.length() > 0 && profile_medium.width > 0 && profile_medium.height > 0) {
settings_client->set_profile_image(k_EAvatarSize64x64, &profile_medium);
settings_server->set_profile_image(k_EAvatarSize64x64, &profile_medium);
} else {
PRINT_DEBUG("%s %" PRI_ZU " %d %d\n", "Medium user avatar image not defined.", profile_medium.data.length(), profile_medium.width, profile_medium.height);
}
if (profile_large.data.length() > 0 && profile_large.width > 0 && profile_large.height > 0) {
settings_client->set_profile_image(k_EAvatarSize184x184, &profile_large);
settings_server->set_profile_image(k_EAvatarSize184x184, &profile_large);
} else {
PRINT_DEBUG("%s %" PRI_ZU " %d %d\n", "Large user avatar image not defined.", profile_large.data.length(), profile_large.width, profile_large.height);
}
{
std::string dlc_config_path = Local_Storage::get_game_settings_path() + "DLC.txt";
@ -621,6 +737,9 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
load_gamecontroller_settings(settings_client);
settings_client->set_settings_parser_done(true);
settings_server->set_settings_parser_done(true);
*settings_client_out = settings_client;
*settings_server_out = settings_server;
*local_storage_out = local_storage;
@ -629,8 +748,33 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
return appid;
}
void save_global_settings(Local_Storage *local_storage, char *name, char *language)
void save_global_settings(Local_Storage *local_storage, Settings * client_settings)
{
local_storage->store_data_settings("account_name.txt", name, strlen(name));
local_storage->store_data_settings("language.txt", language, strlen(language));
if ((local_storage != nullptr) && (client_settings != nullptr)) {
std::string name = client_settings->get_local_name();
std::string language = client_settings->get_language();
std::string ui_notif_pos = client_settings->get_ui_notification_position();
local_storage->store_data_settings("account_name.txt", (char*)name.c_str(), name.length());
local_storage->store_data_settings("language.txt", (char*)language.c_str(), language.length());
local_storage->store_data_settings("ui_notification_position.txt", (char*)ui_notif_pos.c_str(), ui_notif_pos.length());
if (client_settings->get_show_achievement_desc_on_unlock()) {
if (local_storage->data_settings_exists("enable_achievement_desc_on_unlock.txt") != true) {
local_storage->store_data_settings("enable_achievement_desc_on_unlock.txt", " ", sizeof(" "));
}
} else {
if (local_storage->data_settings_exists("enable_achievement_desc_on_unlock.txt") == true) {
local_storage->delete_data_settings("enable_achievement_desc_on_unlock.txt");
}
}
if (client_settings->get_show_achievement_hidden_unearned()) {
if (local_storage->data_settings_exists("enable_displaying_hidden_achievements.txt") != true) {
local_storage->store_data_settings("enable_displaying_hidden_achievements.txt", " ", sizeof(" "));
}
} else {
if (local_storage->data_settings_exists("enable_displaying_hidden_achievements.txt") == true) {
local_storage->delete_data_settings("enable_displaying_hidden_achievements.txt");
}
}
}
}

View File

@ -22,6 +22,6 @@
//returns appid
uint32 create_localstorage_settings(Settings **settings_client_out, Settings **settings_server_out, Local_Storage **local_storage_out);
void save_global_settings(Local_Storage *local_storage, char *name, char *language);
void save_global_settings(Local_Storage *local_storage, Settings *client_settings);
#endif

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_HTMLSURFACE_H
#define INCLUDED_STEAM_HTMLSURFACE_H
class Steam_HTMLsurface :
public ISteamHTMLSurface001,
public ISteamHTMLSurface002,
@ -337,3 +340,5 @@ void FileLoadDialogResponse( HHTMLBrowser unBrowserHandle, const char **pchSelec
}
};
#endif // INCLUDED_STEAM_HTMLSURFACE_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_APPLIST_H
#define INCLUDED_STEAM_APPLIST_H
class Steam_Applist : public ISteamAppList
{
public:
@ -28,3 +31,5 @@ public:
int GetAppBuildId( AppId_t nAppID ); // return the buildid of this app, may change at any time based on backend updates to the game
};
#endif // INCLUDED_STEAM_APPLIST_H

View File

@ -1,5 +1,8 @@
#include "base.h"
#ifndef INCLUDED_STEAM_APPS_H
#define INCLUDED_STEAM_APPS_H
class Steam_Apps :
public ISteamApps001,
public ISteamApps002,
@ -110,3 +113,5 @@ public:
// set current DLC AppID being played (or 0 if none). Allows Steam to track usage of major DLC extensions
bool SetDlcContext( AppId_t nAppID );
};
#endif // INCLUDED_STEAM_APPS_H

View File

@ -50,16 +50,16 @@ static void background_thread(Steam_Client *client)
Steam_Client::Steam_Client()
{
uint32 appid = create_localstorage_settings(&settings_client, &settings_server, &local_storage);
network = new Networking(settings_server->get_local_steam_id(), appid, settings_server->get_port(), &(settings_server->custom_broadcasts), settings_server->disable_networking);
callback_results_client = new SteamCallResults();
callback_results_server = new SteamCallResults();
callbacks_client = new SteamCallBacks(callback_results_client);
callbacks_server = new SteamCallBacks(callback_results_server);
run_every_runcb = new RunEveryRunCB();
uint32 appid = create_localstorage_settings(&settings_client, &settings_server, &local_storage);
network = new Networking(settings_server->get_local_steam_id(), appid, settings_server->get_port(), &(settings_server->custom_broadcasts), settings_server->disable_networking);
PRINT_DEBUG("steam client init: id: %llu server id: %llu appid: %u port: %u \n", settings_client->get_local_steam_id().ConvertToUint64(), settings_server->get_local_steam_id().ConvertToUint64(), appid, settings_server->get_port());
if (appid) {
@ -81,6 +81,7 @@ Steam_Client::Steam_Client()
steam_remote_storage = new Steam_Remote_Storage(settings_client, local_storage, callback_results_client);
steam_screenshots = new Steam_Screenshots(local_storage, callbacks_client);
steam_http = new Steam_HTTP(settings_client, network, callback_results_client, callbacks_client);
steam_unified_messages = new Steam_Unified_Messages(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_controller = new Steam_Controller(settings_client, callback_results_client, callbacks_client, run_every_runcb);
steam_ugc = new Steam_UGC(settings_client, callback_results_client, callbacks_client);
steam_applist = new Steam_Applist();
@ -95,7 +96,6 @@ Steam_Client::Steam_Client()
steam_networking_messages = new Steam_Networking_Messages(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_game_coordinator = new Steam_Game_Coordinator(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_networking_utils = new Steam_Networking_Utils(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_unified_messages = new Steam_Unified_Messages(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_game_search = new Steam_Game_Search(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_parties = new Steam_Parties(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
steam_remoteplay = new Steam_RemotePlay(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
@ -1433,9 +1433,22 @@ void Steam_Client::RegisterCallback( class CCallbackBase *pCallback, int iCallba
PRINT_DEBUG("Unknown callback base %i\n", base_callback);
};
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (isGameServer) {
if (callback_results_server == nullptr) {
callback_results_server = new SteamCallResults();
}
if (callbacks_server == nullptr) {
callbacks_server = new SteamCallBacks(callback_results_server);
}
callbacks_server->addCallBack(iCallback, pCallback);
} else {
if (callback_results_client == nullptr) {
callback_results_client = new SteamCallResults();
}
if (callbacks_client == nullptr) {
callbacks_client = new SteamCallBacks(callback_results_client);
}
callbacks_client->addCallBack(iCallback, pCallback);
}
}
@ -1657,10 +1670,15 @@ void Steam_Client::UnregisterCallback( class CCallbackBase *pCallback)
PRINT_DEBUG("Unknown callback base %i\n", base_callback);
};
std::lock_guard<std::recursive_mutex> lock(global_mutex);
if (isGameServer) {
callbacks_server->rmCallBack(iCallback, pCallback);
if (callbacks_server != nullptr) {
callbacks_server->rmCallBack(iCallback, pCallback);
}
} else {
callbacks_client->rmCallBack(iCallback, pCallback);
if (callbacks_client != nullptr) {
callbacks_client->rmCallBack(iCallback, pCallback);
}
}
}
@ -1670,7 +1688,6 @@ void Steam_Client::RegisterCallResult( class CCallbackBase *pCallback, SteamAPIC
std::lock_guard<std::recursive_mutex> lock(global_mutex);
callback_results_client->addCallBack(hAPICall, pCallback);
callback_results_server->addCallBack(hAPICall, pCallback);
}
void Steam_Client::UnregisterCallResult( class CCallbackBase *pCallback, SteamAPICall_t hAPICall)

View File

@ -53,6 +53,9 @@
#include "../overlay_experimental/steam_overlay.h"
#ifndef INCLUDED_STEAM_CLIENT_H
#define INCLUDED_STEAM_CLIENT_H
enum Steam_Pipe {
NO_USER,
CLIENT,
@ -75,6 +78,7 @@ public ISteamClient018,
public ISteamClient019,
public ISteamClient
{
// Some games (SAO:FB) use pointer math to access the class so member order is important.
public:
Networking *network;
SteamCallResults *callback_results_server, *callback_results_client;
@ -94,6 +98,7 @@ public:
Steam_Remote_Storage *steam_remote_storage;
Steam_Screenshots *steam_screenshots;
Steam_HTTP *steam_http;
Steam_Unified_Messages *steam_unified_messages;
Steam_Controller *steam_controller;
Steam_UGC *steam_ugc;
Steam_Applist *steam_applist;
@ -108,7 +113,6 @@ public:
Steam_Networking_Messages *steam_networking_messages;
Steam_Game_Coordinator *steam_game_coordinator;
Steam_Networking_Utils *steam_networking_utils;
Steam_Unified_Messages *steam_unified_messages;
Steam_Game_Search *steam_game_search;
Steam_Parties *steam_parties;
Steam_RemotePlay *steam_remoteplay;
@ -302,3 +306,5 @@ public:
void DestroyAllInterfaces();
};
#endif // INCLUDED_STEAM_CLIENT_H

View File

@ -16,6 +16,10 @@
<http://www.gnu.org/licenses/>. */
#include "base.h"
#ifndef INCLUDED_STEAM_CONTROLLER_H
#define INCLUDED_STEAM_CONTROLLER_H
#ifndef CONTROLLER_SUPPORT
inline void GamepadInit(void) {}
inline void GamepadShutdown(void) {}
@ -1224,3 +1228,5 @@ void RunCallbacks()
}
};
#endif // INCLUDED_STEAM_CONTROLLER_H

425
dll/steam_friends.cpp Normal file
View File

@ -0,0 +1,425 @@
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
The Goldberg Emulator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator; if not, see
<http://www.gnu.org/licenses/>. */
#include "steam_friends.h"
#include "dll.h"
void Steam_Friends::Callback(Common_Message *msg)
{
if (msg->has_low_level()) {
if (msg->low_level().type() == Low_Level::DISCONNECT) {
PRINT_DEBUG("Steam_Friends::Callback Disconnect\n");
uint64 id = msg->source_id();
auto f = std::find_if(friends.begin(), friends.end(), [&id](Friend const& item) { return item.id() == id; });
if (friends.end() != f) {
persona_change((uint64)f->id(), k_EPersonaChangeStatus);
overlay->FriendDisconnect(*f);
if ((uint64)f->id() != settings->get_local_steam_id().ConvertToUint64()) {
auto nums = avatars.find((uint64)f->id());
if (nums != avatars.end()) {
if (nums->second.smallest != 0) {
settings->remove_image(nums->second.smallest);
}
if (nums->second.medium != 0) {
settings->remove_image(nums->second.medium);
}
if (nums->second.large != 0) {
settings->remove_image(nums->second.large);
}
avatars.erase(nums);
}
friends.erase(f);
}
}
}
if (msg->low_level().type() == Low_Level::CONNECT) {
PRINT_DEBUG("Steam_Friends::Callback Connect\n");
Common_Message msg_;
msg_.set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg_.set_dest_id(msg->source_id());
Friend *f = new Friend(us);
f->set_id(settings->get_local_steam_id().ConvertToUint64());
f->set_name(settings->get_local_name());
f->set_appid(settings->get_local_game_id().AppID());
f->set_lobby_id(settings->get_lobby().ConvertToUint64());
msg_.set_allocated_friend_(f);
network->sendTo(&msg_, true);
}
}
if (msg->has_friend_()) {
PRINT_DEBUG("Steam_Friends::Callback Friend %llu %llu\n", msg->friend_().id(), msg->friend_().lobby_id());
Friend *f = find_friend((uint64)msg->friend_().id());
if (!f) {
if (msg->friend_().id() != settings->get_local_steam_id().ConvertToUint64()) {
friends.push_back(msg->friend_());
overlay->FriendConnect(msg->friend_());
persona_change((uint64)msg->friend_().id(), k_EPersonaChangeName);
}
} else {
std::map<std::string, std::string> map1(f->rich_presence().begin(), f->rich_presence().end());
std::map<std::string, std::string> map2(msg->friend_().rich_presence().begin(), msg->friend_().rich_presence().end());
if (map1 != map2) {
//The App ID of the game. This should always be the current game.
if (isAppIdCompatible(f)) {
rich_presence_updated((uint64)msg->friend_().id(), (uint64)msg->friend_().appid());
}
}
//TODO: callbacks?
*f = msg->friend_();
}
}
if (msg->has_friend_messages()) {
if (msg->friend_messages().type() == Friend_Messages::LOBBY_INVITE) {
PRINT_DEBUG("Steam_Friends::Callback Got Lobby Invite\n");
Friend *f = find_friend((uint64)msg->source_id());
if (f) {
LobbyInvite_t data;
data.m_ulSteamIDUser = msg->source_id();
data.m_ulSteamIDLobby = msg->friend_messages().lobby_id();
data.m_ulGameID = f->appid();
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
if (overlay->Ready())
{
//TODO: the user should accept the invite first but we auto accept it because there's no gui yet
// Then we will handle it !
overlay->SetLobbyInvite(*find_friend(static_cast<uint64>(msg->source_id())), msg->friend_messages().lobby_id());
}
else
{
GameLobbyJoinRequested_t data;
data.m_steamIDLobby = CSteamID((uint64)msg->friend_messages().lobby_id());
data.m_steamIDFriend = CSteamID((uint64)msg->source_id());
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
}
}
if (msg->friend_messages().type() == Friend_Messages::GAME_INVITE) {
PRINT_DEBUG("Steam_Friends::Callback Got Game Invite\n");
//TODO: I'm pretty sure that the user should accept the invite before this is posted but we do like above
if (overlay->Ready())
{
// Then we will handle it !
overlay->SetRichInvite(*find_friend(static_cast<uint64>(msg->source_id())), msg->friend_messages().connect_str().c_str());
}
else
{
std::string const& connect_str = msg->friend_messages().connect_str();
GameRichPresenceJoinRequested_t data = {};
data.m_steamIDFriend = CSteamID((uint64)msg->source_id());
strncpy(data.m_rgchConnect, connect_str.c_str(), k_cchMaxRichPresenceValueLength - 1);
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
}
}
if (msg->has_friend_avatar()) {
CSteamID userID((uint64)msg->source_id());
Friend *f = find_friend(userID.ConvertToUint64());
if (f) {
if (msg->friend_avatar().img().type() == Image::NOTIFY) {
PRINT_DEBUG("%s %" PRIu64 ".\n", "Steam_Friends::Callback Got Friend_Avatar NOTIFY for", userID.ConvertToUint64());
std::string raw_image = msg->friend_avatar().img().img_data();
if (raw_image.length() > 0 && raw_image.length() < FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
uint32_t width = (uint32_t)msg->friend_avatar().img().img_width();
uint32_t height = (uint32_t)msg->friend_avatar().img().img_height();
uint32_t img_type = (uint32_t)msg->friend_avatar().img().img_type();
int eAvatarSize = k_EAvatarSizeMAX;
auto nums = avatars.find(userID.ConvertToUint64());
if (nums == avatars.end()) {
struct Avatar_Numbers n;
generate_avatar_numbers(n);
n.last_update_time = std::chrono::steady_clock::now();
avatars[userID.ConvertToUint64()] = n;
nums = avatars.find(userID.ConvertToUint64());
}
int num_replace = 0;
if (nums != avatars.end()) {
if (width > 0 && width <= 32 && height > 0 && height <= 32) {
eAvatarSize = k_EAvatarSize32x32;
num_replace = nums->second.smallest;
} else {
if (width > 32 && width <= 64 && height > 32 && height <= 64) {
eAvatarSize = k_EAvatarSize64x64;
num_replace = nums->second.medium;
} else {
if (width > 64 && width <= 184 && height > 64 && height <= 184) {
eAvatarSize = k_EAvatarSize184x184;
num_replace = nums->second.large;
}
}
}
if (eAvatarSize != k_EAvatarSizeMAX) {
switch (img_type) {
case Image::RAW:
PRINT_DEBUG("%s %" PRIu64 " %s %d %s.\n",
"Steam_Friends::Callback Got Friend_Avatar NOTIFY for",
userID.ConvertToUint64(),
"size",
eAvatarSize,
"image type RAW");
break;
case Image::JPG:
{
std::string convert;
int n_width = 0;
int n_height = 0;
PRINT_DEBUG("%s %" PRIu64 " %s %d %s.\n",
"Steam_Friends::Callback Got Friend_Avatar NOTIFY for",
userID.ConvertToUint64(),
"size",
eAvatarSize,
"image type JPG");
convert = convert_jpg_buffer_std_string_to_std_string_uint8(raw_image, &n_width, &n_height, NULL, 4);
if (convert.length() > 0 && n_width == width && n_height == height) {
raw_image = convert;
convert.clear();
} else {
raw_image.clear();
}
}
break;
case Image::PNG:
{
std::string convert;
int n_width = 0;
int n_height = 0;
PRINT_DEBUG("%s %" PRIu64 " %s %d %s.\n",
"Steam_Friends::Callback Got Friend_Avatar NOTIFY for",
userID.ConvertToUint64(),
"size",
eAvatarSize,
"image type PNG");
convert = convert_png_buffer_std_string_to_std_string_uint8(raw_image, &n_width, &n_height, NULL, 4);
if (convert.length() > 0 && n_width == width && n_height == height) {
raw_image = convert;
convert.clear();
} else {
raw_image.clear();
}
}
break;
default:
raw_image.clear();
PRINT_DEBUG("%s %" PRIu64 " %s %d %s %d.\n",
"Steam_Friends::Callback Got Friend_Avatar NOTIFY for",
userID.ConvertToUint64(),
"size",
eAvatarSize,
"with unsupported image type",
img_type);
break;
};
if (raw_image.length() > 0) {
int ref = settings->replace_image(num_replace, raw_image, width, height);
if (ref != 0) {
nums->second.last_update_time = std::chrono::steady_clock::now();
AvatarImageLoaded_t ail_data = {};
ail_data.m_steamID = userID.ConvertToUint64();
ail_data.m_iImage = ref;
ail_data.m_iWide = width;
ail_data.m_iTall = height;
callbacks->addCBResult(ail_data.k_iCallback, &ail_data, sizeof(ail_data));
persona_change(userID, k_EPersonaChangeAvatar);
}
}
}
}
}
}
if (msg->friend_avatar().img().type() == Image::REQUEST) {
CSteamID requestID((uint64)msg->dest_id());
if (settings->get_local_steam_id() == requestID) {
PRINT_DEBUG("%s %" PRIu64 ".\n", "Steam_Friends::Callback Got Friend_Avatar REQUEST from", userID.ConvertToUint64());
uint32_t width = (uint32_t)msg->friend_avatar().img().img_width();
uint32_t height = (uint32_t)msg->friend_avatar().img().img_height();
uint32_t img_type = (uint32_t)msg->friend_avatar().img().img_type();
int eAvatarSize = k_EAvatarSizeMAX;
if (width > 0 && width <= 32 && height > 0 && height <= 32) {
eAvatarSize = k_EAvatarSize32x32;
} else {
if (width > 32 && width <= 64 && height > 32 && height <= 64) {
eAvatarSize = k_EAvatarSize64x64;
} else {
if (width > 64 && width <= 184 && height > 64 && height <= 184) {
eAvatarSize = k_EAvatarSize184x184;
}
}
}
int ref = GetFriendAvatar(settings->get_local_steam_id(), eAvatarSize);
if (ref != 0) {
uint32 n_width = 0;
uint32 n_height = 0;
Steam_Utils* steamUtils = get_steam_client()->steam_utils;
if ((steamUtils->GetImageSize(ref, &n_width, &n_height) == true) &&
(n_width > 0) && (n_height > 0)) {
uint8 * raw_image = new uint8[(n_width * n_height * sizeof(uint32))];
if (raw_image != NULL) {
if (steamUtils->GetImageRGBA(ref,
raw_image,
(n_width * n_height * sizeof(uint32))) == true) {
uint32_t img_type = (uint32_t)msg->friend_avatar().img().img_type();
PRINT_DEBUG("%s %" PRIu64 " %s %d %s %d.\n",
"Steam_Friends::Callback Got Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for image type",
img_type,
"size",
eAvatarSize);
std::string pixdata = "";
if (img_type == Image::PNG) {
pixdata = convert_raw_uint8_to_png_std_string(raw_image, n_width, n_height, 4);
if (pixdata.length() <= 0 || pixdata.length() >= FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
if (pixdata.length() >= FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
PRINT_DEBUG("%s %" PRIu64 " %s %d. %s %" PRI_ZU " %s.\n",
"Steam_Friends::Callback Cannot complete Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for PNG image size",
eAvatarSize,
"Image is over maximum size by ",
pixdata.length() - FRIEND_AVATAR_MAX_IMAGE_LENGTH,
"bytes");
} else {
PRINT_DEBUG("%s %" PRIu64 " %s %d. %s.\n",
"Steam_Friends::Callback Cannot complete Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for PNG image size",
eAvatarSize,
"Could not convert image to requested type");
}
// Try again using JPG.
img_type = Image::JPG;
pixdata.clear();
}
}
if (img_type == Image::JPG) {
pixdata = convert_raw_uint8_to_jpg_std_string(raw_image, n_width, n_height, 4);
if (pixdata.length() <= 0 || pixdata.length() >= FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
// Try again using RAW.
if (pixdata.length() >= FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
PRINT_DEBUG("%s %" PRIu64 " %s %d. %s %" PRI_ZU " %s.\n",
"Steam_Friends::Callback Cannot complete Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for JPG image size",
eAvatarSize,
"Image is over maximum size by ",
pixdata.length() - FRIEND_AVATAR_MAX_IMAGE_LENGTH,
"bytes");
} else {
PRINT_DEBUG("%s %" PRIu64 " %s %d. %s.\n",
"Steam_Friends::Callback Cannot complete Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for JPG image size",
eAvatarSize,
"Could not convert image to requested type");
}
img_type = Image::RAW;
pixdata.clear();
}
}
if (img_type == Image::RAW) {
for (size_t x = 0; x < (n_width * n_height * sizeof(uint32)); x++) {
char a = (char)(raw_image[x]);
pixdata += a;
}
if (pixdata.length() <= 0 || pixdata.length() >= FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
// No more attempts.
if (pixdata.length() >= FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
PRINT_DEBUG("%s %" PRIu64 " %s %d. %s %" PRI_ZU " %s.\n",
"Steam_Friends::Callback Cannot complete Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for RAW image size",
eAvatarSize,
"Image is over maximum size by ",
pixdata.length() - FRIEND_AVATAR_MAX_IMAGE_LENGTH,
"bytes");
} else {
PRINT_DEBUG("%s %" PRIu64 " %s %d. %s.\n",
"Steam_Friends::Callback Cannot complete Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for RAW image size",
eAvatarSize,
"Could not convert image to requested type");
}
pixdata.clear();
}
}
if (img_type != Image::PNG && img_type != Image::JPG && img_type != Image::RAW) {
pixdata.clear();
PRINT_DEBUG("%s %" PRIu64 " %s %d %s %d.\n",
"Steam_Friends::Callback Got Friend_Avatar REQUEST from",
userID.ConvertToUint64(),
"for unsupported image type",
img_type,
"size",
eAvatarSize);
}
if (pixdata.length() > 0 && pixdata.length() < FRIEND_AVATAR_MAX_IMAGE_LENGTH) {
PRINT_DEBUG("Steam_Friends::Callback Sending Friend_Avatar NOTIFY size %d type %d\n",
eAvatarSize,
img_type);
Common_Message msg_;
msg_.set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg_.set_dest_id(msg->source_id());
Image *img = new Image();
img->set_type(Image::NOTIFY);
img->set_img_type(static_cast<Image_ImgTypes>(img_type));
img->set_img_width(n_width);
img->set_img_height(n_height);
img->set_img_data(pixdata);
Friend_Avatar *friend_avatar = new Friend_Avatar();
friend_avatar->set_allocated_img(img);
msg_.set_allocated_friend_avatar(friend_avatar);
network->sendTo(&msg_, true);
}
}
delete [] raw_image;
raw_image = NULL;
}
}
}
}
}
}
}
}

View File

@ -27,6 +27,7 @@ struct Avatar_Numbers {
int smallest;
int medium;
int large;
std::chrono::steady_clock::time_point last_update_time;
};
class Steam_Friends :
@ -94,25 +95,181 @@ bool isAppIdCompatible(Friend *f)
return settings->get_local_game_id().AppID() == f->appid();
}
void generate_avatar_numbers(struct Avatar_Numbers & nums) {
static struct Avatar_Numbers blanks;
if (blanks.smallest == 0) {
std::string small_avatar(32 * 32 * 4, 0);
blanks.smallest = settings->add_image(small_avatar, 32, 32);
}
if (blanks.medium == 0) {
std::string medium_avatar(64 * 64 * 4, 0);
blanks.medium = settings->add_image(medium_avatar, 64, 64);
}
if (blanks.large == 0) {
std::string large_avatar(184 * 184 * 4, 0);
blanks.large = settings->add_image(large_avatar, 184, 184);
}
nums.smallest = blanks.smallest;
nums.medium = blanks.medium;
nums.large = blanks.large;
return;
}
STEAM_CALL_RESULT( AvatarImageLoaded_t )
struct Avatar_Numbers add_friend_avatars(CSteamID id)
{
uint64 steam_id = id.ConvertToUint64();
auto avatar_ids = avatars.find(steam_id);
if (avatar_ids != avatars.end()) {
return avatar_ids->second;
bool generate = true;
struct Avatar_Numbers avatar_numbers;
if (settings->is_settings_parser_done() == false) {
do {
std::this_thread::sleep_for(std::chrono::milliseconds(200));
} while (settings->is_settings_parser_done() == false);
}
//TODO: get real image data from self/other peers
struct Avatar_Numbers avatar_numbers;
std::string small_avatar(32 * 32 * 4, 0);
std::string medium_avatar(64 * 64 * 4, 0);
std::string large_avatar(184 * 184 * 4, 0);
if (settings->get_local_steam_id().ConvertToUint64() == steam_id) {
avatar_numbers.smallest = settings->get_profile_image(k_EAvatarSize32x32);
avatar_numbers.medium = settings->get_profile_image(k_EAvatarSize64x64);
avatar_numbers.large = settings->get_profile_image(k_EAvatarSize184x184);
avatar_numbers.smallest = settings->add_image(small_avatar, 32, 32);
avatar_numbers.medium = settings->add_image(medium_avatar, 64, 64);
avatar_numbers.large = settings->add_image(large_avatar, 184, 184);
if (avatar_numbers.smallest != 0 &&
avatar_numbers.medium != 0 &&
avatar_numbers.large != 0) {
generate = false;
}
if (avatar_ids != avatars.end()) {
// Check for updated entry.
if (avatar_numbers.smallest == avatar_ids->second.smallest &&
avatar_numbers.medium == avatar_ids->second.medium &&
avatar_numbers.large == avatar_ids->second.large) {
return avatar_ids->second;
}
}
} else {
if (avatar_ids != avatars.end()) {
return avatar_ids->second;
} else {
// Request avatar data.
PRINT_DEBUG("Steam_Friends::add_friend_avatars sending Friend_Avatar small request for %" PRIu64 ".\n", steam_id);
Common_Message * msg_ = new Common_Message();
msg_->set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg_->set_dest_id(steam_id);
Image *img = new Image();
img->set_type(Image::REQUEST);
img->set_img_type(static_cast<Image_ImgTypes>(settings->get_preferred_network_image_type()));
img->set_img_width(32);
img->set_img_height(32);
img->set_img_data("");
Friend_Avatar *friend_avatar = new Friend_Avatar();
friend_avatar->set_allocated_img(img);
msg_->set_allocated_friend_avatar(friend_avatar);
network->sendTo(msg_, true);
PRINT_DEBUG("Steam_Friends::add_friend_avatars sending Friend_Avatar medium request for %" PRIu64 ".\n", steam_id);
msg_ = new Common_Message();
msg_->set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg_->set_dest_id(steam_id);
img = new Image();
img->set_type(Image::REQUEST);
img->set_img_type(static_cast<Image_ImgTypes>(settings->get_preferred_network_image_type()));
img->set_img_width(64);
img->set_img_height(64);
img->set_img_data("");
friend_avatar = new Friend_Avatar();
friend_avatar->set_allocated_img(img);
msg_->set_allocated_friend_avatar(friend_avatar);
network->sendTo(msg_, true);
PRINT_DEBUG("Steam_Friends::add_friend_avatars sending Friend_Avatar large request for %" PRIu64 ".\n", steam_id);
msg_ = new Common_Message();
msg_->set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg_->set_dest_id(steam_id);
img = new Image();
img->set_type(Image::REQUEST);
img->set_img_type(static_cast<Image_ImgTypes>(settings->get_preferred_network_image_type()));
img->set_img_width(184);
img->set_img_height(184);
img->set_img_data("");
friend_avatar = new Friend_Avatar();
friend_avatar->set_allocated_img(img);
msg_->set_allocated_friend_avatar(friend_avatar);
network->sendTo(msg_, true);
}
}
PRINT_DEBUG("%s %s %s %" PRIu64 ".\n",
"Steam_Friends::add_friend_avatars",
(generate == true) ? "Generating empty" : "Notifying changed",
"avatar image for",
steam_id);
if (generate == true) {
generate_avatar_numbers(avatar_numbers);
if (settings->get_local_steam_id().ConvertToUint64() == steam_id) {
settings->set_profile_image(k_EAvatarSize32x32, avatar_numbers.smallest, false);
settings->set_profile_image(k_EAvatarSize64x64, avatar_numbers.medium, false);
settings->set_profile_image(k_EAvatarSize184x184, avatar_numbers.large, false);
}
}
avatar_numbers.last_update_time = std::chrono::steady_clock::now();
avatars[steam_id] = avatar_numbers;
// Generate callbacks.
uint32 width = 0;
uint32 height = 0;
AvatarImageLoaded_t ail_data = {};
bool sent_ail = false;
auto image = settings->get_image(avatar_numbers.smallest, NULL, &width, &height);
if (image == avatar_numbers.smallest) {
ail_data.m_steamID = steam_id;
ail_data.m_iImage = avatar_numbers.smallest;
ail_data.m_iWide = width;
ail_data.m_iTall = height;
callbacks->addCBResult(ail_data.k_iCallback, &ail_data, sizeof(ail_data));
sent_ail = true;
}
image = settings->get_image(avatar_numbers.medium, NULL, &width, &height);
if (image == avatar_numbers.medium) {
ail_data.m_steamID = steam_id;
ail_data.m_iImage = avatar_numbers.medium;
ail_data.m_iWide = width;
ail_data.m_iTall = height;
callbacks->addCBResult(ail_data.k_iCallback, &ail_data, sizeof(ail_data));
sent_ail = true;
}
image = settings->get_image(avatar_numbers.large, NULL, &width, &height);
if (image == avatar_numbers.large) {
ail_data.m_steamID = steam_id;
ail_data.m_iImage = avatar_numbers.large;
ail_data.m_iWide = width;
ail_data.m_iTall = height;
callbacks->addCBResult(ail_data.k_iCallback, &ail_data, sizeof(ail_data));
sent_ail = true;
}
if (sent_ail) {
persona_change(id, k_EPersonaChangeAvatar);
}
return avatar_numbers;
}
@ -147,6 +304,7 @@ Steam_Friends(Settings* settings, Networking* network, SteamCallResults* callbac
overlay(overlay)
{
this->network->setCallback(CALLBACK_ID_FRIEND, settings->get_local_steam_id(), &Steam_Friends::steam_friends_callback, this);
this->network->setCallback(CALLBACK_ID_FRIEND_AVATAR, settings->get_local_steam_id(), &Steam_Friends::steam_friends_callback, this);
this->network->setCallback(CALLBACK_ID_FRIEND_MESSAGES, settings->get_local_steam_id(), &Steam_Friends::steam_friends_callback, this);
this->network->setCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Steam_Friends::steam_friends_callback, this);
this->run_every_runcb->add(&Steam_Friends::steam_friends_run_every_runcb, this);
@ -157,6 +315,20 @@ Steam_Friends(Settings* settings, Networking* network, SteamCallResults* callbac
{
//TODO rm network callbacks
this->run_every_runcb->remove(&Steam_Friends::steam_friends_run_every_runcb, this);
for (auto x : avatars) {
if (x.first != settings->get_local_steam_id().ConvertToUint64()) {
if (x.second.smallest != 0) {
settings->remove_image(x.second.smallest);
}
if (x.second.medium != 0) {
settings->remove_image(x.second.medium);
}
if (x.second.large != 0) {
settings->remove_image(x.second.large);
}
}
}
}
static bool ok_friend_flags(int iFriendFlags)
@ -594,10 +766,10 @@ void ActivateGameOverlayInviteDialog( CSteamID steamIDLobby )
// gets the small (32x32) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set
int GetSmallFriendAvatar( CSteamID steamIDFriend )
{
PRINT_DEBUG("Steam_Friends::GetSmallFriendAvatar\n");
//IMPORTANT NOTE: don't change friend avatar numbers for the same friend or else some games endlessly allocate stuff.
std::lock_guard<std::recursive_mutex> lock(global_mutex);
struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend);
PRINT_DEBUG("Steam_Friends::GetSmallFriendAvatar %" PRIu64 " -> %d.\n", steamIDFriend.ConvertToUint64(), numbers.smallest);
return numbers.smallest;
}
@ -605,9 +777,9 @@ int GetSmallFriendAvatar( CSteamID steamIDFriend )
// gets the medium (64x64) avatar of the current user, which is a handle to be used in IClientUtils::GetImageRGBA(), or 0 if none set
int GetMediumFriendAvatar( CSteamID steamIDFriend )
{
PRINT_DEBUG("Steam_Friends::GetMediumFriendAvatar\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex);
struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend);
PRINT_DEBUG("Steam_Friends::GetMediumFriendAvatar %" PRIu64 " -> %d.\n", steamIDFriend.ConvertToUint64(), numbers.medium);
return numbers.medium;
}
@ -616,9 +788,9 @@ int GetMediumFriendAvatar( CSteamID steamIDFriend )
// returns -1 if this image has yet to be loaded, in this case wait for a AvatarImageLoaded_t callback and then call this again
int GetLargeFriendAvatar( CSteamID steamIDFriend )
{
PRINT_DEBUG("Steam_Friends::GetLargeFriendAvatar\n");
std::lock_guard<std::recursive_mutex> lock(global_mutex);
struct Avatar_Numbers numbers = add_friend_avatars(steamIDFriend);
PRINT_DEBUG("Steam_Friends::GetLargeFriendAvatar %" PRIu64 " -> %d.\n", steamIDFriend.ConvertToUint64(), numbers.large);
return numbers.large;
}
@ -1077,105 +1249,7 @@ void RunCallbacks()
}
}
void Callback(Common_Message *msg)
{
if (msg->has_low_level()) {
if (msg->low_level().type() == Low_Level::DISCONNECT) {
PRINT_DEBUG("Steam_Friends Disconnect\n");
uint64 id = msg->source_id();
auto f = std::find_if(friends.begin(), friends.end(), [&id](Friend const& item) { return item.id() == id; });
if (friends.end() != f) {
persona_change((uint64)f->id(), k_EPersonaChangeStatus);
overlay->FriendDisconnect(*f);
friends.erase(f);
}
}
if (msg->low_level().type() == Low_Level::CONNECT) {
PRINT_DEBUG("Steam_Friends Connect\n");
Common_Message msg_;
msg_.set_source_id(settings->get_local_steam_id().ConvertToUint64());
msg_.set_dest_id(msg->source_id());
Friend *f = new Friend(us);
f->set_id(settings->get_local_steam_id().ConvertToUint64());
f->set_name(settings->get_local_name());
f->set_appid(settings->get_local_game_id().AppID());
f->set_lobby_id(settings->get_lobby().ConvertToUint64());
msg_.set_allocated_friend_(f);
network->sendTo(&msg_, true);
}
}
if (msg->has_friend_()) {
PRINT_DEBUG("Steam_Friends Friend %llu %llu\n", msg->friend_().id(), msg->friend_().lobby_id());
Friend *f = find_friend((uint64)msg->friend_().id());
if (!f) {
if (msg->friend_().id() != settings->get_local_steam_id().ConvertToUint64()) {
friends.push_back(msg->friend_());
overlay->FriendConnect(msg->friend_());
persona_change((uint64)msg->friend_().id(), k_EPersonaChangeName);
}
} else {
std::map<std::string, std::string> map1(f->rich_presence().begin(), f->rich_presence().end());
std::map<std::string, std::string> map2(msg->friend_().rich_presence().begin(), msg->friend_().rich_presence().end());
if (map1 != map2) {
//The App ID of the game. This should always be the current game.
if (isAppIdCompatible(f)) {
rich_presence_updated((uint64)msg->friend_().id(), (uint64)msg->friend_().appid());
}
}
//TODO: callbacks?
*f = msg->friend_();
}
}
if (msg->has_friend_messages()) {
if (msg->friend_messages().type() == Friend_Messages::LOBBY_INVITE) {
PRINT_DEBUG("Steam_Friends Got Lobby Invite\n");
Friend *f = find_friend((uint64)msg->source_id());
if (f) {
LobbyInvite_t data;
data.m_ulSteamIDUser = msg->source_id();
data.m_ulSteamIDLobby = msg->friend_messages().lobby_id();
data.m_ulGameID = f->appid();
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
if (overlay->Ready())
{
//TODO: the user should accept the invite first but we auto accept it because there's no gui yet
// Then we will handle it !
overlay->SetLobbyInvite(*find_friend(static_cast<uint64>(msg->source_id())), msg->friend_messages().lobby_id());
}
else
{
GameLobbyJoinRequested_t data;
data.m_steamIDLobby = CSteamID((uint64)msg->friend_messages().lobby_id());
data.m_steamIDFriend = CSteamID((uint64)msg->source_id());
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
}
}
if (msg->friend_messages().type() == Friend_Messages::GAME_INVITE) {
PRINT_DEBUG("Steam_Friends Got Game Invite\n");
//TODO: I'm pretty sure that the user should accept the invite before this is posted but we do like above
if (overlay->Ready())
{
// Then we will handle it !
overlay->SetRichInvite(*find_friend(static_cast<uint64>(msg->source_id())), msg->friend_messages().connect_str().c_str());
}
else
{
std::string const& connect_str = msg->friend_messages().connect_str();
GameRichPresenceJoinRequested_t data = {};
data.m_steamIDFriend = CSteamID((uint64)msg->source_id());
strncpy(data.m_rgchConnect, connect_str.c_str(), k_cchMaxRichPresenceValueLength - 1);
callbacks->addCBResult(data.k_iCallback, &data, sizeof(data));
}
}
}
}
void Callback(Common_Message *msg);
};

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_GAME_COORDINATOR_H
#define INCLUDED_STEAM_GAME_COORDINATOR_H
class Steam_Game_Coordinator :
public ISteamGameCoordinator
{
@ -152,3 +155,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_GAME_COORDINATOR_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_GAMESEARCH_H
#define INCLUDED_STEAM_GAMESEARCH_H
class Steam_Game_Search :
public ISteamGameSearch
{
@ -213,3 +216,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_GAMESEARCH_H

View File

@ -16,7 +16,10 @@
<http://www.gnu.org/licenses/>. */
#include "base.h"
#ifndef INCLUDED_STEAM_GAMESERVER_H
#define INCLUDED_STEAM_GAMESERVER_H
//-----------------------------------------------------------------------------
// Purpose: Functions for authenticating users via Steam to play on a game server
//-----------------------------------------------------------------------------
@ -353,3 +356,5 @@ public:
//
void RunCallbacks();
};
#endif // INCLUDED_STEAM_GAMESERVER_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_GAMESERVERSTATS_H
#define INCLUDED_STEAM_GAMESERVERSTATS_H
//-----------------------------------------------------------------------------
// Purpose: Functions for authenticating users via Steam to play on a game server
//-----------------------------------------------------------------------------
@ -61,3 +64,5 @@ public:
STEAM_CALL_RESULT( GSStatsStored_t )
SteamAPICall_t StoreUserStats( CSteamID steamIDUser );
};
#endif // INCLUDED_STEAM_GAMESERVERSTATS_H

View File

@ -17,6 +17,8 @@
#include "base.h"
#ifndef INCLUDED_STEAM_HTTP_H
#define INCLUDED_STEAM_HTTP_H
struct Steam_Http_Request {
HTTPRequestHandle handle;
@ -152,3 +154,5 @@ public:
// Check if the reason the request failed was because we timed it out (rather than some harder failure)
bool GetHTTPRequestWasTimedOut( HTTPRequestHandle hRequest, bool *pbWasTimedOut );
};
#endif // INCLUDED_STEAM_HTTP_H

View File

@ -17,6 +17,9 @@
#include "base.h" // For SteamItemDef_t
#ifndef INCLUDED_STEAM_INVENTORY_H
#define INCLUDED_STEAM_INVENTORY_H
struct Steam_Inventory_Requests {
double timeout = 0.1;
bool done = false;
@ -964,3 +967,5 @@ void RunCallbacks()
}
};
#endif // INCLUDED_STEAM_INVENTORY_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_MASTERSERVER_UPDATER_H
#define INCLUDED_STEAM_MASTERSERVER_UPDATER_H
class Steam_Masterserver_Updater :
public ISteamMasterServerUpdater
{
@ -173,12 +176,64 @@ void ForceHeartbeat()
bool AddMasterServer( const char *pServerAddress )
{
PRINT_DEBUG("Steam_Masterserver_Updater::AddMasterServer\n");
IP_PORT addr;
if (pServerAddress)
{
addr.ip = (uint32)*pServerAddress;
if (pServerAddress[(sizeof(uint32))] != 0)
{
addr.port = (uint16)*(pServerAddress + sizeof(uint32));
}
else
{
addr.port = 27016;
}
PRINT_DEBUG("Steam_Masterserver_Updater::AddMasterServer pServerAddress IP: %d, PORT: %d", addr.ip, addr.port);
this->settings->custom_master_server.insert(addr);
}
return true;
}
bool RemoveMasterServer( const char *pServerAddress )
{
PRINT_DEBUG("Steam_Masterserver_Updater::RemoveMasterServer\n");
std::set<IP_PORT>::iterator iter;
IP_PORT addr;
IP_PORT list;
if (pServerAddress)
{
addr.ip = (uint32)*pServerAddress;
if (pServerAddress[(sizeof(uint32))] != 0)
{
addr.port = (uint16)*(pServerAddress + sizeof(uint32));
}
else
{
addr.port = 27016;
}
PRINT_DEBUG("Steam_Masterserver_Updater::RemoveMasterServer pServerAddress IP: %d, PORT: %d", addr.ip, addr.port);
iter = this->settings->custom_master_server.begin();
while (iter != this->settings->custom_master_server.end())
{
list = (*iter);
if (addr.ip == list.ip &&
(addr.port == list.port || (list.port == 0 && addr.port == 27016)))
{
iter = this->settings->custom_master_server.erase(iter);
}
else
{
iter++;
}
}
}
return true;
}
@ -186,7 +241,7 @@ bool RemoveMasterServer( const char *pServerAddress )
int GetNumMasterServers()
{
PRINT_DEBUG("Steam_Masterserver_Updater::GetNumMasterServers\n");
return 0;
return this->settings->custom_master_server.size();
}
@ -194,7 +249,38 @@ int GetNumMasterServers()
int GetMasterServerAddress( int iServer, char *pOut, int outBufferSize )
{
PRINT_DEBUG("Steam_Masterserver_Updater::GetMasterServerAddress\n");
return 0;
size_t written_bytes = 0;
char * byte_cpy = NULL;
std::set<IP_PORT>::iterator iter;
IP_PORT addr;
if (pOut && outBufferSize >= sizeof(uint32) && this->settings->custom_master_server.size() > 0)
{
iter = this->settings->custom_master_server.begin();
while (written_bytes < outBufferSize && iter != this->settings->custom_master_server.end())
{
addr = (*iter);
byte_cpy = (char*)&(addr.ip);
for (size_t x = 0; x < sizeof(addr.ip) && written_bytes < outBufferSize; x++)
{
memcpy(pOut + x, byte_cpy + x, 1);
written_bytes++;
}
if (addr.port != 0 && addr.port != 27016) // Default updater port.
{
byte_cpy = (char*)&(addr.port);
for (size_t x = 0; x < sizeof(addr.port) && written_bytes < outBufferSize; x++)
{
memcpy(pOut + x, byte_cpy + x, 1);
written_bytes++;
}
}
iter++;
}
}
return written_bytes;
}
@ -217,3 +303,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_MASTERSERVER_UPDATER_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_MATCHMAKING_H
#define INCLUDED_STEAM_MATCHMAKING_H
#define SEND_LOBBY_RATE 5.0
#define PENDING_JOIN_TIMEOUT 10.0
@ -1547,3 +1550,5 @@ void Callback(Common_Message *msg)
};
#endif // INCLUDED_STEAM_MATCHMAKING_H

View File

@ -33,7 +33,7 @@ Steam_Matchmaking_Servers::Steam_Matchmaking_Servers(class Settings *settings, c
this->network->setCallback(CALLBACK_ID_GAMESERVER, (uint64) 0, &network_callback, this);
}
static int server_list_request;
static size_t server_list_request;
// Request a new list of servers of a particular type. These calls each correspond to one of the EMatchMakingType values.
// Each call allocates a new asynchronous request object.
@ -297,7 +297,7 @@ gameserveritem_t *Steam_Matchmaking_Servers::GetServerDetails( HServerListReques
PRINT_DEBUG("equal? %p %p\n", hRequest, g->id);
if (g->id == hRequest) {
gameservers_filtered = g->gameservers_filtered;
PRINT_DEBUG("found %u\n", gameservers_filtered.size());
PRINT_DEBUG("found %" PRI_ZU "\n", gameservers_filtered.size());
break;
}

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_MATCHMAKING_SERVERS_H
#define INCLUDED_STEAM_MATCHMAKING_SERVERS_H
#define SERVER_TIMEOUT 10.0
#define DIRECT_IP_DELAY 0.05
@ -223,3 +226,5 @@ public:
void Callback(Common_Message *msg);
void server_details(Gameserver *g, gameserveritem_t *server);
};
#endif // INCLUDED_STEAM_MATCHMAKING_SERVERS_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_MUSIC_H
#define INCLUDED_STEAM_MUSIC_H
class Steam_Music : public ISteamMusic
{
int playing;
@ -41,3 +44,5 @@ public:
void SetVolume( float flVolume );
float GetVolume();
};
#endif // INCLUDED_STEAM_MUSIC_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_MUSICREMOTE_H
#define INCLUDED_STEAM_MUSICREMOTE_H
class Steam_MusicRemote : public ISteamMusicRemote
{
public:
@ -65,3 +68,5 @@ public:
bool SetCurrentPlaylistEntry( int nID );
bool PlaylistDidChange();
};
#endif // INCLUDED_STEAM_MUSICREMOTE_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_NETWORKING_H
#define INCLUDED_STEAM_NETWORKING_H
//packet timeout in seconds for non connections
#define ORPHANED_PACKET_TIMEOUT (20)
#define NEW_CONNECTION_TIMEOUT (20.0)
@ -1026,3 +1029,5 @@ void Callback(Common_Message *msg)
}
}
};
#endif // INCLUDED_STEAM_NETWORKING_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_NETWORKING_MESSAGES
#define INCLUDED_STEAM_NETWORKING_MESSAGES
#define NETWORKING_MESSAGES_TIMEOUT 30.0
struct Steam_Message_Connection {
@ -444,3 +447,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_NETWORKING_MESSAGES

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_NETWORKING_SOCKETS_H
#define INCLUDED_STEAM_NETWORKING_SOCKETS_H
struct Listen_Socket {
HSteamListenSocket socket_id;
@ -881,7 +884,7 @@ SteamNetworkingMessage_t *get_steam_message_connection(HSteamNetConnection hConn
pMsg->m_pfnRelease = &delete_steam_message;
pMsg->m_nChannel = 0;
connect_socket->second.data.pop();
PRINT_DEBUG("get_steam_message_connection %u %u, %u\n", hConn, size, pMsg->m_nMessageNumber);
PRINT_DEBUG("get_steam_message_connection %u, %u, %" PRIu64 "\n", hConn, size, pMsg->m_nMessageNumber);
return pMsg;
}
@ -2086,13 +2089,13 @@ void Callback(Common_Message *msg)
auto connect_socket = s->connect_sockets.find(msg->networking_sockets().connection_id());
if (connect_socket != s->connect_sockets.end()) {
if (connect_socket->second.remote_identity.GetSteamID64() == msg->source_id() && (connect_socket->second.status == CONNECT_SOCKET_CONNECTED)) {
PRINT_DEBUG("Steam_Networking_Sockets: got data len %u, num %u on connection %u\n", msg->networking_sockets().data().size(), msg->networking_sockets().message_number(), connect_socket->first);
PRINT_DEBUG("Steam_Networking_Sockets: got data len %" PRI_ZU ", num %" PRIu64 " on connection %u\n", msg->networking_sockets().data().size(), msg->networking_sockets().message_number(), connect_socket->first);
connect_socket->second.data.push(msg->networking_sockets());
}
} else {
connect_socket = std::find_if(s->connect_sockets.begin(), s->connect_sockets.end(), [msg](const auto &in) {return in.second.remote_identity.GetSteamID64() == msg->source_id() && (in.second.status == CONNECT_SOCKET_NOT_ACCEPTED || in.second.status == CONNECT_SOCKET_CONNECTED) && in.second.remote_id == msg->networking_sockets().connection_id_from();});
if (connect_socket != s->connect_sockets.end()) {
PRINT_DEBUG("Steam_Networking_Sockets: got data len %u, num %u on not accepted connection %u\n", msg->networking_sockets().data().size(), msg->networking_sockets().message_number(), connect_socket->first);
PRINT_DEBUG("Steam_Networking_Sockets: got data len %" PRI_ZU ", num %" PRIu64 " on not accepted connection %u\n", msg->networking_sockets().data().size(), msg->networking_sockets().message_number(), connect_socket->first);
connect_socket->second.data.push(msg->networking_sockets());
}
}
@ -2110,3 +2113,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_NETWORKING_SOCKETS_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_NETWORKING_SOCKETS_SERIALIZED_H
#define INCLUDED_STEAM_NETWORKING_SOCKETS_SERIALIZED_H
class Steam_Networking_Sockets_Serialized :
public ISteamNetworkingSocketsSerialized002,
public ISteamNetworkingSocketsSerialized003,
@ -154,3 +157,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_NETWORKING_SOCKETS_SERIALIZED_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_NETWORKING_UTILS_H
#define INCLUDED_STEAM_NETWORKING_UTILS_H
class Steam_Networking_Utils :
public ISteamNetworkingUtils001,
public ISteamNetworkingUtils002,
@ -358,7 +361,7 @@ bool SetConnectionConfigValueString( HSteamNetConnection hConn, ESteamNetworking
bool SetConfigValue( ESteamNetworkingConfigValue eValue, ESteamNetworkingConfigScope eScopeType, intptr_t scopeObj,
ESteamNetworkingConfigDataType eDataType, const void *pArg )
{
PRINT_DEBUG("Steam_Networking_Utils::SetConfigValue %i %i %p %i %p\n", eValue, eScopeType, scopeObj, eDataType, pArg);
PRINT_DEBUG("Steam_Networking_Utils::SetConfigValue %i %i %" PRIuPTR " %i %p\n", eValue, eScopeType, scopeObj, eDataType, pArg);
return true;
}
@ -749,3 +752,5 @@ void Callback(Common_Message *msg)
};
#endif // INCLUDED_STEAM_NETWORKING_UTILS_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_PARENTAL_H
#define INCLUDED_STEAM_PARENTAL_H
class Steam_Parental : public ISteamParentalSettings
{
public:
@ -29,3 +32,5 @@ public:
bool BIsFeatureBlocked( EParentalFeature eFeature );
bool BIsFeatureInBlockList( EParentalFeature eFeature );
};
#endif // INCLUDED_STEAM_PARENTAL_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_PARTIES_H
#define INCLUDED_STEAM_PARTIES_H
class Steam_Parties :
public ISteamParties
{
@ -192,3 +195,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_PARTIES_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_REMOTE_STORAGE_H
#define INCLUDED_STEAM_REMOTE_STORAGE_H
struct Async_Read {
SteamAPICall_t api_call;
uint32 offset;
@ -791,3 +794,5 @@ bool EndFileWriteBatch()
};
#endif // INCLUDED_STEAM_REMOTE_STORAGE_H

202
dll/steam_remoteplay.cpp Normal file
View File

@ -0,0 +1,202 @@
/* Copyright (C) 2019 Mr Goldberg
This file is part of the Goldberg Emulator
The Goldberg Emulator is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
The Goldberg Emulator is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the Goldberg Emulator; if not, see
<http://www.gnu.org/licenses/>. */
#include "steam_remoteplay.h"
#include <string.h>
#include <limits.h>
typedef struct remote_play_session_info_T {
RemotePlaySessionID_t session_id;
CSteamID connected_user;
const char * client_name;
ESteamDeviceFormFactor client_form_factor;
int client_resolution_x;
int client_resolution_y;
} remote_play_session_info;
//TODO: NOT thread safe!!!
static std::vector<remote_play_session_info> remote_play_sessions;
int create_remote_play_session_info( RemotePlaySessionID_t session_id, CSteamID connected_user, const char * client_name, ESteamDeviceFormFactor client_form_factor, int client_resolution_x, int client_resolution_y ) {
remote_play_session_info session_info;
size_t buffer_length = 0;
char * buffer = NULL;
if ((remote_play_sessions.size() < UINT_MAX) && (client_name != NULL)) {
session_info.session_id = session_id;
session_info.connected_user = connected_user;
session_info.client_form_factor = client_form_factor;
session_info.client_resolution_x = client_resolution_x;
session_info.client_resolution_y = client_resolution_y;
buffer_length = strlen( client_name );
if (buffer_length > 0) {
buffer = new char[buffer_length + 1];
if (buffer != NULL) {
memcpy(buffer, client_name, buffer_length);
session_info.client_name = buffer;
remote_play_sessions.push_back( (const remote_play_session_info)session_info );
return 0;
}
}
}
return -1;
}
int destroy_remote_play_session_info( size_t index ) {
if (remote_play_sessions.size() < index) {
delete remote_play_sessions[index].client_name;
remote_play_sessions.erase(remote_play_sessions.begin() + index);
return 0;
}
return -1;
}
uint32 get_number_of_remote_play_sessions() {
return (uint32)remote_play_sessions.size();
}
int get_remote_play_session_id( size_t index, RemotePlaySessionID_t * session_id ) {
if ((session_id != NULL) && (index >= 0) && (remote_play_sessions.size() < index)) {
*session_id = remote_play_sessions[index].session_id;
return 0;
}
return -1;
}
int get_remote_play_session_index( RemotePlaySessionID_t session_id, size_t * index ) {
size_t count = 0;
if ((index != NULL) && (remote_play_sessions.size() > 0)) {
for (std::vector<remote_play_session_info>::iterator iter = remote_play_sessions.begin(); iter != remote_play_sessions.end(); iter++) {
if (iter->session_id == session_id) {
*index = count;
return 0;
}
count++;
}
}
return -1;
}
int get_remote_play_session_connected_user( size_t index, CSteamID * connected_user ) {
if ((connected_user != NULL) && (index >= 0) && (remote_play_sessions.size() < index)) {
*connected_user = remote_play_sessions[index].connected_user;
return 0;
}
return -1;
}
int get_remote_play_session_client_name( size_t index, const char ** client_name ) {
if ((client_name != NULL) && (index >= 0) && (remote_play_sessions.size() < index)) {
*client_name = remote_play_sessions[index].client_name;
return 0;
}
return -1;
}
int get_remote_play_session_client_form_factor( size_t index, ESteamDeviceFormFactor * client_form_factor ) {
if ((client_form_factor != NULL) && (index >= 0) && (remote_play_sessions.size() < index)) {
*client_form_factor = remote_play_sessions[index].client_form_factor;
return 0;
}
return -1;
}
int get_remote_play_session_client_resolutions( size_t index, int * client_resolution_x, int * client_resolution_y ) {
if ((client_resolution_x != NULL) && (client_resolution_y != NULL) && (index >= 0) && (remote_play_sessions.size() < index)) {
*client_resolution_x = remote_play_sessions[index].client_resolution_x;
*client_resolution_y = remote_play_sessions[index].client_resolution_y;
return 0;
}
return -1;
}
uint32 Steam_RemotePlay::GetSessionCount()
{
PRINT_DEBUG("Steam_RemotePlay::GetSessionCount\n");
return get_number_of_remote_play_sessions();
}
uint32 Steam_RemotePlay::GetSessionID( int iSessionIndex )
{
RemotePlaySessionID_t session_id;
PRINT_DEBUG("Steam_RemotePlay::GetSessionID\n");
return ((get_remote_play_session_id( iSessionIndex, &session_id ) == 0) ? (session_id) : (0));
}
CSteamID Steam_RemotePlay::GetSessionSteamID( uint32 unSessionID )
{
CSteamID steam_id = k_steamIDNil;
size_t index = 0;
PRINT_DEBUG("Steam_RemotePlay::GetSessionSteamID\n");
if (get_remote_play_session_index( unSessionID, &index ) == 0) {
if (get_remote_play_session_connected_user( index, &steam_id ) == 0) {
return steam_id;
}
}
return k_steamIDNil;
}
const char * Steam_RemotePlay::GetSessionClientName( uint32 unSessionID )
{
const char * client_name = NULL;
size_t index = 0;
PRINT_DEBUG("Steam_RemotePlay::GetSessionClientName\n");
if (get_remote_play_session_index( unSessionID, &index ) == 0) {
if (get_remote_play_session_client_name( index, &client_name ) == 0) {
return client_name;
}
}
return NULL;
}
ESteamDeviceFormFactor Steam_RemotePlay::GetSessionClientFormFactor( uint32 unSessionID )
{
ESteamDeviceFormFactor form_factor = k_ESteamDeviceFormFactorUnknown;
size_t index = 0;
PRINT_DEBUG("Steam_RemotePlay::GetSessionClientFormFactor\n");
if (get_remote_play_session_index( unSessionID, &index ) == 0) {
if (get_remote_play_session_client_form_factor( index, &form_factor ) == 0) {
return form_factor;
}
}
return k_ESteamDeviceFormFactorUnknown;
}
bool Steam_RemotePlay::BGetSessionClientResolution( uint32 unSessionID, int *pnResolutionX, int *pnResolutionY )
{
int x = 0;
int y = 0;
size_t index = 0;
PRINT_DEBUG("Steam_RemotePlay::BGetSessionClientResolution\n");
if ((pnResolutionX != NULL) && (pnResolutionY != NULL)) {
if (get_remote_play_session_index( unSessionID, &index ) == 0) {
if (get_remote_play_session_client_resolutions( index, &x, &y ) == 0) {
*pnResolutionX = x;
*pnResolutionY = y;
return true;
}
}
}
return false;
}

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_REMOTEPLAY_H
#define INCLUDED_STEAM_REMOTEPLAY_H
class Steam_RemotePlay :
public ISteamRemotePlay
{
@ -62,48 +65,24 @@ Steam_RemotePlay(class Settings *settings, class Networking *network, class Stea
}
// Get the number of currently connected Steam Remote Play sessions
uint32 GetSessionCount()
{
PRINT_DEBUG("Steam_RemotePlay::GetSessionCount\n");
return 0;
}
uint32 GetSessionCount();
// Get the currently connected Steam Remote Play session ID at the specified index. Returns zero if index is out of bounds.
uint32 GetSessionID( int iSessionIndex )
{
PRINT_DEBUG("Steam_RemotePlay::GetSessionID\n");
return 0;
}
uint32 GetSessionID( int iSessionIndex );
// Get the SteamID of the connected user
CSteamID GetSessionSteamID( uint32 unSessionID )
{
PRINT_DEBUG("Steam_RemotePlay::GetSessionSteamID\n");
return k_steamIDNil;
}
CSteamID GetSessionSteamID( uint32 unSessionID );
// Get the name of the session client device
// This returns NULL if the sessionID is not valid
const char *GetSessionClientName( uint32 unSessionID )
{
PRINT_DEBUG("Steam_RemotePlay::GetSessionClientName\n");
return NULL;
}
const char *GetSessionClientName( uint32 unSessionID );
// Get the form factor of the session client device
ESteamDeviceFormFactor GetSessionClientFormFactor( uint32 unSessionID )
{
PRINT_DEBUG("Steam_RemotePlay::GetSessionClientFormFactor\n");
return k_ESteamDeviceFormFactorUnknown;
}
ESteamDeviceFormFactor GetSessionClientFormFactor( uint32 unSessionID );
// Get the resolution, in pixels, of the session client device
// This is set to 0x0 if the resolution is not available
bool BGetSessionClientResolution( uint32 unSessionID, int *pnResolutionX, int *pnResolutionY )
{
PRINT_DEBUG("Steam_RemotePlay::BGetSessionClientResolution\n");
return false;
}
bool BGetSessionClientResolution( uint32 unSessionID, int *pnResolutionX, int *pnResolutionY );
// Invite a friend to Remote Play Together
// This returns false if the invite can't be sent
@ -135,3 +114,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_REMOTEPLAY_H

View File

@ -65,7 +65,7 @@ ScreenshotHandle Steam_Screenshots::AddScreenshotToLibrary( const char *pchFilen
if (pchFilename == nullptr)
return INVALID_SCREENSHOT_HANDLE;
std::vector<image_pixel_t> pixels(std::move(local_storage->load_image(pchFilename)));
std::vector<image_pixel_t> pixels(std::move(local_storage->load_image(pchFilename, NULL, NULL)));
if (pixels.size() != size_t(nWidth) * size_t(nHeight))
return INVALID_SCREENSHOT_HANDLE;

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_SCREENSHOTS_H
#define INCLUDED_STEAM_SCREENSHOTS_H
struct screenshot_infos_t
{
std::string screenshot_name;
@ -73,3 +76,5 @@ public:
// JPEG, TGA, and PNG formats are supported.
ScreenshotHandle AddVRScreenshotToLibrary( EVRScreenshotType eType, const char *pchFilename, const char *pchVRFilename );
};
#endif // INCLUDED_STEAM_SCREENSHOTS_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_TV_H
#define INCLUDED_STEAM_TV_H
class Steam_TV :
public ISteamTV
{
@ -122,3 +125,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_TV_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_UGC_H
#define INCLUDED_STEAM_UGC_H
struct UGC_query {
UGCQueryHandle_t handle;
std::set<PublishedFileId_t> return_only;
@ -600,13 +603,13 @@ bool RemoveItemPreview( UGCUpdateHandle_t handle, uint32 index )
bool AddContentDescriptor( UGCUpdateHandle_t handle, EUGCContentDescriptorID descid )
{
PRINT_DEBUG("Steam_UGC::AddContentDescriptor %llu %u\n", handle, index);
PRINT_DEBUG("Steam_UGC::AddContentDescriptor %llu %u\n", handle, descid);
return false;
}
bool RemoveContentDescriptor( UGCUpdateHandle_t handle, EUGCContentDescriptorID descid )
{
PRINT_DEBUG("Steam_UGC::RemoveContentDescriptor %llu %u\n", handle, index);
PRINT_DEBUG("Steam_UGC::RemoveContentDescriptor %llu %u\n", handle, descid);
return false;
}
@ -903,3 +906,5 @@ SteamAPICall_t GetWorkshopEULAStatus()
};
#endif // INCLUDED_STEAM_UGC_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_UNIFIED_MESSAGES_H
#define INCLUDED_STEAM_UNIFIED_MESSAGES_H
class Steam_Unified_Messages :
public ISteamUnifiedMessages
{
@ -121,3 +124,5 @@ void Callback(Common_Message *msg)
}
};
#endif // INCLUDED_STEAM_UNIFIED_MESSAGES_H

View File

@ -19,6 +19,9 @@
#include "appticket.h"
#ifndef INCLUDED_STEAM_USER_H
#define INCLUDED_STEAM_USER_H
class Steam_User :
public ISteamUser009,
public ISteamUser010,
@ -532,3 +535,5 @@ bool BSetDurationControlOnlineState( EDurationControlOnlineState eNewState )
}
};
#endif // INCLUDED_STEAM_USER_H

View File

@ -85,6 +85,8 @@ private:
nlohmann::json defined_achievements;
nlohmann::json user_achievements;
std::vector<std::string> sorted_achievement_names;
std::map<std::string, int32> achievement_image_data_normal;
std::map<std::string, int32> achievement_image_data_gray;
std::map<std::string, int32> stats_cache_int;
std::map<std::string, float> stats_cache_float;
@ -112,10 +114,136 @@ nlohmann::detail::iter_impl<nlohmann::json> defined_achievements_find(std::strin
});
}
int32 achievement_image_data_normal_find(std::string key) {
for (auto & it : achievement_image_data_normal) {
try {
if (it.first == key) {
return it.second;
}
} catch (...) {}
}
return 0;
}
int32 achievement_image_data_gray_find(std::string key) {
for (auto & it : achievement_image_data_gray) {
try {
if (it.first == key) {
return it.second;
}
} catch (...) {}
}
return 0;
}
void load_achievements_db()
{
uint64 count = 0;
uint64 bad_count = 0;
uint64 corrupt_count = 0;
uint64 missing_normal_images = 0;
uint64 missing_gray_images = 0;
uint64 unreadable_normal_images = 0;
uint64 unreadable_gray_images = 0;
std::string name = "";
std::string file_path = Local_Storage::get_game_settings_path() + achievements_user_file;
local_storage->load_json(file_path, defined_achievements);
for (auto & it : defined_achievements) {
name = "";
try {
auto name_it = it.find("name");
if (name_it != it.end()) {
name = static_cast<std::string const&>(*name_it);
}
if (name.length() > 0) {
auto normal_it = it.find("icon");
auto gray_it = it.find("icon_gray");
std::string normal = "";
std::string gray = "";
if (normal_it != it.end()) {
normal = Local_Storage::get_game_settings_path() + static_cast<std::string const&>(*normal_it);
}
if (gray_it != it.end()) {
gray = Local_Storage::get_game_settings_path() + static_cast<std::string const&>(*gray_it);
}
if (normal.length() > 0 && gray.length() > 0) {
uint32 normal_height = 0;
uint32 normal_width = 0;
uint32 gray_height = 0;
uint32 gray_width = 0;
std::vector<image_pixel_t> normal_pixels(local_storage->load_image(normal, &normal_width, &normal_height));
std::vector<image_pixel_t> gray_pixels(local_storage->load_image(gray, &gray_width, &gray_height));
if (normal_width > 0 && normal_height > 0 &&
gray_width > 0 && gray_height > 0) {
std::string normalStr;
std::string grayStr;
normalStr.reserve(sizeof(uint32_t) * normal_width * normal_height);
grayStr.reserve(sizeof(uint32_t) * gray_width * gray_height);
for (auto & pix : normal_pixels) {
normalStr += pix.channels.r;
normalStr += pix.channels.g;
normalStr += pix.channels.b;
normalStr += pix.channels.a;
}
for (auto & pix : gray_pixels) {
grayStr += pix.channels.r;
grayStr += pix.channels.g;
grayStr += pix.channels.b;
grayStr += pix.channels.a;
}
achievement_image_data_normal[name] = settings->add_image(normalStr, normal_width, normal_height);
achievement_image_data_gray[name] = settings->add_image(grayStr, gray_width, gray_height);
count++;
} else {
corrupt_count++;
if (normal_width <= 0 || normal_height <= 0)
unreadable_normal_images++;
if (gray_width <= 0 || gray_height <= 0)
unreadable_gray_images++;
PRINT_DEBUG("%s %s %s.\n",
"Unable to load images for achievement",
name.c_str(),
"unable to get resolution from images.");
}
} else {
corrupt_count++;
if (normal.length() <= 0)
missing_normal_images++;
if (gray.length() <= 0)
missing_gray_images++;
PRINT_DEBUG("%s %s %s.\n",
"Unable to load images for achievement",
name.c_str(),
"an image path is not configured");
}
} else {
bad_count++;
PRINT_DEBUG("%s %s %s %" PRIu64 " %s.\n",
"Invalid achievement json at",
file_path.c_str(),
"for achievement number",
count + corrupt_count + bad_count + 1,
"is invalid");
}
} catch (std::exception &e) {
bad_count++;
PRINT_DEBUG("Loading image data for achievement %s failed. Exception type: %s Reason: %s.\n",
(name.length() > 0) ? name.c_str() : "ERROR: NAME PARSING FROM JSON FAILED",
typeid(e).name(),
e.what());
}
}
PRINT_DEBUG("loaded %" PRIu64 " achievement images.\npartial loaded %" PRIu64 " achievements.\nskipped %" PRIu64 " invalid achievements.\n",
count,
corrupt_count,
bad_count);
PRINT_DEBUG("ignored %" PRIu64 " missing normal achievement images.\nignored %" PRIu64 " missing gray achievement images.\n",
missing_normal_images,
missing_gray_images);
PRINT_DEBUG("ignored %" PRIu64 " unreadable normal achievement images.\nignored %" PRIu64 " unreadable gray achievement images.\n",
unreadable_normal_images,
unreadable_gray_images);
}
void load_achievements()
@ -590,10 +718,18 @@ bool StoreStats()
int GetAchievementIcon( const char *pchName )
{
PRINT_DEBUG("GetAchievementIcon\n");
if (pchName == nullptr) return 0;
int ret = 0;
if (pchName == nullptr) return ret;
std::lock_guard<std::recursive_mutex> lock(global_mutex);
return 0;
bool achieved = false;
if ((GetAchievementAndUnlockTime(pchName, &achieved, NULL) == true) && (achieved == true)) {
ret = achievement_image_data_normal_find(pchName);
} else {
ret = achievement_image_data_gray_find(pchName);
}
return ret;
}

View File

@ -19,6 +19,9 @@
#include "local_storage.h"
#include "../overlay_experimental/steam_overlay.h"
#ifndef INCLUDED_STEAM_UTILS_H
#define INCLUDED_STEAM_UTILS_H
static std::chrono::time_point<std::chrono::steady_clock> app_initialized_time = std::chrono::steady_clock::now();
@ -113,7 +116,10 @@ bool GetImageRGBA( int iImage, uint8 *pubDest, int nDestBufferSize )
if (image == settings->images.end()) return false;
unsigned size = image->second.data.size();
if (nDestBufferSize < size) size = nDestBufferSize;
if (nDestBufferSize < size) {
PRINT_DEBUG("GetImageRGBA %i Given buffer too small. Got 0x%x bytes. Need 0x%x bytes.\n", iImage, nDestBufferSize, size);
size = nDestBufferSize;
}
image->second.data.copy((char *)pubDest, nDestBufferSize);
return true;
}
@ -442,3 +448,5 @@ bool DismissFloatingGamepadTextInput()
}
};
#endif // INCLUDED_STEAM_UTILS_H

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_VIDEO_H
#define INCLUDED_STEAM_VIDEO_H
class Steam_Video : public ISteamVideo
{
public:
@ -32,3 +35,5 @@ public:
void GetOPFSettings( AppId_t unVideoAppID );
bool GetOPFStringForApp( AppId_t unVideoAppID, char *pchBuffer, int32 *pnBufferSize );
};
#endif // INCLUDED_STEAM_VIDEO_H

View File

@ -25,6 +25,7 @@
// Nothing to be done here
#else
#define STEAM_API_FUNCTIONS_IMPL
#include "base.h"
#include "dll.h"
@ -34,6 +35,26 @@
const char *STEAM_PATH;
size_t STEAM_PATH_SIZE;
#ifndef __x86_64__
# define _STAT_VER_LINUX_OLD 1
# define _STAT_VER_KERNEL 1
# define _STAT_VER_SVR4 2
# define _STAT_VER_LINUX 3
# define _MKNOD_VER_LINUX 1
# define _MKNOD_VER_SVR4 2
#else
# define _STAT_VER_KERNEL 0
# define _STAT_VER_LINUX 1
# define _MKNOD_VER_LINUX 0
#endif
#define _STAT_VER _STAT_VER_LINUX
#define _MKNOD_VER _MKNOD_VER_LINUX
/* From kernel_stat.h It help me save some condition */
#define XSTAT_IS_XSTAT64 1
#define STATFS_IS_STATFS64 __STATFS_MATCHES_STATFS64
#define STAT_IS_KERNEL_STAT 1
// Returns a '/' terminated absolute path to the steam folder in user's home,
// root is returned if env home is not set
const char *get_steam_path()
@ -290,7 +311,16 @@ STEAMAPI_API int __wrap_access(const char *path, int mode)
STEAMAPI_API int __wrap___xstat(int ver, const char * path, struct stat * stat_buf)
{
const char *path_lowercased = lowercase_path(path, false, false);
int result = __xstat(ver, path_lowercased, stat_buf);
int result;
switch (ver) {
case _STAT_VER_KERNEL:
result = stat(path_lowercased, stat_buf);
break;
default:
result = EINVAL;
}
if (path_lowercased != path) {
free((void *)path_lowercased);
}
@ -305,7 +335,16 @@ STEAMAPI_API int __wrap_stat(const char * path, struct stat * stat_buf)
STEAMAPI_API int __wrap___lxstat(int ver, const char * path, struct stat * stat_buf)
{
const char *path_lowercased = lowercase_path(path, false, false);
int result = __lxstat(ver, path_lowercased, stat_buf);
int result;
switch (ver) {
case _STAT_VER_KERNEL:
result = lstat(path_lowercased, stat_buf);
break;
default:
result = EINVAL;
}
if (path_lowercased != path) {
free((void *)path_lowercased);
}
@ -350,7 +389,16 @@ STEAMAPI_API DIR *__wrap_opendir(const char *path)
STEAMAPI_API int __wrap___xstat64(int ver, const char *path, struct stat64 *stat_buf)
{
const char *path_lowercased = lowercase_path(path, false, false);
int result = __xstat64(ver, path_lowercased, stat_buf);
int result;
switch (ver) {
case _STAT_VER_KERNEL:
result = stat64(path_lowercased, stat_buf);
break;
default:
result = EINVAL;
}
if (path_lowercased != path) {
free((void *)path_lowercased);
}
@ -360,7 +408,16 @@ STEAMAPI_API int __wrap___xstat64(int ver, const char *path, struct stat64 *stat
STEAMAPI_API int __wrap___lxstat64(int ver, const char *path, struct stat64 *stat_buf)
{
const char *path_lowercased = lowercase_path(path, false, false);
int result = __lxstat64(ver, path_lowercased, stat_buf);
int result;
switch (ver) {
case _STAT_VER_KERNEL:
result = lstat64(path_lowercased, stat_buf);
break;
default:
result = EINVAL;
}
if (path_lowercased != path) {
free((void *)path_lowercased);
}
@ -448,7 +505,7 @@ STEAMAPI_API int __wrap_link(const char *path1, const char *path2)
STEAMAPI_API int __wrap_mknod(const char *path, mode_t mode, dev_t dev)
{
const char *path_lowercased = lowercase_path(path, true, true);
int result = __xmknod(1, path_lowercased, mode, &dev);
int result = mknod(path_lowercased, mode, dev);
if (path_lowercased != path) {
free((void *)path_lowercased);
}

View File

@ -0,0 +1,2 @@
192.168.7.99
removethis.test.domain.com

57
generate_all_deps.bat Normal file
View File

@ -0,0 +1,57 @@
@echo off
cd /d "%~dp0"
call generate_build_win.bat
IF EXIST build\all_deps\debug\x86\*.* ( DEL /F /S /Q build\all_deps\debug\x86\*.* )
IF EXIST build\all_deps\debug\x64\*.* ( DEL /F /S /Q build\all_deps\debug\x64\*.* )
IF EXIST build\all_deps\release\x86\*.* ( DEL /F /S /Q build\all_deps\release\x86\*.* )
IF EXIST build\all_deps\release\x64\*.* ( DEL /F /S /Q build\all_deps\release\x64\*.* )
call build_set_protobuf_directories.bat
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
SET OLD_DIR=%cd%
cd "build\all_deps\debug\x86"
cl /c @%CDS_DIR%/DEBUG.BLD @%CDS_DIR%/PROTOBUF_X86.BLD @%CDS_DIR%\ALL_DEPS.BLD
IF EXIST %CDS_DIR%\DEBUG_ALL_DEPS_X86.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_ALL_DEPS_X86.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_ALL_DEPS_X86.LKS
cd %OLD_DIR%
endlocal
setlocal
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
SET OLD_DIR=%cd%
cd "build\all_deps\debug\x64"
cl /c @%CDS_DIR%/DEBUG.BLD @%CDS_DIR%/PROTOBUF_X64.BLD @%CDS_DIR%\ALL_DEPS.BLD
IF EXIST %CDS_DIR%\DEBUG_ALL_DEPS_X64.LKS ( DEL /F /Q %CDS_DIR%\DEBUG_ALL_DEPS_X64.LKS )
where "*.obj" > %CDS_DIR%\DEBUG_ALL_DEPS_X64.LKS
cd %OLD_DIR%
endlocal
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
SET OLD_DIR=%cd%
cd "build\all_deps\release\x86"
cl /c @%CDS_DIR%/RELEASE.BLD @%CDS_DIR%/PROTOBUF_X86.BLD @%CDS_DIR%\ALL_DEPS.BLD
IF EXIST %CDS_DIR%\RELEASE_ALL_DEPS_X86.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_ALL_DEPS_X86.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_ALL_DEPS_X86.LKS
cd %OLD_DIR%
endlocal
setlocal
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x64.bat
SET OLD_DIR=%cd%
cd "build\all_deps\release\x64"
cl /c @%CDS_DIR%/RELEASE.BLD @%CDS_DIR%/PROTOBUF_X64.BLD @%CDS_DIR%\ALL_DEPS.BLD
IF EXIST %CDS_DIR%\RELEASE_ALL_DEPS_X64.LKS ( DEL /F /Q %CDS_DIR%\RELEASE_ALL_DEPS_X64.LKS )
where "*.obj" > %CDS_DIR%\RELEASE_ALL_DEPS_X64.LKS
cd %OLD_DIR%
endlocal
SET BUILT_ALL_DEPS=1

406
generate_build_win.bat Normal file
View File

@ -0,0 +1,406 @@
@echo off
REM Should be called from the root of the repo.
REM Make build and output dirs.
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\cmds ( mkdir build\cmds )
IF NOT EXIST build\debug ( mkdir build\debug )
IF NOT EXIST build\release ( mkdir build\release )
IF NOT EXIST build\all_deps ( mkdir build\all_deps )
IF NOT EXIST build\all_deps\debug ( mkdir build\all_deps\debug )
IF NOT EXIST build\all_deps\release ( mkdir build\all_deps\release )
IF NOT EXIST build\experimental ( mkdir build\experimental )
IF NOT EXIST build\experimental\debug ( mkdir build\experimental\debug )
IF NOT EXIST build\experimental\release ( mkdir build\experimental\release )
IF NOT EXIST build\experimental_steamclient ( mkdir build\experimental_steamclient )
IF NOT EXIST build\experimental_steamclient\debug ( mkdir build\experimental_steamclient\debug )
IF NOT EXIST build\experimental_steamclient\release ( mkdir build\experimental_steamclient\release )
IF NOT EXIST build\experimental_steamclient\steamclient_loader ( mkdir build\experimental_steamclient\steamclient_loader )
IF NOT EXIST build\experimental_steamclient\steamclient_loader\debug ( mkdir build\experimental_steamclient\steamclient_loader\debug )
IF NOT EXIST build\experimental_steamclient\steamclient_loader\release ( mkdir build\experimental_steamclient\steamclient_loader\release )
IF NOT EXIST build\lobby_connect\debug ( mkdir build\lobby_connect\debug )
IF NOT EXIST build\lobby_connect\release ( mkdir build\lobby_connect\release )
IF NOT EXIST build\tools ( mkdir build\tools )
IF NOT EXIST build\tools\debug ( mkdir build\tools\debug )
IF NOT EXIST build\tools\release ( mkdir build\tools\release )
IF NOT EXIST build\debug\x86 ( mkdir build\debug\x86 )
IF NOT EXIST build\debug\x64 ( mkdir build\debug\x64 )
IF NOT EXIST build\release\x86 ( mkdir build\release\x86 )
IF NOT EXIST build\release\x64 ( mkdir build\release\x64 )
IF NOT EXIST build\all_deps\debug\x86 ( mkdir build\all_deps\debug\x86 )
IF NOT EXIST build\all_deps\debug\x64 ( mkdir build\all_deps\debug\x64 )
IF NOT EXIST build\all_deps\release\x86 ( mkdir build\all_deps\release\x86 )
IF NOT EXIST build\all_deps\release\x64 ( mkdir build\all_deps\release\x64 )
IF NOT EXIST build\experimental\debug\x86 ( mkdir build\experimental\debug\x86 )
IF NOT EXIST build\experimental\debug\x64 ( mkdir build\experimental\debug\x64 )
IF NOT EXIST build\experimental\release\x86 ( mkdir build\experimental\release\x86 )
IF NOT EXIST build\experimental\release\x64 ( mkdir build\experimental\release\x64 )
IF NOT EXIST build\experimental_steamclient\debug\x86 ( mkdir build\experimental_steamclient\debug\x86 )
IF NOT EXIST build\experimental_steamclient\debug\x64 ( mkdir build\experimental_steamclient\debug\x64 )
IF NOT EXIST build\experimental_steamclient\release\x86 ( mkdir build\experimental_steamclient\release\x86 )
IF NOT EXIST build\experimental_steamclient\release\x64 ( mkdir build\experimental_steamclient\release\x64 )
IF NOT EXIST build\experimental_steamclient\debug\x86\deps ( mkdir build\experimental_steamclient\debug\x86\deps )
IF NOT EXIST build\experimental_steamclient\debug\x64\deps ( mkdir build\experimental_steamclient\debug\x64\deps )
IF NOT EXIST build\experimental_steamclient\release\x86\deps ( mkdir build\experimental_steamclient\release\x86\deps )
IF NOT EXIST build\experimental_steamclient\release\x64\deps ( mkdir build\experimental_steamclient\release\x64\deps )
IF NOT EXIST build\experimental_steamclient\debug\x86\sc_deps ( mkdir build\experimental_steamclient\debug\x86\sc_deps )
IF NOT EXIST build\experimental_steamclient\debug\x64\sc_deps ( mkdir build\experimental_steamclient\debug\x64\sc_deps )
IF NOT EXIST build\experimental_steamclient\release\x86\sc_deps ( mkdir build\experimental_steamclient\release\x86\sc_deps )
IF NOT EXIST build\experimental_steamclient\release\x64\sc_deps ( mkdir build\experimental_steamclient\release\x64\sc_deps )
IF NOT EXIST build\experimental_steamclient\steamclient_loader\debug\x86 ( mkdir build\experimental_steamclient\steamclient_loader\debug\x86 )
IF NOT EXIST build\experimental_steamclient\steamclient_loader\debug\x64 ( mkdir build\experimental_steamclient\steamclient_loader\debug\x64 )
IF NOT EXIST build\experimental_steamclient\steamclient_loader\release\x86 ( mkdir build\experimental_steamclient\steamclient_loader\release\x86 )
IF NOT EXIST build\experimental_steamclient\steamclient_loader\release\x64 ( mkdir build\experimental_steamclient\steamclient_loader\release\x64 )
IF NOT EXIST build\lobby_connect\debug\x86 ( mkdir build\lobby_connect\debug\x86 )
IF NOT EXIST build\lobby_connect\debug\x64 ( mkdir build\lobby_connect\debug\x64 )
IF NOT EXIST build\lobby_connect\release\x86 ( mkdir build\lobby_connect\release\x86 )
IF NOT EXIST build\lobby_connect\release\x64 ( mkdir build\lobby_connect\release\x64 )
IF NOT EXIST build\tools\debug\x86 ( mkdir build\tools\debug\x86 )
IF NOT EXIST build\tools\debug\x64 ( mkdir build\tools\debug\x64 )
IF NOT EXIST build\tools\release\x86 ( mkdir build\tools\release\x86 )
IF NOT EXIST build\tools\release\x64 ( mkdir build\tools\release\x64 )
IF NOT EXIST debug ( mkdir debug )
IF NOT EXIST debug\experimental ( mkdir debug\experimental )
IF NOT EXIST debug\experimental_steamclient ( mkdir debug\experimental_steamclient )
IF NOT EXIST debug\lobby_connect ( mkdir debug\lobby_connect )
IF NOT EXIST debug\tools ( mkdir debug\tools )
IF NOT EXIST release ( mkdir release )
IF NOT EXIST release\experimental ( mkdir release\experimental )
IF NOT EXIST release\experimental_steamclient ( mkdir release\experimental_steamclient )
IF NOT EXIST release\lobby_connect ( mkdir release\lobby_connect )
IF NOT EXIST release\tools ( mkdir release\tools )
SET CDS_DIR=%cd%\build\cmds
REM
REM Arguments.
REM
REM normal_args.
IF EXIST %CDS_DIR%\NORMAL_ARGS.ARG ( DEL /F /S /Q %CDS_DIR%\NORMAL_ARGS.ARG )
echo /EHsc > %CDS_DIR%\NORMAL_ARGS.ARG
echo /Ox >> %CDS_DIR%\NORMAL_ARGS.ARG
REM JOB ARGS.
IF "%JOB_COUNT%" == "" ( echo /MP1 >> %CDS_DIR%\NORMAL_ARGS.ARG )
IF NOT "%JOB_COUNT%" == "" ( echo /MP%JOB_COUNT% >> %CDS_DIR%\NORMAL_ARGS.ARG )
REM Debug args.
IF EXIST %CDS_DIR%\DEBUG.BLD ( DEL /F /S /Q %CDS_DIR%\DEBUG.BLD )
IF EXIST %CDS_DIR%\DEBUG.LKS ( DEL /F /S /Q %CDS_DIR%\DEBUG.LKS )
REM Create empty file. (No BUILD time args currently.)
type NUL >> %CDS_DIR%\DEBUG.BLD
REM DISABLE the PDB builds if we are running on the CI. (It can't build them currently.)
IF EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /DEBUG:NONE > %CDS_DIR%\DEBUG.LKS )
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /DEBUG:FULL /OPT:REF /OPT:ICF > %CDS_DIR%\DEBUG.LKS )
REM Release args.
IF EXIST %CDS_DIR%\RELEASE.ARG ( DEL /F /S /Q %CDS_DIR%\RELEASE.ARG )
IF EXIST %CDS_DIR%\RELEASE.LKS ( DEL /F /S /Q %CDS_DIR%\RELEASE.LKS )
REM Release mode Flags.
echo /DEMU_RELEASE_BUILD > %CDS_DIR%\RELEASE.ARG
echo /DNDEBUG >> %CDS_DIR%\RELEASE.ARG
copy %CDS_DIR%\RELEASE.ARG %CDS_DIR%\RELEASE.BLD
type %CDS_DIR%\RELEASE.ARG > %CDS_DIR%\RELEASE.LKS
REM DISABLE the PDB builds if we are running on the CI. (It can't build them currently.)
IF EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /DEBUG:NONE >> %CDS_DIR%\RELEASE.LKS )
IF NOT EXIST %OLD_DIR%\CI_BUILD.TAG ( echo /link /DEBUG:FULL /OPT:REF /OPT:ICF >> %CDS_DIR%\RELEASE.LKS )
REM BASE DLL Flags.
IF EXIST %CDS_DIR%\DLL_MAIN_CPP.ARG ( DEL /F /S /Q %CDS_DIR%\DLL_MAIN_CPP.ARG )
REM EXPERIMENTAL Flags.
IF EXIST %CDS_DIR%\EXPERIMENTAL.ARG ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL.ARG )
echo /DEMU_EXPERIMENTAL_BUILD > %CDS_DIR%\EXPERIMENTAL.ARG
echo /DCONTROLLER_SUPPORT >> %CDS_DIR%\EXPERIMENTAL.ARG
echo /DEMU_OVERLAY >> %CDS_DIR%\EXPERIMENTAL.ARG
REM EXPERIMENTAL_STEAMCLIENT Flags.
IF EXIST %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.ARG ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.ARG )
echo /DSTEAMCLIENT_DLL > %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.ARG
REM lobby_connect Flags.
IF EXIST %CDS_DIR%\LOBBY_CONNECT.ARG ( DEL /F /S /Q %CDS_DIR%\LOBBY_CONNECT.ARG )
echo /DNO_DISK_WRITES > %CDS_DIR%\LOBBY_CONNECT.ARG
echo /DLOBBY_CONNECT >> %CDS_DIR%\LOBBY_CONNECT.ARG
REM
REM Includes.
REM
REM protobuf.
call build_set_protobuf_directories.bat
IF EXIST %CDS_DIR%\PROTOBUF_X86.ICD ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X86.ICD )
IF EXIST %CDS_DIR%\PROTOBUF_X64.ICD ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X64.ICD )
setlocal
SET TEST_A=%cd%
cd %PROTOBUF_X86_DIRECTORY%
SET TEST_B=%cd%\include
cd %TEST_A%
echo /I%TEST_B% > %CDS_DIR%\PROTOBUF_X86.ICD
endlocal
setlocal
SET TEST_A=%cd%
cd %PROTOBUF_X64_DIRECTORY%
SET TEST_B=%cd%\include
cd %TEST_A%
echo /I%TEST_B% > %CDS_DIR%\PROTOBUF_X64.ICD
endlocal
REM OVERLAY_EXPERIMENTAL.
IF EXIST %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD ( DEL /F /S /Q %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD )
echo /I%cd%\overlay_experimental > %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD
REM IMGUI.
IF EXIST %CDS_DIR%\IMGUI.ICD ( DEL /F /S /Q %CDS_DIR%\IMGUI.ICD )
echo /I%cd%\ImGui > %CDS_DIR%\IMGUI.ICD
REM
REM Link Libraries.
REM
REM protobuf.
IF EXIST %CDS_DIR%\PROTOBUF_X86.OS ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X86.OS )
IF EXIST %CDS_DIR%\PROTOBUF_X64.OS ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X64.OS )
dir /b /s %PROTOBUF_X86_LIBRARY% > %CDS_DIR%\PROTOBUF_X86.OS
dir /b /s %PROTOBUF_X64_LIBRARY% > %CDS_DIR%\PROTOBUF_X64.OS
REM BASE DLL.
IF EXIST %CDS_DIR%\DLL_MAIN_CPP.OS ( DEL /F /S /Q %CDS_DIR%\DLL_MAIN_CPP.OS )
echo dbghelp.lib > %CDS_DIR%\DLL_MAIN_CPP.OS
echo Iphlpapi.lib >> %CDS_DIR%\DLL_MAIN_CPP.OS
echo Ws2_32.lib >> %CDS_DIR%\DLL_MAIN_CPP.OS
echo Shell32.lib >> %CDS_DIR%\DLL_MAIN_CPP.OS
echo advapi32.lib >> %CDS_DIR%\DLL_MAIN_CPP.OS
REM EXPERIMENTAL.
IF EXIST %CDS_DIR%\EXPERIMENTAL.OS ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL.OS )
echo Faultrep.lib > %CDS_DIR%\EXPERIMENTAL.OS
echo opengl32.lib >> %CDS_DIR%\EXPERIMENTAL.OS
echo Winmm.lib >> %CDS_DIR%\EXPERIMENTAL.OS
REM steamclient_loader.
IF EXIST %CDS_DIR%\STEAMCLIENT_LOADER.OS ( DEL /F /S /Q %CDS_DIR%\STEAMCLIENT_LOADER.OS )
echo advapi32.lib > %CDS_DIR%\STEAMCLIENT_LOADER.OS
echo user32.lib >> %CDS_DIR%\STEAMCLIENT_LOADER.OS
REM lobby_connect.
IF EXIST %CDS_DIR%\LOBBY_CONNECT.OS ( DEL /F /S /Q %CDS_DIR%\LOBBY_CONNECT.OS )
echo Comdlg32.lib > %CDS_DIR%\LOBBY_CONNECT.OS
REM
REM Files.
REM
REM Protobuf.
REM Needs to be compiled here (really just needs to exist), as we include it below.
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
REM OVERLAY_EXPERIMENTAL.
IF EXIST %CDS_DIR%\OVERLAY_EXPERIMENTAL.FLS ( DEL /F /S /Q %CDS_DIR%\OVERLAY_EXPERIMENTAL.FLS )
IF EXIST %CDS_DIR%\OVERLAY_EXPERIMENTAL_SYSTEM.FLS ( DEL /F /S /Q %CDS_DIR%\OVERLAY_EXPERIMENTAL_SYSTEM.FLS )
where "%cd%\overlay_experimental\:*.cpp" > %CDS_DIR%\OVERLAY_EXPERIMENTAL.FLS
where "%cd%\overlay_experimental\windows\:*.cpp" >> %CDS_DIR%\OVERLAY_EXPERIMENTAL.FLS
where "%cd%\overlay_experimental\System\:*.cpp" >> %CDS_DIR%\OVERLAY_EXPERIMENTAL_SYSTEM.FLS
REM IMGUI.
IF EXIST %CDS_DIR%\IMGUI.FLS ( DEL /F /S /Q %CDS_DIR%\IMGUI.FLS )
where "%cd%\ImGui\:*.cpp" > %CDS_DIR%\IMGUI.FLS
where "%cd%\ImGui\backends\:imgui_impl_dx*.cpp" >> %CDS_DIR%\IMGUI.FLS
where "%cd%\ImGui\backends\:imgui_impl_win32.cpp" >> %CDS_DIR%\IMGUI.FLS
where "%cd%\ImGui\backends\:imgui_impl_vulkan.cpp" >> %CDS_DIR%\IMGUI.FLS
where "%cd%\ImGui\backends\:imgui_impl_opengl3.cpp" >> %CDS_DIR%\IMGUI.FLS
where "%cd%\ImGui\backends\:imgui_win_shader_blobs.cpp" >> %CDS_DIR%\IMGUI.FLS
REM DETOURS.
IF EXIST %CDS_DIR%\DETOURS.FLS ( DEL /F /S /Q %CDS_DIR%\DETOURS.FLS )
where "%cd%\detours\:*.cpp" > %CDS_DIR%\DETOURS.FLS
REM CONTROLLER.
IF EXIST %CDS_DIR%\CONTROLLER.FLS ( DEL /F /S /Q CONTROLLER.FLS )
where "%cd%\controller\:gamepad.c" > %CDS_DIR%\CONTROLLER.FLS
REM sc_different_deps.
IF EXIST %CDS_DIR%\SC_DIFFERENT_DEPS.FLS ( DEL /F /S /Q %CDS_DIR%\SC_DIFFERENT_DEPS.FLS )
where "%cd%\dll\:flat.cpp" > %CDS_DIR%\SC_DIFFERENT_DEPS.FLS
where "%cd%\dll\:dll.cpp" >> %CDS_DIR%\SC_DIFFERENT_DEPS.FLS
REM BASE DLL.
IF EXIST %CDS_DIR%\DLL_MAIN_CPP.FLS ( DEL /F /S /Q %CDS_DIR%\DLL_MAIN_CPP.FLS )
move %cd%\dll\flat.cpp %cd%\dll\flat.cpp.tmp
move %cd%\dll\dll.cpp %cd%\dll\dll.cpp.tmp
where "%cd%\dll\:*.cpp" > %CDS_DIR%\DLL_MAIN_CPP.FLS
move %cd%\dll\flat.cpp.tmp %cd%\dll\flat.cpp
move %cd%\dll\dll.cpp.tmp %cd%\dll\dll.cpp
where "%cd%\dll\:*.cc" >> %CDS_DIR%\DLL_MAIN_CPP.FLS
REM SteamClient.
IF EXIST %CDS_DIR%\STEAMCLIENT.FLS ( DEL /F /S /Q %CDS_DIR%\STEAMCLIENT.FLS )
where "%cd%\:steamclient.cpp" > %CDS_DIR%\STEAMCLIENT.FLS
REM steamclient_loader.
IF EXIST %CDS_DIR%\STEAMCLIENT_LOADER.FLS ( DEL /F /S /Q %CDS_DIR%\STEAMCLIENT_LOADER.FLS )
where "%cd%\steamclient_loader\:*.cpp" > %CDS_DIR%\STEAMCLIENT_LOADER.FLS
REM lobby_connect.
IF EXIST %CDS_DIR%\LOBBY_CONNECT.FLS ( DEL /F /S /Q %CDS_DIR%\LOBBY_CONNECT.FLS )
where "%cd%\:lobby_connect.cpp" > %CDS_DIR%\LOBBY_CONNECT.FLS
REM generate_interfaces_file.
IF EXIST %CDS_DIR%\GENERATE_INTERFACES_FILE.FLS ( DEL /F /S /Q %CDS_DIR%\GENERATE_INTERFACES_FILE.FLS )
where "%cd%\:generate_interfaces_file.cpp" > %CDS_DIR%\GENERATE_INTERFACES_FILE.FLS
REM
REM Build and link cmd script files.
REM
REM protobuf.
IF EXIST %CDS_DIR%\PROTOBUF_X86.BLD ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X86.BLD )
IF EXIST %CDS_DIR%\PROTOBUF_X86.LKS ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X86.LKS )
type %CDS_DIR%\PROTOBUF_X86.ICD > %CDS_DIR%\PROTOBUF_X86.BLD
type %CDS_DIR%\PROTOBUF_X86.BLD > %CDS_DIR%\PROTOBUF_X86.LKS
type %CDS_DIR%\PROTOBUF_X86.OS >> %CDS_DIR%\PROTOBUF_X86.LKS
IF EXIST %CDS_DIR%\PROTOBUF_X64.BLD ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X64.BLD )
IF EXIST %CDS_DIR%\PROTOBUF_X64.LKS ( DEL /F /S /Q %CDS_DIR%\PROTOBUF_X64.LKS )
type %CDS_DIR%\PROTOBUF_X64.ICD > %CDS_DIR%\PROTOBUF_X64.BLD
type %CDS_DIR%\PROTOBUF_X64.BLD > %CDS_DIR%\PROTOBUF_X64.LKS
type %CDS_DIR%\PROTOBUF_X64.OS >> %CDS_DIR%\PROTOBUF_X64.LKS
REM SC_DEPS
IF EXIST %CDS_DIR%\SC_DEPS.BLD ( DEL /F /S /Q %CDS_DIR%\SC_DEPS.BLD )
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\SC_DEPS.BLD
type %CDS_DIR%\EXPERIMENTAL.ARG >> %CDS_DIR%\SC_DEPS.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD >> %CDS_DIR%\SC_DEPS.BLD
type %CDS_DIR%\IMGUI.ICD >> %CDS_DIR%\SC_DEPS.BLD
type %CDS_DIR%\DLL_MAIN_CPP.FLS >> %CDS_DIR%\SC_DEPS.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL.FLS >> %CDS_DIR%\SC_DEPS.BLD
REM DEPS
IF EXIST %CDS_DIR%\DEPS.BLD ( DEL /F /S /Q %CDS_DIR%\DEPS.BLD )
type %CDS_DIR%\DETOURS.FLS >> %CDS_DIR%\DEPS.BLD
type %CDS_DIR%\CONTROLLER.FLS >> %CDS_DIR%\DEPS.BLD
type %CDS_DIR%\IMGUI.FLS >> %CDS_DIR%\DEPS.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL_SYSTEM.FLS >> %CDS_DIR%\DEPS.BLD
REM all_deps.
IF EXIST %CDS_DIR%\ALL_DEPS.BLD ( DEL /F /S /Q %CDS_DIR%\ALL_DEPS.BLD )
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\ALL_DEPS.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD >> %CDS_DIR%\ALL_DEPS.BLD
type %CDS_DIR%\IMGUI.ICD >> %CDS_DIR%\ALL_DEPS.BLD
type %CDS_DIR%\DETOURS.FLS >> %CDS_DIR%\ALL_DEPS.BLD
type %CDS_DIR%\CONTROLLER.FLS >> %CDS_DIR%\ALL_DEPS.BLD
type %CDS_DIR%\IMGUI.FLS >> %CDS_DIR%\ALL_DEPS.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL_SYSTEM.FLS >> %CDS_DIR%\ALL_DEPS.BLD
REM BASE DLL.
IF EXIST %CDS_DIR%\DLL_MAIN_CPP.BLD ( DEL /F /S /Q %CDS_DIR%\DLL_MAIN_CPP.BLD )
IF EXIST %CDS_DIR%\DLL_MAIN_CPP.LKS ( DEL /F /S /Q %CDS_DIR%\DLL_MAIN_CPP.LKS )
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\DLL_MAIN_CPP.BLD
type %CDS_DIR%\DLL_MAIN_CPP.FLS >> %CDS_DIR%\DLL_MAIN_CPP.BLD
type %CDS_DIR%\SC_DIFFERENT_DEPS.FLS >> %CDS_DIR%\DLL_MAIN_CPP.BLD
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\DLL_MAIN_CPP.LKS
type %CDS_DIR%\DLL_MAIN_CPP.OS >> %CDS_DIR%\DLL_MAIN_CPP.LKS
REM EXPERIMENTAL.
IF EXIST %CDS_DIR%\EXPERIMENTAL.BLD ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL.BLD )
IF EXIST %CDS_DIR%\EXPERIMENTAL.LKS ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL.LKS )
REM Note the order and repeats. cl will complain if this gets messed up.
REM OLD SCRIPT.
REM type NORMAL_ARGS.ARG > EXPERIMENTAL.BLD
REM type EXPERIMENTAL.ARG >> EXPERIMENTAL.BLD
REM type EXPERIMENTAL.ICD >> EXPERIMENTAL.BLD
REM type DLL_MAIN_CPP.FLS >> EXPERIMENTAL.BLD
REM type SC_DIFFERENT_DEPS.FLS >> EXPERIMENTAL.BLD
REM type OVERLAY_EXPERIMENTAL.FLS >> EXPERIMENTAL.BLD
REM type OVERLAY_EXPERIMENTAL_SYSTEM.FLS >> EXPERIMENTAL.BLD
REM type DETOURS.FLS >> EXPERIMENTAL.BLD
REM type CONTROLLER.FLS >> EXPERIMENTAL.BLD
REM type IMGUI.FLS >> EXPERIMENTAL.BLD
REM type NORMAL_ARGS.ARG > EXPERIMENTAL.LKS
REM type EXPERIMENTAL.ARG >> EXPERIMENTAL.LKS
REM type EXPERIMENTAL.ICD >> EXPERIMENTAL.LKS
REM type DLL_MAIN_CPP.OS >> EXPERIMENTAL.LKS
REM type EXPERIMENTAL.OS >> EXPERIMENTAL.LKS
REM NEW Combined experimental && experimental_steamclient SCRIPT.
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\EXPERIMENTAL.BLD
type %CDS_DIR%\EXPERIMENTAL.ARG >> %CDS_DIR%\EXPERIMENTAL.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD >> %CDS_DIR%\EXPERIMENTAL.BLD
type %CDS_DIR%\IMGUI.ICD >> %CDS_DIR%\EXPERIMENTAL.BLD
type %CDS_DIR%\SC_DIFFERENT_DEPS.FLS >> %CDS_DIR%\EXPERIMENTAL.BLD
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\EXPERIMENTAL.LKS
type %CDS_DIR%\EXPERIMENTAL.ARG >> %CDS_DIR%\EXPERIMENTAL.LKS
type %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD >> %CDS_DIR%\EXPERIMENTAL.LKS
type %CDS_DIR%\IMGUI.ICD >> %CDS_DIR%\EXPERIMENTAL.LKS
type %CDS_DIR%\DLL_MAIN_CPP.OS >> %CDS_DIR%\EXPERIMENTAL.LKS
type %CDS_DIR%\EXPERIMENTAL.OS >> %CDS_DIR%\EXPERIMENTAL.LKS
REM SteamClient.
IF EXIST %CDS_DIR%\STEAMCLIENT.BLD ( DEL /F /S /Q %CDS_DIR%\STEAMCLIENT.BLD )
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\STEAMCLIENT.BLD
type %CDS_DIR%\EXPERIMENTAL.ARG >> %CDS_DIR%\STEAMCLIENT.BLD
type %CDS_DIR%\OVERLAY_EXPERIMENTAL.ICD >> %CDS_DIR%\STEAMCLIENT.BLD
type %CDS_DIR%\IMGUI.ICD >> %CDS_DIR%\STEAMCLIENT.BLD
type %CDS_DIR%\STEAMCLIENT.FLS >> %CDS_DIR%\STEAMCLIENT.BLD
REM EXPERIMENTAL_STEAMCLIENT.
IF EXIST %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.BLD ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.BLD )
IF EXIST %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS ( DEL /F /S /Q %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS )
REM Note the order and repeats. cl will complain if this gets messed up.
REM FULL
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS
type %CDS_DIR%\EXPERIMENTAL.ARG >> %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS
type %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.ARG >> %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS
type %CDS_DIR%\SC_DIFFERENT_DEPS.FLS >> %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS
type %CDS_DIR%\DLL_MAIN_CPP.OS >> %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS
type %CDS_DIR%\EXPERIMENTAL.OS >> %CDS_DIR%\EXPERIMENTAL_STEAMCLIENT.LKS
REM steamclient_loader.
IF EXIST %CDS_DIR%\STEAMCLIENT_LOADER.BLD ( DEL /F /S /Q %CDS_DIR%\STEAMCLIENT_LOADER.BLD )
IF EXIST %CDS_DIR%\STEAMCLIENT_LOADER.LKS ( DEL /F /S /Q %CDS_DIR%\STEAMCLIENT_LOADER.LKS )
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\STEAMCLIENT_LOADER.BLD
type %CDS_DIR%\STEAMCLIENT_LOADER.FLS >> %CDS_DIR%\STEAMCLIENT_LOADER.BLD
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\STEAMCLIENT_LOADER.LKS
type %CDS_DIR%\STEAMCLIENT_LOADER.OS >> %CDS_DIR%\STEAMCLIENT_LOADER.LKS
REM lobby_connect.
IF EXIST %CDS_DIR%\LOBBY_CONNECT.BLD ( DEL /F /S /Q %CDS_DIR%\LOBBY_CONNECT.BLD )
IF EXIST %CDS_DIR%\LOBBY_CONNECT.LKS ( DEL /F /S /Q %CDS_DIR%\LOBBY_CONNECT.LKS )
type %CDS_DIR%\LOBBY_CONNECT.ARG > %CDS_DIR%\LOBBY_CONNECT.BLD
type %CDS_DIR%\NORMAL_ARGS.ARG >> %CDS_DIR%\LOBBY_CONNECT.BLD
type %CDS_DIR%\LOBBY_CONNECT.FLS >> %CDS_DIR%\LOBBY_CONNECT.BLD
type %CDS_DIR%\DLL_MAIN_CPP.FLS >> %CDS_DIR%\LOBBY_CONNECT.BLD
type %CDS_DIR%\SC_DIFFERENT_DEPS.FLS >> %CDS_DIR%\LOBBY_CONNECT.BLD
type %CDS_DIR%\LOBBY_CONNECT.ARG > %CDS_DIR%\LOBBY_CONNECT.LKS
type %CDS_DIR%\NORMAL_ARGS.ARG >> %CDS_DIR%\LOBBY_CONNECT.LKS
type %CDS_DIR%\DLL_MAIN_CPP.OS >> %CDS_DIR%\LOBBY_CONNECT.LKS
type %CDS_DIR%\LOBBY_CONNECT.OS >> %CDS_DIR%\LOBBY_CONNECT.LKS
REM GENERATE_INTERFACES_FILE
IF EXIST %CDS_DIR%\GENERATE_INTERFACES_FILE.BLD ( DEL /F /S /Q %CDS_DIR%\GENERATE_INTERFACES_FILE.BLD )
IF EXIST %CDS_DIR%\GENERATE_INTERFACES_FILE.LKS ( DEL /F /S /Q %CDS_DIR%\GENERATE_INTERFACES_FILE.LKS )
type %CDS_DIR%\NORMAL_ARGS.ARG >> %CDS_DIR%\GENERATE_INTERFACES_FILE.BLD
type %CDS_DIR%\GENERATE_INTERFACES_FILE.FLS >> %CDS_DIR%\GENERATE_INTERFACES_FILE.BLD
type %CDS_DIR%\NORMAL_ARGS.ARG > %CDS_DIR%\GENERATE_INTERFACES_FILE.LKS

View File

@ -1,127 +0,0 @@
import os
def files_from_dir(dir, extension, filter=[]):
out = []
for f in os.listdir(dir):
if f.endswith(extension) and f not in filter:
out.append(os.path.join(dir, f))
return out
def convert_to_obj(files, obj_dir):
out = []
for f in files:
out.append(os.path.join(obj_dir, os.path.splitext(os.path.basename(f))[0] + ".obj"))
return out
def cl_line_obj(arguments, out_dir):
return "rmdir /S /Q {0}\nmkdir {0}\ncl /Fo:{0}/ /c {1}\n".format(out_dir, ' '.join(arguments))
def cl_line_link(arguments, linker_arguments):
return "cl /LD {} /link {}\n".format(' '.join(arguments), ' '.join(linker_arguments))
def cl_line_exe(arguments, linker_arguments):
return "cl {} /link {}\n".format(' '.join(arguments), ' '.join(linker_arguments))
jobs = 4
normal_build_args = ["/EHsc", "/Ox", "/MP{}".format(jobs)]
includes = ["ImGui", "overlay_experimental"]
includes_32 = list(map(lambda a: '/I{}'.format(a), ["%PROTOBUF_X86_DIRECTORY%\\include\\"] + includes))
includes_64 = list(map(lambda a: '/I{}'.format(a), ["%PROTOBUF_X64_DIRECTORY%\\include\\"] + includes))
debug_build_args = []
release_build_args = ["/DEMU_RELEASE_BUILD", "/DNDEBUG"]
steamclient_build_args = ["/DSTEAMCLIENT_DLL"]
experimental_build_args = ["/DEMU_EXPERIMENTAL_BUILD", "/DCONTROLLER_SUPPORT", "/DEMU_OVERLAY"]
steamclient_experimental_build_args = experimental_build_args + steamclient_build_args
normal_linker_libs = ["Iphlpapi.lib", "Ws2_32.lib", "rtlgenrandom.lib", "Shell32.lib"]
experimental_linker_libs = ["opengl32.lib", "Winmm.lib"] + normal_linker_libs
linker_32 = ['"%PROTOBUF_X86_LIBRARY%"']
linker_64 = ['"%PROTOBUF_X64_LIBRARY%"']
controller_deps = ["controller/gamepad.c"]
imgui_deps = files_from_dir("ImGui", ".cpp") + ["ImGui/backends/imgui_impl_dx9.cpp", "ImGui/backends/imgui_impl_dx10.cpp", "ImGui/backends/imgui_impl_dx11.cpp", "ImGui/backends/imgui_impl_dx12.cpp", "ImGui/backends/imgui_impl_win32.cpp", "ImGui/backends/imgui_impl_vulkan.cpp", "ImGui/backends/imgui_impl_opengl3.cpp", "ImGui/backends/imgui_win_shader_blobs.cpp"]
proto_deps = list(map(lambda a: a.replace(".proto", ".pb.cc"), files_from_dir("dll", ".proto")))
all_deps = proto_deps + files_from_dir("detours", ".cpp") + controller_deps + imgui_deps + files_from_dir("overlay_experimental/System", ".cpp")
sc_different_deps = ["flat.cpp", "dll.cpp"]
steam_deps = files_from_dir("dll", ".cpp", sc_different_deps)
overlay_deps = files_from_dir("overlay_experimental", ".cpp") + files_from_dir("overlay_experimental/windows", ".cpp")
experimental_steam_deps = steam_deps + overlay_deps
sc_different_deps = list(map(lambda a: "dll/" + a, sc_different_deps))
regular_files = []
head = """@echo off
cd /d "%~dp0"
rmdir /S /Q release
mkdir release
mkdir release\experimental
mkdir release\experimental_steamclient
mkdir release\debug_experimental
mkdir release\debug_experimental_steamclient
call build_set_protobuf_directories.bat
"""
head_32bit = """"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\\net.proto
call build_env_x86.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
"""
head_64bit = """"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\\net.proto
call build_env_x64.bat
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
"""
footer = """
copy Readme_release.txt release\Readme.txt
xcopy /s files_example\* release\\
copy Readme_experimental.txt release\experimental\Readme.txt
copy Readme_debug.txt release\debug_experimental\Readme.txt
copy steamclient_loader\ColdClientLoader.ini release\experimental_steamclient\\
call build_win_lobby_connect.bat
call build_win_find_interfaces.bat
"""
out = head
out += head_32bit
deps_folder = "deps"
sc_deps_folder = "deps_sc"
def generate_common(include_arch, linker_arch, steam_api_name, steamclient_name):
out = ""
out += cl_line_obj(normal_build_args + release_build_args + include_arch + all_deps, deps_folder)
out += cl_line_link(normal_build_args + release_build_args + include_arch + steam_deps + sc_different_deps + ["deps/net.pb.obj"] + linker_arch + normal_linker_libs, ["/debug:none", "/OUT:release\\{}".format(steam_api_name)])
debug_full_args = normal_build_args + debug_build_args + experimental_build_args + include_arch
out += cl_line_obj(debug_full_args + experimental_steam_deps, sc_deps_folder)
debug_full_dll_args = debug_full_args + sc_different_deps + convert_to_obj(all_deps, deps_folder) + convert_to_obj(experimental_steam_deps, sc_deps_folder) + linker_arch + experimental_linker_libs
out += cl_line_link(debug_full_dll_args, ["/OUT:release\debug_experimental\\{}".format(steam_api_name)])
out += cl_line_link(steamclient_build_args + debug_full_dll_args, ["/OUT:release\debug_experimental_steamclient\\{}".format(steamclient_name)])
release_full_args = normal_build_args + release_build_args + experimental_build_args + include_arch
out += cl_line_obj(release_full_args + experimental_steam_deps, sc_deps_folder)
release_full_dll_args = release_full_args + sc_different_deps + convert_to_obj(all_deps, deps_folder) + convert_to_obj(experimental_steam_deps, sc_deps_folder) + linker_arch + experimental_linker_libs
out += cl_line_link(release_full_dll_args, ["/debug:none", "/OUT:release\experimental\\{}".format(steam_api_name)])
out += cl_line_link(steamclient_build_args + release_full_dll_args, ["/debug:none", "/OUT:release\experimental_steamclient\\{}".format(steamclient_name)])
out += cl_line_link(release_build_args + experimental_build_args + ["steamclient.cpp"] + normal_build_args, ["/debug:none", "/OUT:release\experimental\\{}".format(steamclient_name)])
return out
out += generate_common(includes_32, linker_32, "steam_api.dll", "steamclient.dll")
out += cl_line_exe(files_from_dir("steamclient_loader", ".cpp") + ["advapi32.lib", "user32.lib"] + normal_build_args, ["/debug:none", "/OUT:release\experimental_steamclient\steamclient_loader.exe"])
out += head_64bit
out += generate_common(includes_64, linker_64, "steam_api64.dll", "steamclient64.dll")
out += footer
with open("build_win_release_test.bat", "w") as f:
f.write(out)

View File

@ -32,93 +32,113 @@
#else
#endif
int main() {
int main(int argc, char ** argv) {
bool broadcast_relay_daemon = false;
if (argc > 1) {
for (int x = 1; x < argc; x++) {
if (strcmp(argv[x], "-d") == 0) {
broadcast_relay_daemon = true;
}
}
}
if (SteamAPI_Init()) {
//Set appid to: LOBBY_CONNECT_APPID
SteamAPI_RestartAppIfNecessary(LOBBY_CONNECT_APPID);
std::cout << "This is a program to find lobbies and run the game with lobby connect parameters" << std::endl;
std::cout << "Api initialized, ";
if (broadcast_relay_daemon) {
std::cout << "Running in relay daemon mode. Press Ctrl+C to exit...." << std::endl;
std::cout.flush();
while (1) {
SteamAPI_RunCallbacks();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
} else {
std::cout << "This is a program to find lobbies and run the game with lobby connect parameters" << std::endl;
std::cout << "Api initialized, ";
top:
std::cout << "waiting a few seconds for connections:" << std::endl;
for (int i = 0; i < 10; ++i) {
SteamAPI_RunCallbacks();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
std::cout << "waiting a few seconds for connections:" << std::endl;
for (int i = 0; i < 10; ++i) {
SteamAPI_RunCallbacks();
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
int friend_count = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
std::cout << "People on the network: " << friend_count << std::endl;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
int friend_count = SteamFriends()->GetFriendCount(k_EFriendFlagAll);
std::cout << "People on the network: " << friend_count << std::endl;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
std::cout << name << " is playing: " << friend_info.m_gameID.AppID() << std::endl;
}
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
std::cout << name << " is playing: " << friend_info.m_gameID.AppID() << std::endl;
}
std::cout << std::endl << "--------------Menu-------------" << std::endl << "\tappid\tname\tcommand line" << std::endl;
std::cout << std::endl << "--------------Menu-------------" << std::endl << "\tappid\tname\tcommand line" << std::endl;
std::vector<std::string> arguments;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
const char *connect = SteamFriends()->GetFriendRichPresence( id, "connect");
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
std::vector<std::string> arguments;
for (int i = 0; i < friend_count; ++i) {
CSteamID id = SteamFriends()->GetFriendByIndex(i, k_EFriendFlagAll);
const char *name = SteamFriends()->GetFriendPersonaName(id);
const char *connect = SteamFriends()->GetFriendRichPresence( id, "connect");
FriendGameInfo_t friend_info = {};
SteamFriends()->GetFriendGamePlayed(id, &friend_info);
if (strlen(connect) > 0) {
std::cout << arguments.size() << "\t" << friend_info.m_gameID.AppID() << "\t" << name << "\t" << connect << std::endl;
arguments.push_back(connect);
} else {
if (friend_info.m_steamIDLobby != k_steamIDNil) {
std::string connect = "+connect_lobby " + std::to_string(friend_info.m_steamIDLobby.ConvertToUint64());
if (strlen(connect) > 0) {
std::cout << arguments.size() << "\t" << friend_info.m_gameID.AppID() << "\t" << name << "\t" << connect << std::endl;
arguments.push_back(connect);
} else {
if (friend_info.m_steamIDLobby != k_steamIDNil) {
std::string connect = "+connect_lobby " + std::to_string(friend_info.m_steamIDLobby.ConvertToUint64());
std::cout << arguments.size() << "\t" << friend_info.m_gameID.AppID() << "\t" << name << "\t" << connect << std::endl;
arguments.push_back(connect);
}
}
}
}
std::cout << arguments.size() << ": Retry." << std::endl;
std::cout << std::endl << "Enter the number corresponding to your choice then press Enter." << std::endl;
unsigned int choice;
std::cin >> choice;
std::cout << arguments.size() << ": Retry." << std::endl;
std::cout << std::endl << "Enter the number corresponding to your choice then press Enter." << std::endl;
unsigned int choice;
std::cin >> choice;
if (choice >= arguments.size()) goto top;
if (choice >= arguments.size()) goto top;
#ifdef _WIN32
std::cout << "starting the game with: " << arguments[choice] << std::endl << "Please select the game exe" << std::endl;
std::cout << "starting the game with: " << arguments[choice] << std::endl << "Please select the game exe" << std::endl;
OPENFILENAMEA ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = 0;
ofn.lpstrFilter = "Exe Files (*.exe)\0*.exe\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(GetOpenFileNameA(&ofn))
{
std::string filename = szFileName;
filename = "\"" + filename + "\" " + arguments[choice];
std::cout << filename << std::endl;
STARTUPINFOA lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;
OPENFILENAMEA ofn;
char szFileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = 0;
ofn.lpstrFilter = "Exe Files (*.exe)\0*.exe\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "txt";
if(GetOpenFileNameA(&ofn))
{
std::string filename = szFileName;
filename = "\"" + filename + "\" " + arguments[choice];
std::cout << filename << std::endl;
STARTUPINFOA lpStartupInfo;
PROCESS_INFORMATION lpProcessInfo;
ZeroMemory( &lpStartupInfo, sizeof( lpStartupInfo ) );
lpStartupInfo.cb = sizeof( lpStartupInfo );
ZeroMemory( &lpProcessInfo, sizeof( lpProcessInfo ) );
ZeroMemory( &lpStartupInfo, sizeof( lpStartupInfo ) );
lpStartupInfo.cb = sizeof( lpStartupInfo );
ZeroMemory( &lpProcessInfo, sizeof( lpProcessInfo ) );
CreateProcessA( NULL,
const_cast<char *>(filename.c_str()), NULL, NULL,
NULL, NULL, NULL, NULL,
&lpStartupInfo,
&lpProcessInfo
);
}
CreateProcessA( NULL,
const_cast<char *>(filename.c_str()), NULL, NULL,
NULL, NULL, NULL, NULL,
&lpStartupInfo,
&lpProcessInfo
);
}
#else
std::cout << "Please launch the game with these arguments: " << arguments[choice] << std::endl;
std::cout << "Please launch the game with these arguments: " << arguments[choice] << std::endl;
#endif
}
}
}

View File

@ -48,6 +48,12 @@
#undef GetModuleHandle
#endif
// Minimal timeout for detecting the real rendering API when multiple are used.
#define MIN_RENDER_DETECT_TIMEOUT 1
// Variance is in milliseconds. 1000 (one second) / 24 (FPS) = Aprox. 41.66 Milliseconds between frames.)
#define MAX_RENDER_DETECT_FRAME_TIMING_VARIANCE 42
#define GET_RENDERER_DETECT_TIMEOUT ((MAX_RENDERER_API_DETECT_TIMEOUT > MIN_RENDER_DETECT_TIMEOUT) ? MAX_RENDERER_API_DETECT_TIMEOUT : MIN_RENDER_DETECT_TIMEOUT) * 1000
#elif defined(__linux__) || defined(linux)
#define RENDERERDETECTOR_OS_LINUX
@ -105,6 +111,15 @@ private:
decltype(::SwapBuffers)* wglSwapBuffers;
decltype(::vkQueuePresentKHR)* vkQueuePresentKHR;
std::mutex timing_detect_mutex;
std::chrono::time_point<std::chrono::steady_clock> initial_hook_detect_time;
std::chrono::time_point<std::chrono::steady_clock> d3d_hook_detect_time;
std::chrono::time_point<std::chrono::steady_clock> ogl_hook_detect_time;
std::chrono::time_point<std::chrono::steady_clock> vkn_hook_detect_time;
std::chrono::steady_clock::duration d3d_frame_duration;
std::chrono::steady_clock::duration ogl_frame_duration;
std::chrono::steady_clock::duration vkn_frame_duration;
bool dxgi_hooked;
bool dxgi1_2_hooked;
bool dx12_hooked;
@ -113,6 +128,7 @@ private:
bool dx9_hooked;
bool opengl_hooked;
bool vulkan_hooked;
bool wine_found;
DX12_Hook* dx12_hook;
DX11_Hook* dx11_hook;
@ -135,6 +151,7 @@ private:
dx9_hooked(false),
opengl_hooked(false),
vulkan_hooked(false),
wine_found(false),
renderer_hook(nullptr),
dx9_hook(nullptr),
dx10_hook(nullptr),
@ -257,6 +274,8 @@ private:
void DeduceDXVersionFromSwapChain(IDXGISwapChain* pSwapChain)
{
PRINT_DEBUG("%s.\n",
"Renderer_Detector DeduceDXVersionFromSwapChain");
IUnknown* pDevice = nullptr;
if (Inst()->dx12_hooked)
{
@ -294,21 +313,154 @@ private:
}
}
static bool CheckD3DHookDetectTimings()
{
auto inst = Inst();
bool ret = false;
// It appears that (NVidia at least) calls IDXGISwapChain when calling OpenGL or Vulkan SwapBuffers.
//
// ---BUT---
//
// Wine and it's derivatives will -always- pass the OpenGL or Vulkan renderer
// detection, depending on what backend they are set to use for D3D.
// (wined3d == OpenGL. vkd3d || vkd3d-proton || DXVK || etc. == Vulkan.)
//
// So pass this check if, under Windows, D3D's frame interval timing isn't close to
// OpenGL's or Vulkan's. (I.e. Multiple frames have passed and only D3D has kept pace.)
// --OR--
// Invert the result under Windows to cover the NVIDIA case.
// --OR--
// Fail this check under Wine if OpenGL's / Vulkan's timing is the only regularly
// incrementing value. (I.e. Multiple frames have passed and only OpenGL OR Vulkan is
// keeping pace.)
// --OR--
// Pass this check under Wine if D3D's frame interval timing is keeping up with
// OpenGL's / Vulkan's. (I.e. Multiple frames have passed, D3D and either OpenGL or
// Vulkan has kept pace.)
{
if (inst->d3d_hook_detect_time != std::chrono::steady_clock::time_point() &&
inst->d3d_frame_duration != std::chrono::steady_clock::duration())
{
if (inst->ogl_hook_detect_time != std::chrono::steady_clock::time_point() &&
inst->ogl_frame_duration != std::chrono::steady_clock::duration())
{
std::chrono::duration<int, std::milli> duration_diff(0);
if (inst->ogl_frame_duration > inst->d3d_frame_duration)
{
duration_diff = std::chrono::duration_cast<std::chrono::milliseconds>(inst->ogl_frame_duration - inst->d3d_frame_duration);
}
else
{
duration_diff = std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration - inst->ogl_frame_duration);
}
if (duration_diff < std::chrono::duration<int, std::milli>(MAX_RENDER_DETECT_FRAME_TIMING_VARIANCE))
{
ret = true;
}
if (!inst->wine_found)
ret = !ret;
}
else
{
if (inst->vkn_hook_detect_time != std::chrono::steady_clock::time_point() &&
inst->vkn_frame_duration != std::chrono::steady_clock::duration())
{
std::chrono::duration<int, std::milli> duration_diff(0);
if (inst->vkn_frame_duration > inst->d3d_frame_duration)
{
duration_diff = std::chrono::duration_cast<std::chrono::milliseconds>(inst->vkn_frame_duration - inst->d3d_frame_duration);
}
else
{
duration_diff = std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration - inst->vkn_frame_duration);
}
if (duration_diff < std::chrono::duration<int, std::milli>(MAX_RENDER_DETECT_FRAME_TIMING_VARIANCE))
{
ret = true;
}
if (!inst->wine_found)
ret = !ret;
}
else
{
ret = true;
}
}
}
}
PRINT_DEBUG("%s %s.\n",
"Renderer_Detector CheckD3DHookDetectTimings Correct API:",
((ret == true) ? "D3D" : "OpenGL / Vulkan"));
return ret;
}
static HRESULT STDMETHODCALLTYPE MyIDXGISwapChain_Present(IDXGISwapChain* _this, UINT SyncInterval, UINT Flags)
{
auto inst = Inst();
HRESULT res;
bool locked;
std::unique_lock<std::mutex> lk(inst->renderer_mutex, std::defer_lock);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyIDXGISwapChain_Present");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyIDXGISwapChain_Present Initial time");
}
if (inst->d3d_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyIDXGISwapChain_Present Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->d3d_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->d3d_hook_detect_time);
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MyIDXGISwapChain_Present current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = CheckD3DHookDetectTimings();
}
}
}
}
// It appears that (NVidia at least) calls IDXGISwapChain when calling OpenGL or Vulkan SwapBuffers.
// So only lock when OpenGL or Vulkan hasn't already locked the mutex.
locked = lk.try_lock();
res = (_this->*inst->IDXGISwapChainPresent)(SyncInterval, Flags);
if (!locked || inst->detection_done)
return res;
inst->DeduceDXVersionFromSwapChain(_this);
res = (_this->*inst->IDXGISwapChainPresent)(SyncInterval, Flags);
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
if (detect_pass)
inst->DeduceDXVersionFromSwapChain(_this);
}
return res;
}
@ -318,16 +470,60 @@ private:
auto inst = Inst();
HRESULT res;
bool locked;
std::unique_lock<std::mutex> lk(inst->renderer_mutex, std::defer_lock);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyIDXGISwapChain_Present1");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyIDXGISwapChain_Present1 Initial time");
}
if (inst->d3d_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyIDXGISwapChain_Present1 Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->d3d_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->d3d_hook_detect_time);
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MyIDXGISwapChain_Present1 current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = CheckD3DHookDetectTimings();
}
}
}
}
// It appears that (NVidia at least) calls IDXGISwapChain when calling OpenGL or Vulkan SwapBuffers.
// So only lock when OpenGL or Vulkan hasn't already locked the mutex.
locked = lk.try_lock();
res = (_this->*inst->IDXGISwapChainPresent1)(SyncInterval, Flags, pPresentParameters);
if (!locked || inst->detection_done)
return res;
inst->DeduceDXVersionFromSwapChain(_this);
res = (_this->*inst->IDXGISwapChainPresent1)(SyncInterval, Flags, pPresentParameters);
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
if (detect_pass)
inst->DeduceDXVersionFromSwapChain(_this);
}
return res;
}
@ -335,13 +531,58 @@ private:
static HRESULT STDMETHODCALLTYPE MyDX9Present(IDirect3DDevice9* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion)
{
auto inst = Inst();
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9Present");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9Present Initial time");
}
if (inst->d3d_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9Present Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->d3d_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->d3d_hook_detect_time);
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MyDX9Present current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = CheckD3DHookDetectTimings();
}
}
}
}
auto res = (_this->*inst->IDirect3DDevice9Present)(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion);
if (inst->detection_done)
return res;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
inst->HookDetected(inst->dx9_hook);
if (detect_pass)
inst->HookDetected(inst->dx9_hook);
}
return res;
}
@ -349,13 +590,58 @@ private:
static HRESULT STDMETHODCALLTYPE MyDX9PresentEx(IDirect3DDevice9Ex* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags)
{
auto inst = Inst();
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9PresentEx");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9PresentEx Initial time");
}
if (inst->d3d_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9PresentEx Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->d3d_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->d3d_hook_detect_time);
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MyDX9PresentEx current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = CheckD3DHookDetectTimings();
}
}
}
}
auto res = (_this->*inst->IDirect3DDevice9ExPresentEx)(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
if (inst->detection_done)
return res;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
inst->HookDetected(inst->dx9_hook);
if (detect_pass)
inst->HookDetected(inst->dx9_hook);
}
return res;
}
@ -363,13 +649,58 @@ private:
static HRESULT STDMETHODCALLTYPE MyDX9SwapChainPresent(IDirect3DSwapChain9* _this, CONST RECT* pSourceRect, CONST RECT* pDestRect, HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion, DWORD dwFlags)
{
auto inst = Inst();
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9SwapChainPresent");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9SwapChainPresent Initial time");
}
if (inst->d3d_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyDX9SwapChainPresent Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->d3d_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->d3d_hook_detect_time);
inst->d3d_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MyDX9SwapChainPresent current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->d3d_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = CheckD3DHookDetectTimings();
}
}
}
}
auto res = (_this->*inst->IDirect3DSwapChain9Present)(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags);
if (inst->detection_done)
return res;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
inst->HookDetected(inst->dx9_hook);
if (detect_pass)
inst->HookDetected(inst->dx9_hook);
}
return res;
}
@ -377,15 +708,57 @@ private:
static BOOL WINAPI MywglSwapBuffers(HDC hDC)
{
auto inst = Inst();
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MywglSwapBuffers");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MywglSwapBuffers Initial time");
}
if (inst->ogl_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->ogl_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MywglSwapBuffers Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->ogl_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->ogl_hook_detect_time);
inst->ogl_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MywglSwapBuffers current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->ogl_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = !(CheckD3DHookDetectTimings());
}
}
}
}
auto res = inst->wglSwapBuffers(hDC);
if (inst->detection_done)
return res;
if (gladLoaderLoadGL() >= GLAD_MAKE_VERSION(3, 1))
{
inst->HookDetected(inst->opengl_hook);
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
if (detect_pass == true && gladLoaderLoadGL() >= GLAD_MAKE_VERSION(3, 1))
inst->HookDetected(inst->opengl_hook);
}
return res;
@ -394,13 +767,58 @@ private:
static VkResult VKAPI_CALL MyvkQueuePresentKHR(VkQueue Queue, const VkPresentInfoKHR* pPresentInfo)
{
auto inst = Inst();
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
bool detect_pass = false;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyvkQueuePresentKHR");
if (!inst->detection_done)
{
auto current = std::chrono::steady_clock::now();
std::lock_guard<std::mutex> t_lk(inst->timing_detect_mutex);
if (inst->initial_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->initial_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyvkQueuePresentKHR Initial time");
}
if (inst->vkn_hook_detect_time == std::chrono::steady_clock::time_point())
{
inst->vkn_hook_detect_time = current;
PRINT_DEBUG("%s.\n",
"Renderer_Detector MyvkQueuePresentKHR Initial detect");
}
else
{
if (std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time) < std::chrono::milliseconds{GET_RENDERER_DETECT_TIMEOUT})
{
inst->vkn_frame_duration = std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->vkn_hook_detect_time);
inst->vkn_hook_detect_time = current;
PRINT_DEBUG("%s %" PRIu64 " %s %" PRIu64 "ms.\n",
"Renderer_Detector MyvkQueuePresentKHR current frame duration:",
(std::chrono::duration_cast<std::chrono::milliseconds>(inst->vkn_frame_duration)).count(),
"ms. time since first detect:",
(std::chrono::duration_cast<std::chrono::milliseconds>(current - inst->initial_hook_detect_time)).count());
}
else
{
detect_pass = !(CheckD3DHookDetectTimings());
}
}
}
}
auto res = inst->vkQueuePresentKHR(Queue, pPresentInfo);
if (inst->detection_done)
return res;
{
std::lock_guard<std::mutex> lk(inst->renderer_mutex);
if (inst->detection_done)
return res;
inst->HookDetected(inst->vulkan_hook);
if (detect_pass)
inst->HookDetected(inst->vulkan_hook);
}
return res;
}
@ -583,6 +1001,23 @@ private:
{
if (!dx10_hooked)
{
//HACK: Remove when wine _finally_ implements the NULL renderer....
bool found_wine = false;
std::string ntdll_path = FindPreferedModulePath("ntdll.dll");
if (!ntdll_path.empty())
{
HMODULE hNTdll = GetModuleHandleA(ntdll_path.c_str());
if (hNTdll != nullptr)
{
auto wine_get_version = (const char*(*)())GetProcAddress(hNTdll, "wine_get_version");
if (wine_get_version != nullptr)
{
found_wine = true;
SPDLOG_WARN("Found WINE version: %s.\n", wine_get_version());
}
}
}
System::Library::Library libD3d10;
if (!libD3d10.OpenLibrary(library_path, false))
{
@ -607,7 +1042,7 @@ private:
if (D3D10CreateDevice != nullptr && CreateDXGIFactory1 != nullptr)
{
D3D10CreateDevice(NULL, D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &pDevice);
D3D10CreateDevice(NULL, (found_wine) ? D3D10_DRIVER_TYPE_WARP : D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &pDevice);
if (pDevice != nullptr)
{
CreateDXGIFactory1(IID_PPV_ARGS(&pDXGIFactory));
@ -627,6 +1062,24 @@ private:
pDXGIFactory->CreateSwapChainForHwnd(pDevice, dummyWindow, &SwapChainDesc, NULL, NULL, reinterpret_cast<IDXGISwapChain1**>(&pSwapChain));
}
else
{
SPDLOG_WARN("Failed to instanciate IDXGIFactory2, fallback to pure DX10 detection");
}
}
else
{
SPDLOG_WARN("Failed to instanciate ID3D10Device, fallback to pure DX10 detection");
}
}
else
{
if (D3D10CreateDevice == nullptr)
{
SPDLOG_WARN("Failed to get address of D3D10CreateDevice, fallback to pure DX10 detection");
} else
{
SPDLOG_WARN("Failed to get address of CreateDXGIFactory1, fallback to pure DX10 detection");
}
}
@ -660,7 +1113,11 @@ private:
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.Windowed = TRUE;
D3D10CreateDeviceAndSwapChain(NULL, D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice);
D3D10CreateDeviceAndSwapChain(NULL, (found_wine) ? D3D10_DRIVER_TYPE_WARP : D3D10_DRIVER_TYPE_NULL, NULL, 0, D3D10_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice);
}
else
{
SPDLOG_WARN("Failed to get address of D3D10CreateDeviceAndSwapChain, DX10 API failed.");
}
}
@ -698,6 +1155,23 @@ private:
{
if (!dx11_hooked)
{
//HACK: Remove when wine _finally_ implements the NULL renderer....
bool found_wine = false;
std::string ntdll_path = FindPreferedModulePath("ntdll.dll");
if (!ntdll_path.empty())
{
HMODULE hNTdll = GetModuleHandleA(ntdll_path.c_str());
if (hNTdll != nullptr)
{
auto wine_get_version = (const char*(*)())GetProcAddress(hNTdll, "wine_get_version");
if (wine_get_version != nullptr)
{
found_wine = true;
SPDLOG_WARN("Found WINE version: %s.\n", wine_get_version());
}
}
}
System::Library::Library libD3d11;
if (!libD3d11.OpenLibrary(library_path, false))
{
@ -722,7 +1196,7 @@ private:
if (D3D11CreateDevice != nullptr && CreateDXGIFactory1 != nullptr)
{
D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &pDevice, NULL, NULL);
D3D11CreateDevice(NULL, (found_wine) ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &pDevice, NULL, NULL);
if (pDevice != nullptr)
{
CreateDXGIFactory1(IID_PPV_ARGS(&pDXGIFactory));
@ -741,7 +1215,17 @@ private:
SwapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
pDXGIFactory->CreateSwapChainForHwnd(pDevice, dummyWindow, &SwapChainDesc, NULL, NULL, reinterpret_cast<IDXGISwapChain1**>(&pSwapChain));
} else {
SPDLOG_WARN("Failed to instanciate IDXGIFactory2, fallback to pure DX11 detection");
}
} else {
SPDLOG_WARN("Failed to instanciate ID3D11Device, fallback to pure DX11 detection");
}
} else {
if (D3D11CreateDevice == nullptr) {
SPDLOG_WARN("Failed to get address of D3D11CreateDevice, fallback to pure DX11 detection");
} else {
SPDLOG_WARN("Failed to get address of CreateDXGIFactory1, fallback to pure DX11 detection");
}
}
@ -775,7 +1259,9 @@ private:
SwapChainDesc.SampleDesc.Quality = 0;
SwapChainDesc.Windowed = TRUE;
D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, NULL, D3D11_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice, NULL, NULL);
D3D11CreateDeviceAndSwapChain(NULL, (found_wine) ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, NULL, D3D11_SDK_VERSION, &SwapChainDesc, &pSwapChain, &pDevice, NULL, NULL);
} else {
SPDLOG_WARN("Failed to get address of D3D11CreateDeviceAndSwapChain, DX11 API failed.");
}
}
@ -1045,6 +1531,20 @@ private:
bool EnterDetection()
{
std::string ntdll_path = FindPreferedModulePath("ntdll.dll");
if (!ntdll_path.empty())
{
HMODULE hNTdll = GetModuleHandleA(ntdll_path.c_str());
if (hNTdll != nullptr)
{
auto wine_get_version = (const char*(*)())GetProcAddress(hNTdll, "wine_get_version");
if (wine_get_version != nullptr)
{
wine_found = true;
PRINT_DEBUG("Found WINE version: %s.\n", wine_get_version());
}
}
}
return CreateHWND() != nullptr;
}
@ -1063,6 +1563,7 @@ private:
dx9_hooked = false;
opengl_hooked = false;
vulkan_hooked = false;
wine_found = false;
delete dx9_hook ; dx9_hook = nullptr;
delete dx10_hook ; dx10_hook = nullptr;
@ -1070,6 +1571,15 @@ private:
delete dx12_hook ; dx12_hook = nullptr;
delete opengl_hook; opengl_hook = nullptr;
delete vulkan_hook; vulkan_hook = nullptr;
initial_hook_detect_time = std::chrono::time_point<std::chrono::steady_clock>();
d3d_hook_detect_time = std::chrono::time_point<std::chrono::steady_clock>();
ogl_hook_detect_time = std::chrono::time_point<std::chrono::steady_clock>();
vkn_hook_detect_time = std::chrono::time_point<std::chrono::steady_clock>();
d3d_frame_duration = std::chrono::steady_clock::duration();
ogl_frame_duration = std::chrono::steady_clock::duration();
vkn_frame_duration = std::chrono::steady_clock::duration();
}
#elif defined(RENDERERDETECTOR_OS_LINUX)
@ -1312,6 +1822,22 @@ public:
{
std::lock_guard<std::mutex> lk(stop_detection_mutex);
if (timeout != std::chrono::milliseconds{ -1 })
{
if (timeout < std::chrono::milliseconds{ GET_RENDERER_DETECT_TIMEOUT * 2 })
{// Need enough time to determine API if multiple are used.
timeout = std::chrono::milliseconds{ GET_RENDERER_DETECT_TIMEOUT * 2 };
}
PRINT_DEBUG("%s %" PRIu64 ".\n",
"Renderer_Detector Detection timeout set to:",
timeout.count());
}
else
{
PRINT_DEBUG("%s.\n",
"Renderer_Detector Detection timeout set to: infinite");
}
if (detection_count == 0)
{// If we have no detections in progress, restart detection.
detection_cancelled = false;
@ -1401,7 +1927,7 @@ public:
}
stop_detection_cv.notify_all();
SPDLOG_TRACE("Renderer detection done {}.", (void*)renderer_hook);
SPDLOG_TRACE("Renderer detection done %p.", (void*)renderer_hook);
return renderer_hook;
});

View File

@ -27,6 +27,21 @@
#include "Renderer_Hook.h"
/* Timeout is in seconds.
Used for determining which rendering API is the real one used by
the app when multiple APIs are used. (NVIDIA, Wine, etc.)
This is an internally used value, separate from the timeout given
to DetectRenderer().
If you define it below the minimal level (one second), the minimal level
will be used.
Any timeout given to DetectRenderer() less than this value will be upgraded
to it.
*/
#define MAX_RENDERER_API_DETECT_TIMEOUT 1
namespace ingame_overlay {
std::future<Renderer_Hook*> DetectRenderer(std::chrono::milliseconds timeout = std::chrono::milliseconds{ -1 });

View File

@ -38,6 +38,8 @@
#include <spdlog/spdlog.h>
#endif
#define PRINT_DEBUG_NO_LINENUM(a, ...) do {FILE *t = fopen("STEAM_LOG.txt", "a"); fprintf(t, a, __VA_ARGS__); fclose(t);} while (0)
#ifndef SPDLOG_TRACE
#define SPDLOG_TRACE(x, ...) PRINT_DEBUG(x "\n", __VA_ARGS__)
#endif
@ -47,6 +49,9 @@
#ifndef SPDLOG_INFO
#define SPDLOG_INFO(x, ...) PRINT_DEBUG(x "\n", __VA_ARGS__)
#endif
#ifndef SPDLOG_INFO_NO_NEWLINE
#define SPDLOG_INFO_NO_NEWLINE(x, ...) PRINT_DEBUG_NO_LINENUM(x, __VA_ARGS__)
#endif
#ifndef SPDLOG_WARN
#define SPDLOG_WARN(x, ...) PRINT_DEBUG(x "\n", __VA_ARGS__)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -68,6 +68,8 @@ struct Notification
std::chrono::seconds start_time;
std::string message;
std::pair<const Friend, friend_window_state>* frd;
std::string ach_name;
CSteamID steam_id;
};
struct Overlay_Achievement
@ -78,11 +80,67 @@ struct Overlay_Achievement
bool hidden;
bool achieved;
uint32 unlock_time;
uint8 * raw_image;
uint32 raw_image_width;
uint32 raw_image_height;
std::weak_ptr<uint64_t> image_resource;
};
struct Profile_Image_ID
{
CSteamID id;
int eAvatarSize;
};
bool operator<(const Profile_Image_ID &a, const Profile_Image_ID &b);
bool operator>(const Profile_Image_ID &a, const Profile_Image_ID &b);
bool operator<=(const Profile_Image_ID &a, const Profile_Image_ID &b);
bool operator>=(const Profile_Image_ID &a, const Profile_Image_ID &b);
bool operator==(const Profile_Image_ID &a, const Profile_Image_ID &b);
bool operator!=(const Profile_Image_ID &a, const Profile_Image_ID &b);
struct Profile_Image
{
uint32 width;
uint32 height;
uint8 * raw_image;
std::weak_ptr<uint64_t> image_resource;
};
#ifdef small
#undef small
#endif
struct Profile_Image_Set
{
Profile_Image small;
Profile_Image medium;
Profile_Image large;
};
struct Temporary_Image
{
Profile_Image image_data;
std::chrono::steady_clock::time_point last_display_time;
};
enum DisplayImageType {
displayImageTypeAchievement = 0,
displayImageTypeAvatar = 1,
displayImageTypeCustom = 2,
displayImageTypeEND = 3
};
#ifdef EMU_OVERLAY
#include <future>
#include "Renderer_Hook.h"
class Steam_Overlay_CCallback;
class Steam_Overlay
{
Settings* settings;
@ -90,6 +148,7 @@ class Steam_Overlay
SteamCallBacks* callbacks;
RunEveryRunCB* run_every_runcb;
Networking* network;
Steam_Overlay_CCallback* overlay_CCallback;
// friend id, show client window (to chat and accept invite maybe)
std::map<Friend, friend_window_state, Friend_Less> friends;
@ -101,16 +160,33 @@ class Steam_Overlay
int h_inset, v_inset;
std::string show_url;
std::vector<Overlay_Achievement> achievements;
bool show_achievements, show_settings;
bool show_achievements, show_settings, show_profile_image_select;
void *fonts_atlas;
bool disable_forced, local_save, warning_forced;
uint32_t appid;
bool disable_forced, local_save, warning_forced, show_achievement_desc_on_unlock, show_achievement_hidden_unearned;
uint32_t appid, total_achievement_count, earned_achievement_count;
char username_text[256];
std::atomic_bool save_settings;
std::atomic_bool save_settings, save_small_profile_image, save_medium_profile_image, save_large_profile_image;
// Set Avatar Image filesystem chooser
bool show_drive_list;
std::map<std::string, bool> filesystem_list;
std::string current_path;
std::string future_path;
// Avatar Images
std::map<CSteamID, Profile_Image_Set> profile_images;
std::map<CSteamID, uint32_t>lazy_load_avatar_images;
std::string new_profile_image_path;
std::string current_status_message;
bool tried_load_new_profile_image, cleared_new_profile_images_struct;
Profile_Image_Set new_profile_image_handles;
bool radio_btn_new_profile_image_size[3];
int current_language;
int current_ui_notification_position_selection;
std::string warning_message;
@ -149,6 +225,82 @@ class Steam_Overlay
void BuildFriendWindow(Friend const& frd, friend_window_state &state);
// Notifications like achievements, chat and invitations
void BuildNotifications(int width, int height);
// ImGui image.
std::map<uint8*,Temporary_Image> temp_display_images;
int display_imgui_achievement(float xSize,
float ySize,
float image_color_multipler_r,
float image_color_multipler_g,
float image_color_multipler_b,
float image_color_multipler_a,
std::string achName,
uint32_t loadType);
int display_imgui_avatar(float xSize,
float ySize,
float image_color_multipler_r,
float image_color_multipler_g,
float image_color_multipler_b,
float image_color_multipler_a,
CSteamID userID,
int eAvatarSize,
uint32_t loadType);
int display_imgui_custom_image(float xSize,
float ySize,
float image_color_multipler_r,
float image_color_multipler_g,
float image_color_multipler_b,
float image_color_multipler_a,
uint8 * imageData,
uint32_t imageDataLength,
uint32_t imageDataWidth,
uint32_t imageDataHeight);
int display_imgui_image(uint32_t displayImageType,
float xSize,
float ySize,
float image_color_multipler_r,
float image_color_multipler_g,
float image_color_multipler_b,
float image_color_multipler_a,
std::string achName,
CSteamID userID,
int eAvatarSize,
uint8 * imageData,
uint32_t imageDataLength,
uint32_t imageDataWidth,
uint32_t imageDataHeight,
uint32_t loadType);
void LoadAchievementImage(Overlay_Achievement & ach);
void CreateAchievementImageResource(Overlay_Achievement & ach);
void DestroyAchievementImageResource(Overlay_Achievement & ach);
void DestroyAchievementImageResources();
// Profile images
void populate_initial_profile_images(CSteamID id);
bool LoadProfileImage(const CSteamID & id, const int eAvatarSize);
bool LoadProfileImage(const CSteamID & id, const int eAvatarSize, Profile_Image_Set & images);
bool CreateProfileImageResource(const CSteamID & id, const int eAvatarSize);
bool CreateProfileImageResource(const CSteamID & id, const int eAvatarSize, Profile_Image_Set & images);
void DestroyProfileImage(const CSteamID & id, const int eAvatarSize);
void DestroyProfileImage(const CSteamID & id, const int eAvatarSize, Profile_Image_Set & images);
void DestroyProfileImageResource(const CSteamID & id, const int eAvatarSize);
void DestroyProfileImageResource(const CSteamID & id, const int eAvatarSize, Profile_Image_Set & images);
void DestroyProfileImageResources();
// Temporary images
void ReturnTemporaryImage(Profile_Image & imageData);
Profile_Image GetTemporaryImage(uint8 * imageData);
void DestroyTemporaryImageResource(uint8 * imageData);
void DestroyTemporaryImageResources();
void DestroyTemporaryImage(uint8 * imageData);
void DestroyTemporaryImages();
void PruneTemporaryImages();
public:
Steam_Overlay(Settings* settings, SteamCallResults* callback_results, SteamCallBacks* callbacks, RunEveryRunCB* run_every_runcb, Networking *network);
@ -163,6 +315,7 @@ public:
void SetNotificationInset(int nHorizontalInset, int nVerticalInset);
void SetupOverlay();
void UnSetupOverlay();
bool RegisteredInternalCallbacks();
void HookReady(bool ready);
@ -183,9 +336,10 @@ public:
void FriendConnect(Friend _friend);
void FriendDisconnect(Friend _friend);
void AddMessageNotification(std::string const& message);
void AddMessageNotification(std::string const& message, CSteamID frd);
void AddAchievementNotification(nlohmann::json const& ach);
void AddInviteNotification(std::pair<const Friend, friend_window_state> &wnd_state);
void OnAvatarImageLoaded(AvatarImageLoaded_t *pParam);
};
#else
@ -205,6 +359,7 @@ public:
void SetNotificationInset(int nHorizontalInset, int nVerticalInset) {}
void SetupOverlay() {}
void UnSetupOverlay() {}
bool RegisteredInternalCallbacks() const { return true; }
void HookReady(bool ready) {}
@ -225,9 +380,10 @@ public:
void FriendConnect(Friend _friend) {}
void FriendDisconnect(Friend _friend) {}
void AddMessageNotification(std::string const& message) {}
void AddMessageNotification(std::string const& message, CSteamID frd) {}
void AddAchievementNotification(nlohmann::json const& ach) {}
void AddInviteNotification(std::pair<const Friend, friend_window_state> &wnd_state) {}
void OnAvatarImageLoaded(AvatarImageLoaded_t *pParam) {}
};
#endif

View File

@ -207,6 +207,7 @@ DX11_Hook::DX11_Hook():
_Hooked(false),
_WindowsHooked(false),
pContext(nullptr),
pDevice(nullptr),
mainRenderTargetView(nullptr),
Present(nullptr),
ResizeBuffers(nullptr),
@ -263,6 +264,11 @@ void DX11_Hook::LoadFunctions(
std::weak_ptr<uint64_t> DX11_Hook::CreateImageResource(const void* image_data, uint32_t width, uint32_t height)
{
if (pDevice == nullptr) {
SPDLOG_INFO("DX11 CreateImageResource %p pDevice is NULL.\n", image_data);
return std::shared_ptr<uint64_t>();
}
ID3D11ShaderResourceView** resource = new ID3D11ShaderResourceView*(nullptr);
// Create texture
@ -273,6 +279,7 @@ std::weak_ptr<uint64_t> DX11_Hook::CreateImageResource(const void* image_data, u
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
@ -282,6 +289,7 @@ std::weak_ptr<uint64_t> DX11_Hook::CreateImageResource(const void* image_data, u
subResource.pSysMem = image_data;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
pDevice->CreateTexture2D(&desc, &subResource, &pTexture);
if (pTexture != nullptr)

View File

@ -163,12 +163,7 @@ std::weak_ptr<uint64_t> OpenGL_Hook::CreateImageResource(const void* image_data,
{
GLuint* texture = new GLuint(0);
glGenTextures(1, texture);
if (glGetError() != GL_NO_ERROR)
{
delete texture;
return std::shared_ptr<uint64_t>(nullptr);
}
// Save old texture id
GLint oldTex;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex);
@ -177,13 +172,17 @@ std::weak_ptr<uint64_t> OpenGL_Hook::CreateImageResource(const void* image_data,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Upload pixels into texture
#if defined(GL_UNPACK_ROW_LENGTH) && !defined(__EMSCRIPTEN__)
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
glBindTexture(GL_TEXTURE_2D, oldTex);
glFlush();
auto ptr = std::shared_ptr<uint64_t>((uint64_t*)texture, [](uint64_t* handle)
{
if (handle != nullptr)

View File

@ -32,6 +32,9 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
WCHAR ExeRunDir[MAX_PATH] = { 0 };
WCHAR ExeCommandLine[4096] = { 0 };
WCHAR AppId[128] = { 0 };
HANDLE SharedMemFileMap = 0;
HANDLE SharedMemFileView = 0;
HANDLE SharedMemFileLock = 0;
STARTUPINFOW info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
@ -100,14 +103,45 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
return 0;
}
// Create shared mem map.
SharedMemFileMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 1024, L"Local\\SteamStart_SharedMemFile");
if (!SharedMemFileMap)
{
MessageBoxA(NULL, "Unable to create shared memory mapping.", "ColdClientLoader", MB_ICONERROR);
return 0;
}
SharedMemFileView = MapViewOfFile(SharedMemFileMap, SECTION_ALL_ACCESS, 0, 0, 0);
if (!SharedMemFileView)
{
MessageBoxA(NULL, "Unable to create view of shared memory mapping.", "ColdClientLoader", MB_ICONERROR);
CloseHandle(SharedMemFileMap);
return 0;
}
SharedMemFileLock = CreateEventW(NULL, FALSE, FALSE, L"Local\\SteamStart_SharedMemLock");
if (!SharedMemFileLock)
{
MessageBoxA(NULL, "Unable to create lock for shared memory mapping.", "ColdClientLoader", MB_ICONERROR);
CloseHandle(SharedMemFileView);
CloseHandle(SharedMemFileMap);
return 0;
}
SetEvent(SharedMemFileLock);
// Create env.
SetEnvironmentVariableW(L"SteamAppPath", ExeRunDir);
WCHAR CommandLine[8192];
_snwprintf(CommandLine, _countof(CommandLine), L"\"%ls\" %ls", ExeFile, ExeCommandLine);
if (!ExeFile[0] || !CreateProcessW(ExeFile, CommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo))
{
MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR);
CloseHandle(SharedMemFileLock);
CloseHandle(SharedMemFileView);
CloseHandle(SharedMemFileMap);
return 0;
}
HKEY Registrykey;
HKEY Registrykey_32BitView;
// Declare some variables to be used for Steam registry.
DWORD UserId = 0x03100004771F810D & 0xffffffff;
DWORD ProcessID = GetCurrentProcessId();
@ -116,8 +150,12 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
DWORD keyType = REG_SZ;
WCHAR OrgSteamCDir[MAX_PATH] = { 0 };
WCHAR OrgSteamCDir64[MAX_PATH] = { 0 };
WCHAR OrgSteamCDir_32BitView[MAX_PATH] = { 0 };
WCHAR OrgSteamCDir64_32BitView[MAX_PATH] = { 0 };
DWORD Size1 = MAX_PATH;
DWORD Size2 = MAX_PATH;
DWORD Size3 = MAX_PATH;
DWORD Size4 = MAX_PATH;
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
{
orig_steam = true;
@ -127,6 +165,24 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
} else {
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS)
{
MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR);
TerminateProcess(processInfo.hProcess, NULL);
CloseHandle(SharedMemFileLock);
CloseHandle(SharedMemFileView);
CloseHandle(SharedMemFileMap);
return 0;
}
}
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &Registrykey_32BitView) == ERROR_SUCCESS)
{
orig_steam = true;
// Get original values to restore later.
RegQueryValueExW(Registrykey_32BitView, L"SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir_32BitView, &Size3);
RegQueryValueExW(Registrykey_32BitView, L"SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64_32BitView, &Size4);
} else {
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS | KEY_WOW64_32KEY, NULL, &Registrykey_32BitView, NULL) != ERROR_SUCCESS)
{
MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR);
TerminateProcess(processInfo.hProcess, NULL);
@ -137,26 +193,34 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
// Set values to Windows registry.
RegSetValueExA(Registrykey, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD));
RegSetValueExA(Registrykey, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD));
RegSetValueExA(Registrykey_32BitView, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD));
RegSetValueExA(Registrykey_32BitView, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD));
{
// Before saving to the registry check again if the path was valid and if the file exist
if (GetFileAttributesW(ClientPath) != INVALID_FILE_ATTRIBUTES) {
RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)(lstrlenW(ClientPath) * sizeof(WCHAR)) + 1);
RegSetValueExW(Registrykey_32BitView, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)(lstrlenW(ClientPath) * sizeof(WCHAR)) + 1);
}
else {
RegSetValueExW(Registrykey, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
RegSetValueExW(Registrykey_32BitView, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
}
if (GetFileAttributesW(Client64Path) != INVALID_FILE_ATTRIBUTES) {
RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)(lstrlenW(Client64Path) * sizeof(WCHAR)) + 1);
RegSetValueExW(Registrykey_32BitView, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)(lstrlenW(Client64Path) * sizeof(WCHAR)) + 1);
}
else {
RegSetValueExW(Registrykey, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
RegSetValueExW(Registrykey_32BitView, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
}
}
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
RegSetValueExA(Registrykey_32BitView, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
// Close the HKEY Handle.
RegCloseKey(Registrykey);
RegCloseKey(Registrykey_32BitView);
ResumeThread(processInfo.hThread);
WaitForSingleObject(processInfo.hThread, INFINITE);
@ -173,7 +237,21 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
// Close the HKEY Handle.
RegCloseKey(Registrykey);
}
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS | KEY_WOW64_32KEY, &Registrykey_32BitView) == ERROR_SUCCESS)
{
// Restore the values.
RegSetValueExW(Registrykey_32BitView, L"SteamClientDll", NULL, REG_SZ, (LPBYTE)OrgSteamCDir_32BitView, Size3);
RegSetValueExW(Registrykey_32BitView, L"SteamClientDll64", NULL, REG_SZ, (LPBYTE)OrgSteamCDir64_32BitView, Size4);
// Close the HKEY Handle.
RegCloseKey(Registrykey_32BitView);
}
}
// Close the SharedMem handles.
CloseHandle(SharedMemFileLock);
CloseHandle(SharedMemFileView);
CloseHandle(SharedMemFileMap);
return 0;
}