4 Commits

Author SHA1 Message Date
acidicoala
907e939b67 Fixed string section name 2026-01-04 04:49:35 +05:00
acidicoala
7b82994b17 Regenerate linux proxy exports 2026-01-04 04:49:28 +05:00
acidicoala
11bd820921 Sync KoalaBox (brotli, openssl) 2026-01-04 04:49:19 +05:00
acidicoala
9acf7312d3 Fixed static order init fiasco 2026-01-02 21:57:41 +05:00
12 changed files with 1957 additions and 52 deletions

2
.idea/SmokeAPI.iml generated
View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CIDR" type="CPP_MODULE" version="4" />

View File

@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="linux_exports_generator [32]" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="--input_libs_glob $ProjectFileDir$/res/steamworks/*/binaries/linux32/libsteam_api.so --output_path $ProjectFileDir$/src/generated/32/proxy_exports" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="linux_exports_generator" CONFIG_NAME="Debug [64]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="linux_exports_generator">
<configuration default="false" name="linux_exports_generator [32]" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="--input_libs_glob $ProjectFileDir$/res/steamworks/*/binaries/linux32/libsteam_api.so --output_path $ProjectFileDir$/src/generated/32/proxy_exports" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="linux_exports_generator" CONFIG_NAME="Debug [32]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="linux_exports_generator">
<method v="2">
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
</method>

View File

@@ -150,9 +150,6 @@ The following list features links in Arch Linux repositories, but if you are usi
you should use the equivalent package for your distro.
Required libraries:
- [brotli](https://archlinux.org/packages/core/x86_64/brotli/)
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-brotli/)]
- [gcc-libs](https://archlinux.org/packages/core/x86_64/gcc-libs/)
[[32-bit](https://archlinux.org/packages/core/x86_64/lib32-gcc-libs/)]
@@ -165,12 +162,6 @@ Required libraries:
- [libnghttp2](https://archlinux.org/packages/core/x86_64/libnghttp2/)
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-libnghttp2/)]
- [libssh2](https://archlinux.org/packages/core/x86_64/libssh2/)
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-libssh2/)]
- [openssl](https://archlinux.org/packages/core/x86_64/openssl/)
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-openssl/)]
- [zlib](https://archlinux.org/packages/core/x86_64/zlib/)
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-zlib/)]
@@ -194,7 +185,6 @@ wrappers might cause issues in theory. However, in practice real tests show that
chance of success compared to proxy mode. So, at the end of the day, try both modes to see which one works
best for you.
### 🔀 Proxy mode (🐧 Linux)
Same as on Windows:
@@ -214,10 +204,10 @@ For example:
1. Extract and paste the `libsmoke_api32.so` or `libsmoke_api64.so` in the root of game's installation directory.
2. In Steam _Library_ open game's _Properties_, switch to the _General_ tab, and set the following _LAUNCH OPTIONS_:
| Bitness | Launch Options |
|---------|------------------------------------------------------------------------------------------------------------------------|
| 32-bit | `LD_PRELOAD="./libsmoke_api32.so $HOME/.local/share/Steam/ubuntu12_32/gameoverlayrenderer.so" ./<GameExe32> %command%` |
| 64-bit | `LD_PRELOAD="./libsmoke_api64.so $HOME/.local/share/Steam/ubuntu12_64/gameoverlayrenderer.so" ./<GameExe64> %command%` |
| Bitness | Launch Options |
|---------|---------------------------------------------------------------------------------------------------------------------------------|
| 32-bit | `LD_PRELOAD="./libsmoke_api32.so $HOME/.local/share/Steam/ubuntu12_32/gameoverlayrenderer.so" ./<GameExe32> ; exit ; %command%` |
| 64-bit | `LD_PRELOAD="./libsmoke_api64.so $HOME/.local/share/Steam/ubuntu12_64/gameoverlayrenderer.so" ./<GameExe64> ; exit ; %command%` |
Where `<GameExe32>` and `<GameExe64>` correspond to the actual filename of the game executable. For example:
- `TheEscapists2.x86` (32-bit)
@@ -234,6 +224,9 @@ If you have other environment variables, and you don't know how to correctly com
then please make extensive use of search engines and LLMs for guidance and examples
before seeking help the official forum topic.
> [!NOTE]
> The `; exit ; %command%` at the end of launch options
> is a trick used to force Steam to directly run the game executable.
## ⚙ Configuration

File diff suppressed because it is too large Load Diff

View File

@@ -7208,6 +7208,211 @@ EXPORT void VR_Shutdown() {
asm volatile ("jmp *%rax");
}
EXPORT void __gcclibcxx_demangle_callback() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __gxx_personality_v0() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __new_handler() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap___lxstat() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap___lxstat64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap___xstat() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap___xstat64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_access() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_chdir() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_chmod() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_chown() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_dlmopen() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_dlopen() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_fopen() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_fopen64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_freopen() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_lchown() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_link() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_lstat() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_lstat64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_mkdir() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_mkfifo() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_mknod() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_mount() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_open() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_open64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_opendir() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_rename() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_rmdir() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_scandir() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_scandir64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_stat() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_stat64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_statfs() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_statfs64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_statvfs() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_statvfs64() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_symlink() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_unlink() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_utime() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void __wrap_utimes() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
}
EXPORT void g_pSteamClientGameServer() {
asm volatile ("movabs $0xFeedBeefDeadC0de, %%rax":::"rax");
asm volatile ("jmp *%rax");
@@ -14443,6 +14648,211 @@ namespace proxy_exports {
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__gcclibcxx_demangle_callback");
src_address = dlsym(original_lib_handle, "__gcclibcxx_demangle_callback");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__gxx_personality_v0");
src_address = dlsym(original_lib_handle, "__gxx_personality_v0");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__new_handler");
src_address = dlsym(original_lib_handle, "__new_handler");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap___lxstat");
src_address = dlsym(original_lib_handle, "__wrap___lxstat");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap___lxstat64");
src_address = dlsym(original_lib_handle, "__wrap___lxstat64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap___xstat");
src_address = dlsym(original_lib_handle, "__wrap___xstat");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap___xstat64");
src_address = dlsym(original_lib_handle, "__wrap___xstat64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_access");
src_address = dlsym(original_lib_handle, "__wrap_access");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_chdir");
src_address = dlsym(original_lib_handle, "__wrap_chdir");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_chmod");
src_address = dlsym(original_lib_handle, "__wrap_chmod");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_chown");
src_address = dlsym(original_lib_handle, "__wrap_chown");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_dlmopen");
src_address = dlsym(original_lib_handle, "__wrap_dlmopen");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_dlopen");
src_address = dlsym(original_lib_handle, "__wrap_dlopen");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_fopen");
src_address = dlsym(original_lib_handle, "__wrap_fopen");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_fopen64");
src_address = dlsym(original_lib_handle, "__wrap_fopen64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_freopen");
src_address = dlsym(original_lib_handle, "__wrap_freopen");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_lchown");
src_address = dlsym(original_lib_handle, "__wrap_lchown");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_link");
src_address = dlsym(original_lib_handle, "__wrap_link");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_lstat");
src_address = dlsym(original_lib_handle, "__wrap_lstat");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_lstat64");
src_address = dlsym(original_lib_handle, "__wrap_lstat64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_mkdir");
src_address = dlsym(original_lib_handle, "__wrap_mkdir");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_mkfifo");
src_address = dlsym(original_lib_handle, "__wrap_mkfifo");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_mknod");
src_address = dlsym(original_lib_handle, "__wrap_mknod");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_mount");
src_address = dlsym(original_lib_handle, "__wrap_mount");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_open");
src_address = dlsym(original_lib_handle, "__wrap_open");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_open64");
src_address = dlsym(original_lib_handle, "__wrap_open64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_opendir");
src_address = dlsym(original_lib_handle, "__wrap_opendir");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_rename");
src_address = dlsym(original_lib_handle, "__wrap_rename");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_rmdir");
src_address = dlsym(original_lib_handle, "__wrap_rmdir");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_scandir");
src_address = dlsym(original_lib_handle, "__wrap_scandir");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_scandir64");
src_address = dlsym(original_lib_handle, "__wrap_scandir64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_stat");
src_address = dlsym(original_lib_handle, "__wrap_stat");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_stat64");
src_address = dlsym(original_lib_handle, "__wrap_stat64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_statfs");
src_address = dlsym(original_lib_handle, "__wrap_statfs");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_statfs64");
src_address = dlsym(original_lib_handle, "__wrap_statfs64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_statvfs");
src_address = dlsym(original_lib_handle, "__wrap_statvfs");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_statvfs64");
src_address = dlsym(original_lib_handle, "__wrap_statvfs64");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_symlink");
src_address = dlsym(original_lib_handle, "__wrap_symlink");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_unlink");
src_address = dlsym(original_lib_handle, "__wrap_unlink");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_utime");
src_address = dlsym(original_lib_handle, "__wrap_utime");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "__wrap_utimes");
src_address = dlsym(original_lib_handle, "__wrap_utimes");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);
std::memcpy(static_cast<uint8_t*>(dest_address) + 2, &src_address, sizeof(void*));
dest_address = dlsym(self_lib_handle, "g_pSteamClientGameServer");
src_address = dlsym(original_lib_handle, "g_pSteamClientGameServer");
if(!src_address) src_address = reinterpret_cast<void*>(panic_exit);

View File

@@ -25,7 +25,7 @@
#include "build_config.h"
#if defined(KB_WIN)
#ifdef KB_WIN
#include "koalabox/win.hpp"
#elif defined(KB_LINUX) && defined(KB_32)
#include "generated/32/proxy_exports.hpp"
@@ -64,11 +64,14 @@ namespace {
std::set<std::string> versions;
const auto rdata_section = kb::lib::get_section_or_throw(steamapi_handle, kb::lib::CONST_STR_SECTION);
const auto rdata = rdata_section.to_string();
// On Linux the section name depends on individual lib file, so we can't use generic constants
// ReSharper disable once CppDFAUnreachableCode
const std::string str_section_name = kb::platform::is_windows ? ".rdata" : ".rodata";
const auto str_section = kb::lib::get_section_or_throw(steamapi_handle, str_section_name);
const auto str_section_str = str_section.to_string();
const std::regex pattern(R"(SteamClient\d{3})");
const auto matches_begin = std::sregex_iterator(rdata.begin(), rdata.end(), pattern);
const auto matches_begin = std::sregex_iterator(str_section_str.begin(), str_section_str.end(), pattern);
const auto matches_end = std::sregex_iterator();
for(std::sregex_iterator i = matches_begin; i != matches_end; ++i) {
@@ -108,10 +111,10 @@ namespace {
static const auto CreateInterface$ = KB_LIB_GET_FUNC(steamclient_handle, CreateInterface);
if(auto* steamapi_handle = kb::lib::get_lib_handle(STEAM_API_MODULE)) {
if(original_steamapi_handle) {
// SteamAPI might have been initialized.
// Hence, we need to query SteamClient interfaces and hook them if needed.
const auto steamclient_versions = find_steamclient_versions(steamapi_handle);
const auto steamclient_versions = find_steamclient_versions(original_steamapi_handle);
for(const auto& steamclient_version : steamclient_versions) {
if(CreateInterface$(steamclient_version.c_str(), nullptr)) {
#ifdef KB_WIN
@@ -123,6 +126,8 @@ namespace {
LOG_INFO("'{}' has not been initialized. Waiting for initialization.", steamclient_version);
}
}
} else {
LOG_ERROR("{} -> original_steamapi_handle is null", __func__);
}
return true;
@@ -229,16 +234,16 @@ namespace smoke_api {
kb::globals::init_globals(self_module_handle, PROJECT_NAME);
config::instance = kb::config::parse<config::Config>();
config::get() = kb::config::parse<config::Config>();
if(config::instance.logging) {
if(config::get().logging) {
kb::logger::init_file_logger(kb::paths::get_log_path());
} else {
kb::logger::init_null_logger();
}
LOG_INFO("{} v{}{} | Built at '{}'", PROJECT_NAME, PROJECT_VERSION, VERSION_SUFFIX, __TIMESTAMP__);
LOG_DEBUG("Parsed config:\n{}", nlohmann::ordered_json(config::instance).dump(2));
LOG_DEBUG("Parsed config:\n{}", nlohmann::ordered_json(config::get()).dump(2));
const auto exe_path = kb::lib::get_fs_path(nullptr);
const auto exe_name = kb::path::to_str(exe_path.filename());

View File

@@ -1,14 +1,16 @@
#include <koalabox/config.hpp>
#include <koalabox/io.hpp>
#include <koalabox/logger.hpp>
#include "smoke_api/config.hpp"
namespace smoke_api::config {
Config instance; // NOLINT(cert-err58-cpp)
Config& get() noexcept {
static Config config;
return config;
}
std::vector<DLC> get_extra_dlcs(const uint32_t app_id) {
return DLC::get_dlcs_from_apps(instance.extra_dlcs, app_id);
return DLC::get_dlcs_from_apps(get().extra_dlcs, app_id);
}
bool is_dlc_unlocked(
@@ -16,16 +18,16 @@ namespace smoke_api::config {
const AppId_t dlc_id,
const std::function<bool()>& original_function
) {
auto status = instance.default_app_status;
auto status = get().default_app_status;
const auto app_id_str = std::to_string(app_id);
if(instance.override_app_status.contains(app_id_str)) {
status = instance.override_app_status[app_id_str];
if(get().override_app_status.contains(app_id_str)) {
status = get().override_app_status[app_id_str];
}
const auto dlc_id_str = std::to_string(dlc_id);
if(instance.override_dlc_status.contains(dlc_id_str)) {
status = instance.override_dlc_status[dlc_id_str];
if(get().override_dlc_status.contains(dlc_id_str)) {
status = get().override_dlc_status[dlc_id_str];
}
bool is_unlocked;

View File

@@ -43,7 +43,7 @@ namespace smoke_api::config {
)
};
extern Config instance;
Config& get() noexcept;
std::vector<DLC> get_extra_dlcs(AppId_t app_id);

View File

@@ -14,8 +14,15 @@ namespace {
/// This means we have to get extra DLC IDs from local config, remote config, or cache.
constexpr auto MAX_DLC = 64;
std::map<uint32_t, std::vector<DLC>> app_dlcs; // NOLINT(cert-err58-cpp)
std::set<uint32_t> fully_fetched; // NOLINT(cert-err58-cpp)
auto& get_fully_fetched_apps() {
static std::set<uint32_t> fully_fetched_apps;
return fully_fetched_apps;
}
auto& get_app_dlc_map() {
static std::map<uint32_t, std::vector<DLC>> app_dlc_map;
return app_dlc_map;
}
std::string get_app_id_log(const uint32_t app_id) {
return app_id ? std::format("App ID: {:>8}, ", app_id) : "";
@@ -31,13 +38,13 @@ namespace {
if(app_id == 0) {
LOG_ERROR("{} -> App ID is 0", __func__);
app_dlcs[app_id] = {}; // Dummy value to avoid checking for presence on each access
get_app_dlc_map()[app_id] = {}; // Dummy value to avoid checking for presence on each access
return;
}
// We want to fetch data only once. However, if any of the remote sources have failed
// previously, we want to attempt fetching again.
if(fully_fetched.contains(app_id)) {
if(get_fully_fetched_apps().contains(app_id)) {
return;
}
@@ -67,13 +74,13 @@ namespace {
}
if(github_dlcs_opt && steam_dlcs_opt) {
fully_fetched.insert(app_id);
get_fully_fetched_apps().insert(app_id);
} else {
append_dlcs(smoke_api::cache::get_dlcs(app_id), "disk cache");
}
// Cache DLCs in memory and cache for future use
app_dlcs[app_id] = aggregated_dlcs;
get_app_dlc_map()[app_id] = aggregated_dlcs;
smoke_api::cache::save_dlcs(app_id, aggregated_dlcs);
}
@@ -137,12 +144,12 @@ namespace smoke_api::steam_apps {
fetch_and_cache_dlcs(app_id);
if(app_dlcs.empty()) {
if(get_app_dlc_map().empty()) {
LOG_DEBUG("{} -> No cached DLCs, responding with original count", function_name);
return total_count(original_count);
}
return total_count(static_cast<int>(app_dlcs[app_id].size()));
return total_count(static_cast<int>(get_app_dlc_map()[app_id].size()));
} catch(const std::exception& e) {
LOG_ERROR("{} -> Uncaught exception: {}", function_name, e.what());
return 0;
@@ -188,8 +195,8 @@ namespace smoke_api::steam_apps {
pchName[bytes_to_copy] = '\0'; // Ensure null-termination
};
if(!app_dlcs.empty() && app_dlcs.contains(app_id)) {
const auto& dlcs = app_dlcs[app_id];
if(!get_app_dlc_map().empty() && get_app_dlc_map().contains(app_id)) {
const auto& dlcs = get_app_dlc_map()[app_id];
if(iDLC >= 0 && iDLC < dlcs.size()) {
output_dlc(dlcs[iDLC]);

View File

@@ -14,7 +14,7 @@ namespace smoke_api::steam_http {
try {
const auto result = original_function();
if(config::instance.log_steam_http) {
if(config::get().log_steam_http) {
const std::string_view buffer =
pBodyDataBuffer && unBufferSize
? std::string_view(
@@ -50,7 +50,7 @@ namespace smoke_api::steam_http {
try {
const auto result = original_function();
if(config::instance.log_steam_http) {
if(config::get().log_steam_http) {
const std::string_view buffer =
pBodyDataBuffer && unBufferSize
? std::string_view(
@@ -87,7 +87,7 @@ namespace smoke_api::steam_http {
try {
const auto result = original_function();
if(config::instance.log_steam_http) {
if(config::get().log_steam_http) {
const std::string_view content_type =
pchContentType ? pchContentType : "smoke_api::N/A";

View File

@@ -70,11 +70,11 @@ namespace smoke_api::steam_inventory {
);
static uint32_t original_count = 0;
const auto injected_count = config::instance.extra_inventory_items.size();
const auto injected_count = config::get().extra_inventory_items.size();
// Automatically get inventory items from steam
static std::vector<SteamItemDef_t> auto_inventory_items;
if(config::instance.auto_inject_inventory) {
if(config::get().auto_inject_inventory) {
static std::once_flag inventory_inject_flag;
std::call_once(
inventory_inject_flag,
@@ -126,7 +126,7 @@ namespace smoke_api::steam_inventory {
for(int i = 0; i < injected_count; i++) {
auto& item = pOutItemsArray[original_count + auto_injected_count + i];
const auto item_def_id = config::instance.extra_inventory_items[i];
const auto item_def_id = config::get().extra_inventory_items[i];
item = new_item(item_def_id);