Compare commits

...

53 Commits

Author SHA1 Message Date
redpolline
dec6e8bdbe 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
2025-02-13 03:05:50 +00:00
redpolline
97b34c5e98 Add dummy UI object if achievement isn't loaded.
This should prevent the achievements list in the steam overlay from
being unreadable when the images are not able to be displayed.
2025-02-12 09:35:27 -05:00
redpolline
82e2abd117 Fix incorrect achievements.json parsing.
The correct name for the locked achievement image is "icon_gray".

Also fix the debugging counters and properly check for an existing key
in the parsed json.
2025-02-12 09:35:27 -05:00
redpolline
08ceeb2419 Silence some compiler warnings in base.cpp. 2025-02-12 09:35:27 -05:00
redpolline
17d4701e88 Add more debug logging to achievement image loads. 2025-02-12 09:35:27 -05:00
redpolline
7d0555b6ee Fix another C0000005 in the overlay. 2025-02-12 09:35:27 -05:00
redpolline
38cbfb3be9 Fix renderer detection under Wine.
Use new timing checks to detect D3D being dependant on other APIs.
(Should work now regardless of platform, but GPU hardware detection may still be
needed...)
2025-02-12 09:35:27 -05:00
redpolline
32689355d0 Implement SteamAPI_WriteMiniDump. 2025-02-12 09:35:26 -05:00
redpolline
8726d331f9 Prevent overlay crash if no achievements are defd.
Disable the "show achievements" button too.
2025-02-12 09:35:26 -05:00
redpolline
f3ac8485ed HACK: Wine DX10 and DX11 Detection.
Wine doesn't implement the NULL renderer, and tries to fallback to the
REFERENCE renderer. Which then also fails when we try to create a 1x1
DXGI_USAGE_RENDER_TARGET_OUTPUT swapchain.

Until Wine manages to get a NULL renderer working, just use the WARP
renderer instead. (Which Wine also doesn't implement and falls back to
the hardware renderer for, but at least it works properly.)
2025-02-12 09:35:26 -05:00
redpolline
9f4cc05f2a Fix overlay when avatar images are not configured.
(Otherwise, we'll crash after generating too many images.)
2025-02-12 09:35:26 -05:00
redpolline
4083408bcb Add PDB generation to release builds & LC x64.
Adds pdb generation to windows release builds. (Easier debugging.)

Adds lobby_connect x64 windows builds. (release and debug.)
2025-02-12 09:35:26 -05:00
redpolline
bfb56db87d Rate limit Settings::background_monitor. 2025-02-12 09:35:26 -05:00
redpolline
c81c506b97 Fix linux build scripts.
Make seperate debug and release build scripts.

Strip the release build.

Add missing define flags.

Fix shared lib arg for libasan.
2025-02-12 09:35:26 -05:00
redpolline
59cb19e56a Clang fixes. 2025-02-12 09:35:26 -05:00
redpolline
c5afbe9fea Return a val when EMU_OVERLAY isn't defined.
Steam_Overlay::RegisteredInternalCallbacks must return a value when
EMU_OVERLAY isn't defined. (lobby_connect build.)
2025-02-12 09:35:25 -05:00
redpolline
e2e21441c8 Add missing NO_DISK_WRITES local_storage funcs.
Add Local_Storage::delete_data_settings and Local_Storage::data_settings_exists
implementations when NO_DISK_WRITES is defined. (lobby_connect build.)
2025-02-12 09:35:25 -05:00
redpolline
55b5118dc0 Add Overlay UI functions.
Too many things to list.
2025-02-12 09:35:25 -05:00
redpolline
cd5d45e610 Support saving / loading UI Notification Position. 2025-02-12 09:35:25 -05:00
redpolline
816479259b Add Settings::ui_notification_position. 2025-02-12 09:35:25 -05:00
redpolline
ba49e5618c Use correct callback queue for AvatarImageLoaded_t 2025-02-12 09:35:25 -05:00
redpolline
5705403157 Check callback registration in NOTIFY_AVATAR_IMAGE.
Make sure overlay callbacks are registered before firing callbacks for
set_profile_image.
2025-02-12 09:35:25 -05:00
redpolline
4dbf130cb9 Allow checking registration for GB_CALLBACK
Add cb_type ## _is_registered function for GOLDBERG_CALLBACK_INTERNAL
macro to allow external checking of the callback's registration status
with CCallbackMgr.
2025-02-12 09:35:25 -05:00
redpolline
f693bfb073 Implement sending and receiving friend avatars.
Moves Steam_Friends::Callback into a cpp file.

Generates callbacks for avatar changes.

Requests avatars when asked for one that is unknown.
2025-02-12 09:35:25 -05:00
redpolline
25d34a65c4 Redo image handling in settings.
Lock the buffers when modifying them.

Notify when callers change a set avatar image.

Create a get function for images.

Allow deletion of previously loaded images, and reuse of their ids.
2025-02-12 09:35:25 -05:00
redpolline
c593c3f8b8 Move most functionality from the macro to template.
Have the users of the macro use common functionality.
2025-02-12 09:35:24 -05:00
redpolline
35ff20ebfc Add image buffer writing, file copy, avatar save.
Adds functions for saving the user selected avatar image to the global
settings folder. (These also get reused to send the avatar to remote
users.)
2025-02-12 09:35:24 -05:00
redpolline
e555bcef7a Init callback objects first, fix mutex locking
Init callback related objects in Steam_Client before initing anything
else.

Fix missing global_mutex lock in Steam_Client::RegisterCallback() and
Steam_Client::UnregisterCallback().
2025-02-12 09:35:24 -05:00
redpolline
55277ab770 Change filenames for global settings avatar images...
... and fix the debug messages.

This changes the filenames to be "avatar_*" instead of "profile_*" to
keep things consistent with the proper naming elsewhere.
2025-02-12 09:35:24 -05:00
redpolline
bfb0272300 Fix debug message for Steam_Utils::GetImageRGBA(). 2025-02-12 09:35:24 -05:00
redpolline
f560fce352 Add protobuf message type Image and Friend_Avatar.
Also adds Friend_Avatar to the Common_Message list of possible
messages.
2025-02-12 09:35:24 -05:00
redpolline
75035de2f4 Add try_get_steam_client().
This allows the emulator to attempt to access the global steam_client object
without creating it if it doesn't exist.
2025-02-12 09:35:24 -05:00
redpolline
cde29f0fd0 Create GOLDBERG_CALLBACK_INTERNAL() macro.
This allows the usage of steam callbacks within the emulator itself.
2025-02-12 09:35:24 -05:00
redpolline
1fa0f4d4d5 Add fs utility functions for overlay use.
As we need to add a file chooser to the overlay, we need the backend
functions for it to use.

This commit adds:

Local_Storage::get_parent_directory().
Local_Storage::is_directory().
Local_Storage::get_user_pictures_path().
Local_Storage::get_drive_list().
Posix version of DirectoryExists().
2025-02-12 09:35:24 -05:00
redpolline
d493e30b98 Add avatar image loading from global ...
... settings directory.

Also adds some additional related debug logging, and a utility function
for converting between std::vector<image_pixel_t> used by Local_Storage::load_image(),
and std::string used by Settings::add_image().
2025-02-12 09:35:23 -05:00
redpolline
0eaba52f76 Make add_friend_avatars handle local_user avatar
... changes.

Implements STEAM_CALL_RESULT( AvatarImageLoaded_t ).
Adds support for a sending a STEAM_CALL_RESULT( PersonaStateChange_t ) with the k_EPersonaChangeAvatar flag.

Creates a mapping in Settings to hold the avatar image data.

Also adds additional debug logging to indicate which image handle is
returned for each user / image size.
2025-02-12 09:35:23 -05:00
redpolline
1408890d20 Enumerate fonts under Windows instead of ...
... hardcoding a path to a font file from the system directory.

Wine doesn't have anything in there, and doing it this way allows
Wine to "just work" without using Winetricks.
2025-02-12 09:35:23 -05:00
redpolline
5241fc892f Overlay: Implement achievement icon display.
Display achievement icons in steam_overlay, and during achievement
notifications.

Add total achievement counts and progress bar to steam_overlay.

Add new global settings for displaying unearned hidden achievements in
the achievement list and displaying achievement descriptions in unlock
notifications. (Both disabled by default.)
2025-02-12 09:35:23 -05:00
redpolline
59b8354f2d Win7 / Wine fixes DX11_Hook.cpp.
Don't create image resources if the D3D device isn't inited yet.
(Causes app crash.)

Set quality value on substruct.
2025-02-12 09:35:23 -05:00
redpolline
77d2a84af8 Wine + Enscripten fixes for OpenGL_Hook.cpp. 2025-02-12 09:35:23 -05:00
redpolline
2164ff292c Extra debugging log functions. 2025-02-12 09:35:23 -05:00
redpolline
8029c41c04 Implement ISteamUserStats::GetAchievementIcon(). 2025-02-12 09:35:23 -05:00
redpolline
662e22bade Add some achievement display settings. 2025-02-12 09:35:23 -05:00
redpolline
dfc486dd3b Add functions for global flag settings, ...
return width and height for loaded images.
2025-02-12 09:35:23 -05:00
redpolline
a1ec70d3b0 Fix memory leak in resolve_ip. 2025-02-12 09:35:22 -05:00
redpolline
a8c696c565 Fix detours not attaching to all threads on startup. 2025-02-12 09:35:22 -05:00
redpolline
c9236a7337 Fix compiler warnings. 2025-02-12 09:35:22 -05:00
redpolline
e767bb9fe9 Add inttypes defs to common_includes.h 2025-02-12 09:35:22 -05:00
redpolline
e88f92cf4a Add 32bit registry view editing to ColdClientLoader. 2025-02-12 09:35:22 -05:00
redpolline
629473b53e Set env:SteamAppPath in steamclient_loader. 2025-02-12 09:35:22 -05:00
redpolline
8e8355c013 Add missing header include guards. 2025-02-12 09:35:22 -05:00
redpolline
ae6e1829dd CI: Use winehq.org's rpm until fedora 40 goes EOL.
Otherwise, we'll be constantly changing the URL in the CI yml everytime
Wine makes a new point release.
2025-02-12 09:32:46 -05:00
redpolline
74d22df42e Fix CI to use BAT files only for win build.
For consistency have the CI use the same build path as
the end-user builds.

Use where.exe from wine-10.0.

CI's version is a stub. Use one that actually works, until the CI gets
updated.

Also, fix broken RtlGenRandom by importing ADVAPI32's GetUserNameW(),
and calling GetModuleHandleW() / GetProcAddress() for SystemFunction032().
Instead of trying to use a fake import lib.

Bonus: Can now use the host system's username as the default for the
steam user name instead of "Noob".
("Noob" is still used as the fallback if this call fails, or the host
system's username is invalid.)
2025-02-11 07:59:19 -05:00
79 changed files with 6557 additions and 657 deletions

View File

@ -59,27 +59,34 @@ 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" " " | tr "/" "\\\\")"; sed "s|dll/\*.cpp|$DLL_FILES|g" -i *.bat
- DLL_FILES="$(ls dll/*.proto | tr "\n" " " | tr "/" "\\\\" | sed "s/.proto/.pb.cc/g")"; sed "s|dll/\*.cc|$DLL_FILES|g" -i *.bat
- sed "s| /MP12 | /MP4 |g" -i *.bat
# CI can't produce PDBs. Throws a bunch of errors, and skips building the PEs.
- sed "s| /DDEBUG\:FULL | |g" -i *.bat
# Turn on echo.
- sed "s|echo off|echo on|g" -i *.bat
- python generate_build_win_bat.py
- touch CI_BUILD.TAG
- export WINEDEBUG=-all
- wine cmd /c build_win_release_test.bat
- cp build_win_release_test.bat release/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/
@ -162,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

@ -1,4 +0,0 @@
#!/bin/bash
protoc -I"${PWD}/dll/" --cpp_out="${PWD}/dll/" "${PWD}"/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 libsteam_api.so
clang++ -fPIC -o lobby_connect lobby_connect.cpp dll/*.cpp dll/*.cc -g3 -Wno-return-type -fsanitize=address -lasan -lprotobuf-lite -std=c++14 && echo built lobby_connect

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,38 +1,9 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\experimental ( mkdir build\experimental )
IF NOT EXIST build\experimental\debug ( mkdir build\experimental\debug )
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 EXIST build\experimental\debug\x86\*.* ( DEL /F /S /Q build\experimental\debug\x86\*.* )
IF EXIST build\experimental\debug\x64\*.* ( DEL /F /S /Q build\experimental\debug\x64\*.* )
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
IF NOT EXIST debug ( mkdir debug )
IF NOT EXIST debug\experimental ( mkdir debug\experimental )
IF EXIST debug\experimental\*.* ( DEL /F /S /Q debug\experimental\*.* )
SET SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD=1
SET SKIP_STEAMCLIENT_LOADER=1
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\experimental\debug\x86
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /I%OLD_DIR%/ImGui /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental\steam_api.pdb /link /OUT:%OLD_DIR%\debug\experimental\steam_api.dll
cl /LD %OLD_DIR%/steamclient.cpp /EHsc /MP12 /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental\steamclient.pdb /link /OUT:%OLD_DIR%\debug\experimental\steamclient.dll
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\experimental\debug\x64
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /I%OLD_DIR%/ImGui /I%OLD_DIR%/%PROTOBUF_X64_DIRECTORY%\include\ /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental\steam_api64.pdb /link /OUT:%OLD_DIR%\debug\experimental\steam_api64.dll
cl /LD %OLD_DIR%/steamclient.cpp /EHsc /MP12 /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental\steamclient64.pdb /link /OUT:%OLD_DIR%\debug\experimental\steamclient64.dll
cd %OLD_DIR%
endlocal
call build_win_debug_experimental_steamclient.bat

View File

@ -1,36 +1,141 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
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\debug\x86 ( mkdir build\experimental_steamclient\debug\x86 )
IF NOT EXIST build\experimental_steamclient\debug\x64 ( mkdir build\experimental_steamclient\debug\x64 )
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\*.* )
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 NOT EXIST debug ( mkdir debug )
IF NOT EXIST debug\experimental_steamclient ( mkdir debug\experimental_steamclient )
IF EXIST debug\experimental_steamclient\*.* ( DEL /F /S /Q debug\experimental_steamclient\*.* )
call build_set_protobuf_directories.bat
setlocal
IF DEFINED SKIP_X86 GOTO LK_X64
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
SET OLD_DIR=%cd%
cd build\experimental_steamclient\debug\x86
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /I%OLD_DIR%/ImGui /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_EXPERIMENTAL_BUILD /DEMU_OVERLAY /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental_steamclient\steamclient.pdb /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient.dll
cl %OLD_DIR%/steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x32.pdb /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x32.exe
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
SET OLD_DIR=%cd%
cd build\experimental_steamclient\debug\x64
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /I%OLD_DIR%/ImGui /I%OLD_DIR%/%PROTOBUF_X64_DIRECTORY%\include\ /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_EXPERIMENTAL_BUILD /DEMU_OVERLAY /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental_steamclient\steamclient64.pdb /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient64.dll
cl %OLD_DIR%/steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x64.pdb /link /OUT:%OLD_DIR%\debug\experimental_steamclient\steamclient_loader_x64.exe
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

@ -1,25 +1,46 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\debug ( mkdir build\debug )
IF NOT EXIST build\debug\lobby_connect ( mkdir build\debug\lobby_connect )
IF NOT EXIST build\debug\lobby_connect\x86 ( mkdir build\debug\lobby_connect\x86 )
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 NOT EXIST debug ( mkdir debug )
IF NOT EXIST debug\lobby_connect ( mkdir debug\lobby_connect )
IF EXIST debug\lobby_connect\*.* ( DEL /F /S /Q debug\lobby_connect\*.* )
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\debug\lobby_connect\x86
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /DNO_DISK_WRITES /DLOBBY_CONNECT /DEMU_RELEASE_BUILD /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ %OLD_DIR%/lobby_connect.cpp %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Comdlg32.lib /EHsc /MP12 /Ox /DDEBUG:FULL /Zi /Fd:%OLD_DIR%\debug\lobby_connect\lobby_connect.pdb /link /OUT:%OLD_DIR%\debug\lobby_connect\lobby_connect.exe
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%
copy Readme_lobby_connect.txt debug\lobby_connect\Readme.txt
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,20 +1,39 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\release ( mkdir build\release )
IF NOT EXIST build\release\tools ( mkdir build\release\tools )
IF NOT EXIST build\release\tools\x86 ( mkdir build\release\tools\x86 )
IF EXIST build\release\tools\x86\*.* ( DEL /F /S /Q build\release\tools\x86\*.* )
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 NOT EXIST release\tools ( mkdir release\tools )
IF EXIST release\tools\*.* ( DEL /F /S /Q release\tools\*.* )
setlocal
call build_env_x86.bat
SET OLD_DIR=%cd%
cd build\release\tools\x86
cl %OLD_DIR%/generate_interfaces_file.cpp /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\tools\generate_interfaces_file.exe
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%
copy Readme_generate_interfaces.txt release\tools\Readme_generate_interfaces.txt
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,23 +1,46 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\release ( mkdir build\release )
IF NOT EXIST build\release\lobby_connect ( mkdir build\release\lobby_connect )
IF NOT EXIST build\release\lobby_connect\x86 ( mkdir build\release\lobby_connect\x86 )
IF EXIST build\release\lobby_connect\x86\*.* ( DEL /F /S /Q build\release\lobby_connect\x86\*.* )
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 NOT EXIST release\lobby_connect ( mkdir release\lobby_connect )
IF EXIST release\lobby_connect\*.* ( DEL /F /S /Q release\lobby_connect\*.* )
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\release\lobby_connect\x86
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /DNO_DISK_WRITES /DLOBBY_CONNECT /DEMU_RELEASE_BUILD /DNDEBUG /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ %OLD_DIR%/lobby_connect.cpp %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Comdlg32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\lobby_connect\lobby_connect.exe
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%
copy Readme_lobby_connect.txt release\lobby_connect\Readme.txt
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,42 +1,51 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\release ( mkdir build\release )
IF NOT EXIST build\release\x86 ( mkdir build\release\x86 )
IF NOT EXIST build\release\x64 ( mkdir build\release\x64 )
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 NOT EXIST release ( mkdir release )
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 )
call build_set_protobuf_directories.bat
SET OLD_DIR=%cd%
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
cd build\release\x86
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\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
cd build\release\x64
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DNDEBUG /I%OLD_DIR%/%PROTOBUF_X64_DIRECTORY%\include\ %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc "%OLD_DIR%/%PROTOBUF_X64_LIBRARY%" Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\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,37 +1,9 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\experimental ( mkdir build\experimental )
IF NOT EXIST build\experimental\release ( mkdir build\experimental\release )
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 EXIST build\experimental\release\x86\*.* ( DEL /F /S /Q build\experimental\release\x86\*.* )
IF EXIST build\experimental\release\x64\*.* ( DEL /F /S /Q build\experimental\release\x64\*.* )
IF NOT EXIST release\experimental ( mkdir release\experimental )
IF EXIST release\experimental\*.* ( DEL /F /S /Q release\experimental\*.* )
IF NOT "%1" == "" ( SET JOB_COUNT=%~1 )
call build_set_protobuf_directories.bat
SET SKIP_EXPERIMENTAL_STEAMCLIENT_BUILD=1
SET SKIP_STEAMCLIENT_LOADER=1
setlocal
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
SET OLD_DIR=%cd%
cd "build\experimental\release\x86"
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /DNDEBUG /I%OLD_DIR%/ImGui /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\experimental\steam_api.dll
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG %OLD_DIR%/steamclient.cpp /EHsc /MP4 /Ox /link /OUT:%OLD_DIR%\release\experimental\steamclient.dll
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 "%OLD_DIR%\build\experimental\release\x64"
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DCONTROLLER_SUPPORT /DEMU_OVERLAY /DNDEBUG /I%OLD_DIR%/ImGui /I%OLD_DIR%/%PROTOBUF_X64_DIRECTORY%\include\ /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\experimental\steam_api64.dll
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DNDEBUG %OLD_DIR%/steamclient.cpp /EHsc /MP4 /Ox /link /OUT:%OLD_DIR%\release\experimental\steamclient64.dll
cd %OLD_DIR%
copy Readme_experimental.txt release\experimental\Readme.txt
endlocal
call build_win_release_experimental_steamclient.bat

View File

@ -1,38 +1,141 @@
@echo off
cd /d "%~dp0"
IF NOT EXIST build ( mkdir build )
IF NOT EXIST build\experimental ( mkdir build\experimental )
IF NOT EXIST build\experimental\steamclient ( mkdir build\experimental\steamclient )
IF NOT EXIST build\experimental\steamclient\release ( mkdir build\experimental\steamclient\release )
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 )
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 NOT EXIST release\experimental_steamclient ( mkdir release\experimental_steamclient )
IF EXIST release\experimental_steamclient\*.* ( DEL /F /S /Q release\experimental_steamclient\*.* )
call build_set_protobuf_directories.bat
setlocal
IF DEFINED SKIP_X86 GOTO LK_X64
"%PROTOC_X86_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
call build_env_x86.bat
SET OLD_DIR=%cd%
cd "build\experimental\steamclient\release\x86"
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_OVERLAY /I%OLD_DIR%/ImGui /DNDEBUG /I%OLD_DIR%/%PROTOBUF_X86_DIRECTORY%\include\ /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X86_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient.dll
cl %OLD_DIR%/steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient_loader_x32.exe
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%
copy steamclient_loader\ColdClientLoader.ini release\experimental_steamclient\
: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
SET OLD_DIR=%cd%
cd "build\experimental\steamclient\release\x64"
cl %OLD_DIR%/dll/rtlgenrandom.c %OLD_DIR%/dll/rtlgenrandom.def
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_OVERLAY /I%OLD_DIR%/ImGui /DNDEBUG /I%OLD_DIR%/%PROTOBUF_X64_DIRECTORY%\include\ /I%OLD_DIR%/overlay_experimental %OLD_DIR%/dll/*.cpp %OLD_DIR%/dll/*.cc %OLD_DIR%/detours/*.cpp %OLD_DIR%/controller/gamepad.c %OLD_DIR%/ImGui/*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_dx*.cpp %OLD_DIR%/ImGui/backends/imgui_impl_win32.cpp %OLD_DIR%/ImGui/backends/imgui_impl_vulkan.cpp %OLD_DIR%/ImGui/backends/imgui_impl_opengl3.cpp %OLD_DIR%/ImGui/backends/imgui_win_shader_blobs.cpp %OLD_DIR%/overlay_experimental/*.cpp %OLD_DIR%/overlay_experimental/windows/*.cpp %OLD_DIR%/overlay_experimental/System/*.cpp "%OLD_DIR%/%PROTOBUF_X64_LIBRARY%" opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient64.dll
cl %OLD_DIR%/steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:%OLD_DIR%\release\experimental_steamclient\steamclient_loader_x64.exe
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
endlocal

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
@ -112,6 +125,7 @@ inline void reset_LastError()
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <sys/time.h>
@ -126,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
@ -151,6 +174,7 @@ inline void reset_LastError()
#include <fstream>
#include <sstream>
#include <iterator>
#include <typeinfo>
#include <vector>
#include <map>
@ -202,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)
#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);
@ -143,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;
@ -170,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());
}
}
@ -217,9 +217,39 @@ uint32 create_localstorage_settings(Settings **settings_client_out, Settings **s
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));
}
@ -230,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;
@ -265,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;
{
@ -304,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();
@ -322,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) {
@ -380,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";
@ -628,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;
@ -636,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) {
@ -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,
@ -303,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
{
@ -300,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

View File

@ -17,6 +17,9 @@
#include "base.h"
#ifndef INCLUDED_STEAM_REMOTEPLAY_H
#define INCLUDED_STEAM_REMOTEPLAY_H
class Steam_RemotePlay :
public ISteamRemotePlay
{
@ -111,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;
@ -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

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,132 +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"]
lobby_connect_args = ["/DNO_DISK_WRITES", "/DLOBBY_CONNECT"]
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
mkdir release\lobby_connect
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\\
REM call build_win_lobby_connect.bat
copy Readme_lobby_connect.txt release\lobby_connect\Readme.txt
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("./", "lobby_connect.cpp") + files_from_dir("dll", "flat.cpp") + files_from_dir("dll", "dll.cpp") + lobby_connect_args + normal_build_args + release_build_args + includes_32 + proto_deps + steam_deps + normal_linker_libs + ["Comdlg32.lib", "user32.lib"], linker_32 + ["/debug:none", "/OUT:release\lobby_connect\lobby_connect.exe"])
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

@ -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

@ -127,6 +127,9 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
}
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))
@ -138,6 +141,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
return 0;
}
HKEY Registrykey;
HKEY Registrykey_32BitView;
// Declare some variables to be used for Steam registry.
DWORD UserId = 0x03100004771F810D & 0xffffffff;
DWORD ProcessID = GetCurrentProcessId();
@ -146,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;
@ -166,30 +174,53 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
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);
return 0;
}
}
// 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);
@ -206,6 +237,15 @@ 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.