mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2026-06-15 23:55:23 -04:00
Compare commits
105 Commits
v3.1.5
...
e69734f9e7
| Author | SHA1 | Date | |
|---|---|---|---|
| e69734f9e7 | |||
| bfc59ab64f | |||
| a6f43d80e6 | |||
| db58468823 | |||
| 15ba0ed447 | |||
| aa0504ff14 | |||
| 3312e92dce | |||
| e6dbffb671 | |||
| ef3b8894e3 | |||
| 009d839ec3 | |||
| 70160206b8 | |||
| 86eb2085e7 | |||
| 5f07cec291 | |||
| 4bf9898f83 | |||
| 1f8fab7b48 | |||
| 36d5143463 | |||
| d5db62c2f2 | |||
| 7e9c4c42b9 | |||
| cc17984702 | |||
| 293f490e1d | |||
| 060d6e15a3 | |||
| 96ec32228c | |||
| 725be9f346 | |||
| 5382c84906 | |||
| 5629b7b5e2 | |||
| 673cd11e47 | |||
| ec99d79bf7 | |||
| fb17902116 | |||
| fce11580d6 | |||
| 2fad0ee43f | |||
| 73fab4020d | |||
| bdbd1ff540 | |||
| 477f019b49 | |||
| 8d3d2c13d8 | |||
| b362bb2828 | |||
| 06809b2c5d | |||
| 85710cce37 | |||
| fe7eef72bd | |||
| 1572a0fd4a | |||
| 7e744f5492 | |||
| c29445126b | |||
| c6767419e4 | |||
| dac3cad5e2 | |||
| 62071a1489 | |||
| f8de04812a | |||
| df43442fce | |||
| 76cf15126c | |||
| 8194a3333d | |||
| 599749a799 | |||
| ef5bc217b0 | |||
| 9f1a5edd5f | |||
| d879b21bd4 | |||
| 5aa9ffef85 | |||
| 0c6c8e02b6 | |||
| 0f5d98e42b | |||
| 2da049ec2a | |||
| 227a920e11 | |||
| 21a4f56145 | |||
| 3ab61365ce | |||
| 2ce8967257 | |||
| 83623841bd | |||
| d46acb56e8 | |||
| 7ec6f5b277 | |||
| 7758663b2e | |||
| 3d5261e293 | |||
| 469299340f | |||
| e3505e48fb | |||
| 35ea324898 | |||
| b4c12f5a37 | |||
| 8a92c50fd3 | |||
| fe5c4cede4 | |||
| d7d5eb349b | |||
| 7b20bde2fc | |||
| 02e66ed624 | |||
| 23ee93464a | |||
| ca5fcf8cb0 | |||
| 2b3930031f | |||
| debb44c138 | |||
| 21cab6c469 | |||
| 7cb32f84db | |||
| 9a0ab12b86 | |||
| 05569a4019 | |||
| 49efd831bf | |||
| 9944f3bd3f | |||
| 53868e8bed | |||
| 842387bb2f | |||
| c062696706 | |||
| aea513fbd1 | |||
| 99564ae4b7 | |||
| 046df29a6b | |||
| 5012ed3da8 | |||
| 297382f6a2 | |||
| e6fe7ad22e | |||
| 548ba0fe00 | |||
| cd8be9f80a | |||
| ca4457556c | |||
| 509b70c0b0 | |||
| ac9c1a3fcc | |||
| 265829f434 | |||
| d03f95adb7 | |||
| d8e1333d42 | |||
| 922b649fc3 | |||
| d829396c08 | |||
| 59d45c9dab | |||
| 81a8ef42ab |
@@ -1,3 +1,4 @@
|
||||
* text eol=lf
|
||||
|
||||
*.dll binary
|
||||
*.so binary
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
name: Continuous Integration
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
ci:
|
||||
name: CI
|
||||
uses: acidicoala/KoalaBox/.github/workflows/build-and-package.yml@a2838977f0b6a2933814e301e0a69ad53fdc6bce
|
||||
permissions:
|
||||
contents: write
|
||||
with:
|
||||
arch: '[ 32, 64 ]'
|
||||
config: Release
|
||||
modules: '[ "SmokeAPI" ]'
|
||||
zip_command: >
|
||||
zip -j $ZIP_NAME
|
||||
artifacts/*/*.dll
|
||||
res/SmokeAPI.config.json
|
||||
res/README.txt
|
||||
@@ -0,0 +1,11 @@
|
||||
name: '🚧 Development Build'
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**' # This prevents dev builds on tag pushes
|
||||
|
||||
jobs:
|
||||
dev-build:
|
||||
name: '🚧 Development Build'
|
||||
uses: acidicoala/SmokeAPI/.github/workflows/matrix-build.yml@master
|
||||
@@ -0,0 +1,18 @@
|
||||
name: Matrix Build
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ Linux, Windows ]
|
||||
bitness: [ 32, 64 ]
|
||||
|
||||
uses: acidicoala/KoalaBox/.github/workflows/build-cmake.yml@master
|
||||
with:
|
||||
module: SmokeAPI
|
||||
os: ${{ matrix.os }}
|
||||
bitness: ${{ matrix.bitness }}
|
||||
@@ -0,0 +1,20 @@
|
||||
name: '🏷️ Tag Release'
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
build-binaries:
|
||||
name: '🏗️ Build Binaries'
|
||||
uses: acidicoala/SmokeAPI/.github/workflows/matrix-build.yml@master
|
||||
|
||||
create-release:
|
||||
name: '📦 Create Release'
|
||||
uses: acidicoala/KoalaBox/.github/workflows/create-release.yml@master
|
||||
needs: build-binaries
|
||||
with:
|
||||
zip_files: >
|
||||
res/README.txt
|
||||
res/SmokeAPI.config.json
|
||||
Generated
+17
@@ -4,9 +4,16 @@
|
||||
<w>abcdefghijklmnopqrstuvwxyz</w>
|
||||
<w>acidicoala</w>
|
||||
<w>ajaxgetdlclist</w>
|
||||
<w>cstring</w>
|
||||
<w>dlmopen</w>
|
||||
<w>dlopen</w>
|
||||
<w>dlsym</w>
|
||||
<w>dynsym</w>
|
||||
<w>elfio</w>
|
||||
<w>endfor</w>
|
||||
<w>ghcr</w>
|
||||
<w>indicies</w>
|
||||
<w>inja</w>
|
||||
<w>inlinentd</w>
|
||||
<w>isteamapps</w>
|
||||
<w>isteamclient</w>
|
||||
@@ -16,10 +23,20 @@
|
||||
<w>koality</w>
|
||||
<w>koaloader</w>
|
||||
<w>libgtk</w>
|
||||
<w>libsteam</w>
|
||||
<w>memcpy</w>
|
||||
<w>movabs</w>
|
||||
<w>movl</w>
|
||||
<w>peparse</w>
|
||||
<w>phnt</w>
|
||||
<w>polyhook</w>
|
||||
<w>rtld</w>
|
||||
<w>simplecpp</w>
|
||||
<w>steamapi</w>
|
||||
<w>steamapps</w>
|
||||
<w>steamclient</w>
|
||||
<w>winhttp</w>
|
||||
<w>winmm</w>
|
||||
<w>wstr</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
|
||||
Generated
+1
@@ -20,4 +20,5 @@
|
||||
<option name="useRustfmt" value="true" />
|
||||
<option name="version" value="2" />
|
||||
</component>
|
||||
<component name="WestSettings"><![CDATA[{}]]></component>
|
||||
</project>
|
||||
@@ -1,7 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="exports_generator [32] [linux]" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="FALSE libsteam_api_o $ProjectFileDir$/res/steamworks/*/binaries/linux32/libsteam_api.so $CMakeCurrentGenerationDir$/generated/libsteam_api_exports.cpp" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="exports_generator" CONFIG_NAME="Debug [32]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="exports_generator">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,7 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="exports_generator [64] [win]" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="FALSE steam_api64_o $ProjectFileDir$/res/steamworks/*/binaries/steam_api64.dll $CMakeCurrentGenerationDir$/generated/linker_exports_for_steam_api.h" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="exports_generator" CONFIG_NAME="Debug [32]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="exports_generator">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,7 @@
|
||||
<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 [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>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="linux_exports_generator [64]" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="--input_libs_glob $ProjectFileDir$/res/steamworks/*/binaries/linux64/libsteam_api.so --output_path $ProjectFileDir$/src/generated/64/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>
|
||||
</configuration>
|
||||
</component>
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="steamworks_parser" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$ProjectFileDir$/res/" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="steamworks_parser" CONFIG_NAME="Debug [64]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="steamworks_parser">
|
||||
<configuration default="false" name="steamworks_parser" type="CMakeRunConfiguration" factoryName="Application" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" WORKING_DIR="file://$ProjectFileDir$/res/" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="steamworks_parser" CONFIG_NAME="Debug [32]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="steamworks_parser">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="windows_exports_generator [64]" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="--forwarded_dll_name "steam_api64_o" --lib_files_glob "$ProjectFileDir$\res\steamworks\*\binaries\steam_api64.dll" --output_file_path "$CMakeCurrentGenerationDir$\generated\linker_exports_for_steam_api.h" --sources_input_path """ REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" EMULATE_TERMINAL="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="SmokeAPI" TARGET_NAME="windows_exports_generator" CONFIG_NAME="Debug [32]" RUN_TARGET_PROJECT_NAME="SmokeAPI" RUN_TARGET_NAME="windows_exports_generator">
|
||||
<method v="2">
|
||||
<option name="com.jetbrains.cidr.execution.CidrBuildBeforeRunTaskProvider$BuildBeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
+21
-20
@@ -1,11 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
|
||||
project(SmokeAPI VERSION 3.1.5)
|
||||
project(SmokeAPI VERSION 4.0.0)
|
||||
|
||||
include(KoalaBox/cmake/KoalaBox.cmake)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_definitions(-DKB_DEBUG)
|
||||
endif()
|
||||
add_subdirectory(KoalaBox)
|
||||
add_subdirectory(tools)
|
||||
|
||||
@@ -29,8 +26,22 @@ set(SMOKE_API_STATIC_SOURCES
|
||||
static/smoke_api/steamclient/steamclient.hpp
|
||||
)
|
||||
|
||||
if(IS_LINUX)
|
||||
set(GENERATED_SOURCES_DIR src/generated/${BITNESS})
|
||||
file(MAKE_DIRECTORY ${GENERATED_SOURCES_DIR})
|
||||
set(GENERATED_SOURCES
|
||||
${GENERATED_SOURCES_DIR}/proxy_exports.hpp
|
||||
${GENERATED_SOURCES_DIR}/proxy_exports.cpp
|
||||
)
|
||||
|
||||
foreach(SRC IN LISTS GENERATED_SOURCES)
|
||||
file(TOUCH ${SRC})
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
set(SMOKE_API_SOURCES
|
||||
${SMOKE_API_STATIC_SOURCES}
|
||||
${GENERATED_SOURCES}
|
||||
src/smoke_api/smoke_api.cpp
|
||||
src/smoke_api/smoke_api.hpp
|
||||
src/steam_api/virtuals/isteamapps.cpp
|
||||
@@ -53,7 +64,6 @@ if(WIN32)
|
||||
|
||||
list(APPEND SMOKE_API_SOURCES src/main_win.cpp)
|
||||
else()
|
||||
set_32_and_64(LINUX_DIR linux32 linux64)
|
||||
set(STEAM_API_MODULE libsteam_api)
|
||||
set(STEAMCLIENT_DLL steamclient)
|
||||
|
||||
@@ -73,7 +83,6 @@ target_include_directories(SmokeAPI_common INTERFACE
|
||||
)
|
||||
target_link_libraries(SmokeAPI_common INTERFACE KoalaBox $<TARGET_OBJECTS:KoalaBox>)
|
||||
|
||||
|
||||
### Static SmokeAPI
|
||||
|
||||
add_library(SmokeAPI_static STATIC ${SMOKE_API_STATIC_SOURCES})
|
||||
@@ -105,9 +114,9 @@ if(WIN32)
|
||||
configure_linker_exports(
|
||||
TARGET SmokeAPI
|
||||
HEADER_NAME "linker_exports_for_steam_api.h"
|
||||
FORWARDED_DLL "${STEAM_API_MODULE}_o"
|
||||
INPUT_SOURCES_DIR ""
|
||||
DLL_FILES_GLOB "${CMAKE_CURRENT_SOURCE_DIR}/res/steamworks/*/binaries/${STEAM_API_MODULE}.dll"
|
||||
FORWARDED_DLL_NAME "${STEAM_API_MODULE}_o"
|
||||
LIB_FILES_GLOB "${CMAKE_CURRENT_SOURCE_DIR}/res/steamworks/*/binaries/${STEAM_API_MODULE}.dll"
|
||||
SOURCES_INPUT_PATH ""
|
||||
)
|
||||
|
||||
set(HEADER_CONTENT "#pragma once\n\n")
|
||||
@@ -117,9 +126,9 @@ if(WIN32)
|
||||
configure_linker_exports(
|
||||
TARGET SmokeAPI
|
||||
HEADER_NAME "${HEADER_NAME}"
|
||||
FORWARDED_DLL "C:/Windows/System32/${WIN_DLL}.dll"
|
||||
INPUT_SOURCES_DIR ""
|
||||
DLL_FILES_GLOB "C:/Windows/System32/${WIN_DLL}.dll"
|
||||
FORWARDED_DLL_NAME "C:/Windows/System32/${WIN_DLL}.dll"
|
||||
LIB_FILES_GLOB "C:/Windows/System32/${WIN_DLL}.dll"
|
||||
SOURCES_INPUT_PATH ""
|
||||
)
|
||||
|
||||
set(HEADER_CONTENT "${HEADER_CONTENT}#include <${HEADER_NAME}>\n")
|
||||
@@ -132,12 +141,4 @@ if(WIN32)
|
||||
|
||||
# Ignore linker warnings regarding COM-related private exports
|
||||
set_target_properties(SmokeAPI PROPERTIES LINK_FLAGS "/ignore:4104")
|
||||
else()
|
||||
# configure_linker_exports(
|
||||
# TARGET SmokeAPI
|
||||
# HEADER_NAME "libsteam_api_exports.cpp"
|
||||
# FORWARDED_DLL "${STEAM_API_MODULE}_o.so"
|
||||
# DLL_FILES_GLOB "${CMAKE_CURRENT_SOURCE_DIR}/res/steamworks/*/binaries/${LINUX_DIR}/${STEAM_API_MODULE}.so"
|
||||
# INPUT_SOURCES_DIR ""
|
||||
# )
|
||||
endif()
|
||||
|
||||
+1
-1
Submodule KoalaBox updated: c8d3ce1a73...57cee7c22b
@@ -3,12 +3,15 @@
|
||||
# SmokeAPI
|
||||
|
||||
|
||||
_Legit DLC Unlocker for Steamworks._
|
||||
|
||||
_Legit DLC ownership emulation for Steamworks._
|
||||
|
||||
## ✨ Features
|
||||
|
||||
* `🔓` Emulate DLC ownership in legitimately owned games
|
||||
* `🛅` Emulate Inventory item ownership
|
||||
* `📄` Optional configuration
|
||||
* `🐧` Support for 32-bit and 64-bit Windows and Linux systems
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
@@ -20,7 +23,7 @@ _Legit DLC Unlocker for Steamworks._
|
||||
|
||||
### ❓ What is SmokeAPI?
|
||||
|
||||
SmokeAPI is a DLC unlocker for games that are _legitimately_ owned in your Steam account.
|
||||
SmokeAPI is a tool for Steamworks DLC ownership emulation in games that are _legitimately_ owned in Steam.
|
||||
It attempts to fool games that use Steamworks SDK (Steamworks) into thinking that you own the game's DLCs.
|
||||
However, SmokeAPI does not modify the rest of the Steamworks, hence features like multiplayer, achievements, and so on remain fully functional.
|
||||
|
||||
@@ -33,7 +36,9 @@ Therefore, **you have to first research the game's topic**, to see if it support
|
||||
|
||||
Additionally, there are several points to bear in mind when it comes to unlocking DLCs with SmokeAPI:
|
||||
|
||||
* SmokeAPI most definitely will not work with games that use 3rd party DRM, such as games from Ubisoft, Rockstar, etc.* SmokeAPI most likely will not work with games that use Denuvo SecureDLC.
|
||||
|
||||
* SmokeAPI most definitely will not work with games that use 3rd party DRM, such as games from Ubisoft, Rockstar, etc.
|
||||
* SmokeAPI most likely will not work with games that use Denuvo SecureDLC.
|
||||
* SmokeAPI is unlikely to unlock anything in Free-To-Play games since they typically store all player data on the corresponding game server and hence all the checks are server-side.
|
||||
* SmokeAPI will not work with games that employ additional ownership protection or if the game is using alternative DLC verification mechanism.
|
||||
* SmokeAPI is unlikely to work with games that use an anti-cheat, since they typically detect any DLL/EXE that has been tampered with. Sometimes it is possible to disable an anti-cheat, but that typically entails the loss of online capabilities. Search in the respective game topic for more information about how to disable anti-cheat.
|
||||
@@ -67,13 +72,13 @@ SmokeAPI supports **2** installation modes: _Hook mode_ and _Proxy mode_.
|
||||
- **Advantages**:
|
||||
- Guaranteed to load
|
||||
- **Disadvantages**:
|
||||
- Might need reinstallation aftera game update
|
||||
- Might need reinstallation after a game update
|
||||
|
||||
My advice is to try installing the unlocker in hook mode first.
|
||||
If it doesn't work, try installing it in proxy mode instead.
|
||||
If that didn't work, refer to the _Troubleshooting_ section below.
|
||||
|
||||
## 🛠 Installation instructions
|
||||
## 🛠 Installation instructions (🪟 Windows)
|
||||
|
||||
> [!NOTE]
|
||||
> To determine the bitness of a game you can open _Task Manager_, navigate to _Details_ tab,
|
||||
@@ -82,6 +87,14 @@ If that didn't work, refer to the _Troubleshooting_ section below.
|
||||
|
||||
### 🪝 Hook mode
|
||||
|
||||
Hook mode itself has two sub-modes: Self-Hook and Hook with injector.
|
||||
|
||||
#### 🪝 Self-Hook mode
|
||||
|
||||
In self-hook mode SmokeAPI is injected automatically without the help of third-party injectors.
|
||||
It works best when a game doesn't have any protections against DLL injection.
|
||||
The main advantage of this mode is its minimal setup, which adds only 1 new DLL to the game folder.
|
||||
|
||||
- Download the [latest SmokeAPI release zip].
|
||||
- From this downloaded zip extract `smoke_api32.dll` or `smoke_api64.dll`, depending on a game's bitness.
|
||||
- Rename the unzipped DLL to `version.dll` or `winhttp.dll` or `winmm.dll`.
|
||||
@@ -108,6 +121,8 @@ For example, assuming that the game loads `d3d11.dll`:
|
||||
There are games which have extra protections that break hook mode.
|
||||
In such cases, it might be worth trying [Special K], which can inject SmokeAPI as a [custom plugin].
|
||||
|
||||
---
|
||||
|
||||
### 🔀 Proxy mode
|
||||
|
||||
- Find a `steam_api.dll` or `steam_api64.dll` file in game directory, and rename it to `steam_api_o.dll` or `steam_api64_o.dll`.
|
||||
@@ -121,6 +136,105 @@ In such cases, it might be worth trying [Special K], which can inject SmokeAPI a
|
||||
[Special K]: https://www.special-k.info
|
||||
[custom plugin]: https://wiki.special-k.info/en/SpecialK/Tools#custom-plugin
|
||||
|
||||
## 🛠️ Installation instructions (🐧 Linux)
|
||||
|
||||
> [!NOTE]
|
||||
> Linux support in SmokeAPI is highly experimental/unstable and has known issues.
|
||||
> If none of the methods below work for you, then consider running a Windows version of a game
|
||||
> via Proton compatibility layer and follow the instructions in the Windows section.
|
||||
|
||||
### ✔️ Requirements
|
||||
|
||||
Linux builds of SmokeAPI depend on several libraries. Make sure they are installed on your system.
|
||||
The following list features links in Arch Linux repositories, but if you are using a different distribution,
|
||||
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/)]
|
||||
|
||||
- [glibc](https://archlinux.org/packages/core/x86_64/glibc/)
|
||||
[[32-bit](https://archlinux.org/packages/core/x86_64/lib32-glibc/)]
|
||||
|
||||
- [libidn2](https://archlinux.org/packages/core/x86_64/libidn2/)
|
||||
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-libidn2/)]
|
||||
|
||||
- [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/)]
|
||||
|
||||
- [zstd](https://archlinux.org/packages/core/x86_64/zstd/)
|
||||
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-zstd/)]
|
||||
|
||||
|
||||
Optional libraries:
|
||||
- [gtk3](https://archlinux.org/packages/extra/x86_64/gtk3/)
|
||||
[[32-bit](https://archlinux.org/packages/multilib/x86_64/lib32-gtk3/)]
|
||||
|
||||
---
|
||||
|
||||
Just like on Windows, SmokeAPI features 32 and 64-bit Linux builds.
|
||||
In release archive they are named as `libsmoke_api32.so` or `libsmoke_api64.so` respectively.
|
||||
However, unlike Windows, it is recommended to use proxy mode, rather than hook mode.
|
||||
This is because the current hook mode installation method has to directly launch game
|
||||
executable. However, by default Steam doesn't do that, instead it launches certain wrappers
|
||||
that setup game environment with optimal parameters. Hence, launching a game without those
|
||||
wrappers might cause issues in theory. However, in practice real tests show that hook mode has higher
|
||||
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:
|
||||
1. Rename the original `libsteam_api.so` to `libsteam_api_o.so`
|
||||
2. Extract and paste the `libsmoke_api32.so` or `libsmoke_api64.so` to the same directory, renaming it to `libsteam_api.so`.
|
||||
|
||||
### 🪝 Hook mode (🐧 Linux)
|
||||
|
||||
Linux doesn't have the same easily exploitable library injection mechanism that Windows has.
|
||||
However, it is possible to force any Linux executable to load any library by using the
|
||||
`LD_PRELOAD` environment variable. In fact, Steam itself already uses that to inject its overlay,
|
||||
hence we can use it as well. But we have to include that overlay library as well when specifying
|
||||
`LD_PRELOAD`, otherwise the game will be launched with SmokeAPI, but without Steam overlay.
|
||||
|
||||
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%` |
|
||||
|
||||
Where `<GameExe32>` and `<GameExe64>` correspond to the actual filename of the game executable. For example:
|
||||
- `TheEscapists2.x86` (32-bit)
|
||||
- `TheEscapists2.x86_64` (64-bit)
|
||||
- `_linux/darkest.bin.x86` (32-bit)
|
||||
- `_linux/darkest.bin.x86_64` (64-bit)
|
||||
- `bin/linux_x64/eurotrucks2` (64-bit)
|
||||
- `binaries/victoria3` (64-bit)
|
||||
|
||||
And so on. Notice that Linux executables do not have `.exe` extension like on Windows, so make sure to copy the entire
|
||||
file name as it is. Naturally, the exact options might change depending on where files are located on your filesystem
|
||||
and other environment variables you might have specified previously.
|
||||
If you have other environment variables, and you don't know how to correctly combine them,
|
||||
then please make extensive use of search engines and LLMs for guidance and examples
|
||||
before seeking help the official forum topic.
|
||||
|
||||
|
||||
## ⚙ Configuration
|
||||
|
||||
SmokeAPI does not require any manual configuration.
|
||||
@@ -172,7 +286,7 @@ Below you can find an example config where nearly every option has been customiz
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.1.5/res/SmokeAPI.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v4.0.0/res/SmokeAPI.schema.json",
|
||||
"$version": 4,
|
||||
"logging": true,
|
||||
"log_steam_http": true,
|
||||
@@ -209,11 +323,12 @@ Below you can find an example config where nearly every option has been customiz
|
||||
```
|
||||
</details>
|
||||
|
||||
|
||||
## 🎓 Extra info
|
||||
|
||||
### 🔑 How SmokeAPI works in games with large number of DLCs
|
||||
|
||||
Some games that have a large number of DLCs begin ownership verification by querying the Steamworks API for a list of all available DLCs.
|
||||
Some the games that have a large number of DLCs begin ownership verification by querying the Steamworks API for a list of all available DLCs.
|
||||
Once the game receives the list, it will go over each item and check the ownership.
|
||||
The issue arises from the fact that response from Steamworks SDK may max out at 64, depending on how much unowned DLCs the user has.
|
||||
To alleviate this issue, SmokeAPI will make a web request to Steam API for a full list of DLCs, which works well most of the time.
|
||||
@@ -255,10 +370,10 @@ If you have made sure that you picked the right DLL for Koaloader, then try addi
|
||||
|
||||
### 💥 The game is crashing
|
||||
|
||||
If the game is crashing or not opening as expected after installing an unlocker, then try to download and install the latest [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017, 2019, and 2022](https://support.microsoft.com/en-gb/help/2977003/the-latest-supported-visual-c-downloads)
|
||||
<details><summary>Download page</summary>
|
||||
If the game is crashing or not opening as expected after installing an unlocker, then try to download and install the [Latest supported Visual C++ Redistributable version](https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist?view=msvc-170#latest-supported-redistributable-version)
|
||||
<details><summary>Download page screenshot</summary>
|
||||
|
||||

|
||||

|
||||
</details>
|
||||
|
||||
## 🏗️ Building from source
|
||||
@@ -291,6 +406,7 @@ For example:
|
||||
```
|
||||
|
||||
[Visual Studio Build Tools 2022]: https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022
|
||||
|
||||
[CMake]: https://cmake.org/
|
||||
|
||||
## 📚 Acknowledgments
|
||||
@@ -308,13 +424,17 @@ This project makes use of the following open source projects:
|
||||
- [microsoft/wil](https://github.com/microsoft/wil)
|
||||
- [p-ranav/glob](https://github.com/p-ranav/glob)
|
||||
- [pantor/inja](https://github.com/pantor/inja)
|
||||
- [jarro2783/cxxopts](https://github.com/jarro2783/cxxopts)
|
||||
- [serge1/ELFIO](https://github.com/serge1/ELFIO)
|
||||
- [bshoshany/thread-pool](https://github.com/bshoshany/thread-pool)
|
||||
- [batterycenter/embed](https://github.com/batterycenter/embed)
|
||||
- [serge1/ELFIO](https://github.com/serge1/ELFIO)
|
||||
|
||||
r
|
||||
|
||||
## 📄 License
|
||||
|
||||
This software is licensed under the [Unlicense](https://unlicense.org),
|
||||
terms of which are available in [UNLICENSE.txt](UNLICENSE.txt).
|
||||
|
||||
|
||||
[Koaloader]: https://github.com/acidicoala/Koaloader
|
||||
|
||||
+8
-13
@@ -1,24 +1,24 @@
|
||||
{% extends "./KoalaBox/templates/README.base.md" %}
|
||||
{% block content %}
|
||||
|
||||
_Legit DLC Unlocker for Steamworks._
|
||||
_Legit DLC ownership emulation for Steamworks._
|
||||
|
||||
## ✨ Features
|
||||
|
||||
* `🔓` Emulate DLC ownership in legitimately owned games
|
||||
* `🛅` Emulate Inventory item ownership
|
||||
* `📄` Optional configuration
|
||||
* `🐧` Support for 32-bit and 64-bit Windows and Linux systems
|
||||
|
||||
{% include "KoalaBox/templates/markdown/links.md" %}
|
||||
|
||||
|
||||
{% include "KoalaBox/templates/markdown/intro.md" %}
|
||||
|
||||
|
||||
{% include "KoalaBox/templates/markdown/usage.md" %}
|
||||
|
||||
{% include "KoalaBox/templates/markdown/install-win.md" %}
|
||||
|
||||
{% include "KoalaBox/templates/markdown/installation.md" %}
|
||||
|
||||
{% include "KoalaBox/templates/markdown/install-linux.md" %}
|
||||
|
||||
{% include "KoalaBox/templates/markdown/configuration.md" %}
|
||||
|
||||
@@ -26,7 +26,7 @@ _Legit DLC Unlocker for Steamworks._
|
||||
|
||||
### 🔑 How SmokeAPI works in games with large number of DLCs
|
||||
|
||||
Some games that have a large number of DLCs begin ownership verification by querying the Steamworks API for a list of all available DLCs.
|
||||
Some the games that have a large number of DLCs begin ownership verification by querying the Steamworks API for a list of all available DLCs.
|
||||
Once the game receives the list, it will go over each item and check the ownership.
|
||||
The issue arises from the fact that response from Steamworks SDK may max out at 64, depending on how much unowned DLCs the user has.
|
||||
To alleviate this issue, SmokeAPI will make a web request to Steam API for a full list of DLCs, which works well most of the time.
|
||||
@@ -46,14 +46,9 @@ They will be added to the list of missing DLC IDs to facilitate config-less oper
|
||||
|
||||
{% include "KoalaBox/templates/markdown/troubleshooting.md" %}
|
||||
|
||||
|
||||
{% include "KoalaBox/templates/markdown/building.md" %}
|
||||
|
||||
|
||||
{% include "KoalaBox/templates/markdown/acknowledgements.md" %}
|
||||
{% block extra_oss_libs %}
|
||||
- [bshoshany/thread-pool](https://github.com/bshoshany/thread-pool)
|
||||
{% include "KoalaBox/templates/markdown/acknowledgements.md" %}{% block extra_oss_libs %}- [bshoshany/thread-pool](https://github.com/bshoshany/thread-pool)
|
||||
- [batterycenter/embed](https://github.com/batterycenter/embed)
|
||||
- [serge1/ELFIO](https://github.com/serge1/ELFIO)
|
||||
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.1.5/res/SmokeAPI.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v4.0.0/res/SmokeAPI.schema.json",
|
||||
"$version": 4,
|
||||
"logging": true,
|
||||
"log_steam_http": false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.1.5/res/SmokeAPI.schema.json",
|
||||
"$id": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v4.0.0/res/SmokeAPI.schema.json",
|
||||
"title": "SmokeAPI configuration",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -120,7 +120,7 @@
|
||||
},
|
||||
"examples": [
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.1.5/res/SmokeAPI.schema.json",
|
||||
"$schema": "https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v4.0.0/res/SmokeAPI.schema.json",
|
||||
"$version": 4,
|
||||
"logging": true,
|
||||
"log_steam_http": true,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
// Auto-generated header file
|
||||
#pragma once
|
||||
|
||||
namespace proxy_exports {
|
||||
void init(void* self_lib_handle, void* original_lib_handle);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,6 @@
|
||||
// Auto-generated header file
|
||||
#pragma once
|
||||
|
||||
namespace proxy_exports {
|
||||
void init(void* self_lib_handle, void* original_lib_handle);
|
||||
}
|
||||
+83
-23
@@ -1,27 +1,36 @@
|
||||
#include <regex>
|
||||
#include <set>
|
||||
|
||||
#include <glob/glob.h>
|
||||
#include <polyhook2/MemProtector.hpp>
|
||||
|
||||
#include <koalabox/config.hpp>
|
||||
#include <koalabox/lib_monitor.hpp>
|
||||
#include <koalabox/globals.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/lib.hpp>
|
||||
#include <koalabox/lib_monitor.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/path.hpp>
|
||||
#include <koalabox/paths.hpp>
|
||||
#include <koalabox/platform.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
|
||||
#include "smoke_api.hpp"
|
||||
|
||||
// static
|
||||
#include "smoke_api/config.hpp"
|
||||
#include "smoke_api/steamclient/steamclient.hpp"
|
||||
|
||||
#include "smoke_api.hpp"
|
||||
#include "steam_api/steam_interfaces.hpp"
|
||||
#include "steam_api/virtuals/steam_api_virtuals.hpp"
|
||||
|
||||
#include "build_config.h"
|
||||
|
||||
#ifdef KB_WIN
|
||||
#if defined(KB_WIN)
|
||||
#include "koalabox/win.hpp"
|
||||
#elif defined(KB_LINUX) && defined(KB_32)
|
||||
#include "generated/32/proxy_exports.hpp"
|
||||
#elif defined(KB_LINUX) && defined(KB_64)
|
||||
#include "generated/64/proxy_exports.hpp"
|
||||
#endif
|
||||
|
||||
// Hooking steam_api has shown itself to be less desirable than steamclient
|
||||
@@ -66,11 +75,13 @@ namespace {
|
||||
versions.insert(i->str());
|
||||
}
|
||||
|
||||
LOG_DEBUG("Found {} steamclient version(s) in read-only section: {}", versions.size(), versions);
|
||||
|
||||
return versions;
|
||||
}
|
||||
|
||||
void warn_if_late_injection(const std::string& steamclient_version) {
|
||||
#ifdef KB_WIN
|
||||
void warn_if_late_injection(const std::string& steamclient_version) {
|
||||
if(kb::util::is_wine_env()) {
|
||||
return;
|
||||
}
|
||||
@@ -82,8 +93,8 @@ namespace {
|
||||
"Probable cause: SmokeAPI was injected too late. If possible, try injecting it earlier."
|
||||
);
|
||||
LOG_WARN("NOTE: You can safely ignore this warning if running under Proton or native Linux");
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
// ReSharper disable once CppDFAConstantFunctionResult
|
||||
bool on_steamclient_loaded(void* steamclient_handle) {
|
||||
@@ -97,13 +108,15 @@ namespace {
|
||||
|
||||
static const auto CreateInterface$ = KB_LIB_GET_FUNC(steamclient_handle, CreateInterface);
|
||||
|
||||
if(auto* steamapi_handle = kb::lib::get_library_handle(STEAM_API_MODULE)) {
|
||||
if(auto* steamapi_handle = kb::lib::get_lib_handle(STEAM_API_MODULE)) {
|
||||
// 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);
|
||||
for(const auto& steamclient_version : steamclient_versions) {
|
||||
if(CreateInterface$(steamclient_version.c_str(), nullptr)) {
|
||||
#ifdef KB_WIN
|
||||
warn_if_late_injection(steamclient_version);
|
||||
#endif
|
||||
|
||||
steam_interfaces::hook_steamclient_interface(steamclient_handle, steamclient_version);
|
||||
} else {
|
||||
@@ -164,12 +177,57 @@ namespace {
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void init_hook_mode([[maybe_unused]] void* self_module_handle) {
|
||||
is_hook_mode = true;
|
||||
#ifdef KB_LINUX
|
||||
// Because we got injected via LD_PRELOAD,
|
||||
// Linux loader will resolve all SteamAPI exports in unlocker instead of original library.
|
||||
// Hence, we need to patch the stubs even in hook mode.
|
||||
|
||||
const std::string lib_name = STEAM_API_MODULE ".so";
|
||||
for(const auto& lib_path : glob::rglob({"./" + lib_name, "**/" + lib_name})) {
|
||||
if(const auto lib_bitness = kb::lib::get_bitness(lib_path)) {
|
||||
if(static_cast<uint8_t>(*lib_bitness) == kb::platform::bitness) {
|
||||
if(const auto lib_handle = kb::lib::load(lib_path)) {
|
||||
LOG_INFO("Found original library: {}", kb::path::to_str(lib_path));
|
||||
|
||||
original_steamapi_handle = *lib_handle;
|
||||
proxy_exports::init(self_module_handle, original_steamapi_handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!original_steamapi_handle) {
|
||||
kb::util::panic("Failed to find original " + lib_name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_proxy_mode([[maybe_unused]] void* self_module_handle) {
|
||||
is_hook_mode = true;
|
||||
|
||||
original_steamapi_handle = kb::lib::load_original_library(kb::paths::get_self_dir(), STEAM_API_MODULE);
|
||||
#ifdef KB_LINUX
|
||||
proxy_exports::init(self_module_handle, original_steamapi_handle);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
namespace smoke_api {
|
||||
void init(void* module_handle) {
|
||||
void init(void* self_module_handle) {
|
||||
try {
|
||||
kb::globals::init_globals(module_handle, PROJECT_NAME);
|
||||
static std::mutex section;
|
||||
const std::lock_guard lock(section);
|
||||
|
||||
static bool init_complete = false;
|
||||
if(init_complete) {
|
||||
LOG_ERROR("{} is already initialized", PROJECT_NAME);
|
||||
}
|
||||
|
||||
kb::globals::init_globals(self_module_handle, PROJECT_NAME);
|
||||
|
||||
config::instance = kb::config::parse<config::Config>();
|
||||
|
||||
@@ -185,8 +243,8 @@ namespace smoke_api {
|
||||
const auto exe_path = kb::lib::get_fs_path(nullptr);
|
||||
const auto exe_name = kb::path::to_str(exe_path.filename());
|
||||
|
||||
LOG_DEBUG("Process name: '{}' [{}-bit]", exe_name, kb::util::BITNESS);
|
||||
LOG_DEBUG("Self name: '{}'", kb::path::to_str(kb::lib::get_fs_path(module_handle).filename()));
|
||||
LOG_DEBUG("Process name: '{}' [{}-bit]", exe_name, kb::platform::bitness);
|
||||
LOG_DEBUG("Self name: '{}'", kb::path::to_str(kb::lib::get_fs_path(self_module_handle).filename()));
|
||||
|
||||
#ifdef KB_WIN
|
||||
kb::win::check_self_duplicates();
|
||||
@@ -195,21 +253,17 @@ namespace smoke_api {
|
||||
// We need to hook functions in either mode
|
||||
kb::hook::init(true);
|
||||
|
||||
if(kb::hook::is_hook_mode(module_handle, STEAM_API_MODULE)) {
|
||||
if(kb::hook::is_hook_mode(self_module_handle, STEAM_API_MODULE)) {
|
||||
LOG_INFO("Detected hook mode");
|
||||
|
||||
is_hook_mode = true;
|
||||
init_lib_monitor();
|
||||
init_hook_mode(self_module_handle);
|
||||
} else {
|
||||
LOG_INFO("Detected proxy mode");
|
||||
|
||||
is_hook_mode = true;
|
||||
init_lib_monitor();
|
||||
|
||||
const auto self_path = kb::paths::get_self_dir();
|
||||
original_steamapi_handle = kb::lib::load_original_library(self_path, STEAM_API_MODULE);
|
||||
init_proxy_mode(self_module_handle);
|
||||
}
|
||||
|
||||
init_lib_monitor();
|
||||
|
||||
init_complete = true;
|
||||
LOG_INFO("Initialization complete");
|
||||
} catch(const std::exception& e) {
|
||||
kb::util::panic(std::format("Initialization error: {}", e.what()));
|
||||
@@ -218,8 +272,13 @@ namespace smoke_api {
|
||||
|
||||
void shutdown() {
|
||||
try {
|
||||
static bool shutdown_complete = false;
|
||||
if(shutdown_complete) {
|
||||
LOG_ERROR("{} is already shut down", PROJECT_NAME);
|
||||
}
|
||||
|
||||
if(original_steamapi_handle != nullptr) {
|
||||
kb::lib::unload_library(original_steamapi_handle);
|
||||
kb::lib::unload(original_steamapi_handle);
|
||||
original_steamapi_handle = nullptr;
|
||||
}
|
||||
|
||||
@@ -229,6 +288,7 @@ namespace smoke_api {
|
||||
|
||||
// TODO: Unhook everything
|
||||
|
||||
shutdown_complete = true;
|
||||
LOG_INFO("Shutdown complete");
|
||||
} catch(const std::exception& e) {
|
||||
LOG_ERROR("Shutdown error: {}", e.what());
|
||||
|
||||
@@ -2,20 +2,8 @@
|
||||
|
||||
#include "smoke_api/types.hpp"
|
||||
|
||||
constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION";
|
||||
constexpr auto STEAM_CLIENT = "SteamClient";
|
||||
constexpr auto STEAM_HTTP = "STEAMHTTP_INTERFACE_VERSION";
|
||||
constexpr auto STEAM_USER = "SteamUser";
|
||||
constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V";
|
||||
constexpr auto STEAM_GAME_SERVER = "SteamGameServer";
|
||||
|
||||
// IMPORTANT: DLL_EXPORT is hardcoded in exports_generator.cpp,
|
||||
// so any name changes here must be reflected there as well.
|
||||
#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec(dllexport) TYPE __cdecl
|
||||
|
||||
namespace smoke_api {
|
||||
|
||||
void init(void* module_handle);
|
||||
void init(void* self_module_handle);
|
||||
void shutdown();
|
||||
|
||||
AppId_t get_app_id();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "smoke_api/steamclient/steamclient.hpp"
|
||||
|
||||
#include "steam_api/steam_interfaces.hpp"
|
||||
#include "smoke_api/smoke_api.hpp"
|
||||
#include "virtuals/steam_api_virtuals.hpp"
|
||||
|
||||
namespace {
|
||||
@@ -37,7 +36,7 @@ namespace {
|
||||
|
||||
return {
|
||||
{
|
||||
STEAM_APPS,
|
||||
"STEAMAPPS_INTERFACE_VERSION",
|
||||
interface_data_t{
|
||||
.fallback_version = "STEAMAPPS_INTERFACE_VERSION008",
|
||||
.entry_map = {
|
||||
@@ -49,7 +48,7 @@ namespace {
|
||||
}
|
||||
},
|
||||
{
|
||||
STEAM_CLIENT,
|
||||
steam_interfaces::STEAM_CLIENT,
|
||||
interface_data_t{
|
||||
.fallback_version = "SteamClient021",
|
||||
.entry_map = {
|
||||
@@ -61,7 +60,7 @@ namespace {
|
||||
}
|
||||
},
|
||||
{
|
||||
STEAM_GAME_SERVER,
|
||||
"SteamGameServer",
|
||||
interface_data_t{
|
||||
.fallback_version = "SteamGameServer015",
|
||||
.entry_map = {
|
||||
@@ -70,7 +69,7 @@ namespace {
|
||||
}
|
||||
},
|
||||
{
|
||||
STEAM_HTTP,
|
||||
"STEAMHTTP_INTERFACE_VERSION",
|
||||
interface_data_t{
|
||||
.fallback_version = "STEAMHTTP_INTERFACE_VERSION003",
|
||||
.entry_map = {
|
||||
@@ -81,7 +80,7 @@ namespace {
|
||||
}
|
||||
},
|
||||
{
|
||||
STEAM_INVENTORY,
|
||||
"STEAMINVENTORY_INTERFACE_V",
|
||||
interface_data_t{
|
||||
.fallback_version = "STEAMINVENTORY_INTERFACE_V003",
|
||||
.entry_map = {
|
||||
@@ -96,7 +95,7 @@ namespace {
|
||||
}
|
||||
},
|
||||
{
|
||||
STEAM_USER,
|
||||
"SteamUser",
|
||||
interface_data_t{
|
||||
.fallback_version = "SteamUser023",
|
||||
.entry_map = {
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
)
|
||||
|
||||
namespace steam_interfaces {
|
||||
constexpr auto STEAM_CLIENT = "SteamClient";
|
||||
|
||||
void hook_virtuals(const void* interface_ptr, const std::string& version_string);
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
|
||||
#include <koalabox/hook.hpp>
|
||||
|
||||
#ifdef KB_WIN
|
||||
#if defined(KB_WIN)
|
||||
#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall // NOLINT(*-macro-parentheses)
|
||||
#define C_DECL(TYPE) extern "C" __declspec(noinline) TYPE __cdecl
|
||||
#elifdef KB_LINUX
|
||||
#elif defined(KB_LINUX)
|
||||
#define VIRTUAL(TYPE) __attribute__ ((__noinline__)) TYPE
|
||||
#define C_DECL(TYPE) extern "C" __attribute__ ((__noinline__)) TYPE
|
||||
#endif
|
||||
@@ -21,6 +21,7 @@
|
||||
#define SWAPPED_CALL_CLOSURE(FUNC, ...) \
|
||||
[&] { SWAPPED_CALL(THIS, FUNC, __VA_ARGS__); }
|
||||
|
||||
#if defined(KB_WIN)
|
||||
/**
|
||||
* By default, virtual functions are declared with __thiscall
|
||||
* convention, which is normal since they are class members.
|
||||
@@ -53,6 +54,26 @@
|
||||
#define THIS ECX
|
||||
#define DECLARE_ARGS() void* ECX = nullptr; const void* EDX = nullptr;
|
||||
#endif
|
||||
#elif defined(KB_LINUX)
|
||||
/**
|
||||
* In 64-bit mode, Linux binaries pass first 6 arguments via registers.
|
||||
* `this` pointer is passed as the first argument via the RDI register.
|
||||
*
|
||||
* In 32-bit mode, Linux binaries pass arguments via stack.
|
||||
* `this` pointer is passed as the first argument via the first stack parameter.
|
||||
*/
|
||||
#ifdef KB_64
|
||||
#define PARAMS(...) const void* $RDI __VA_OPT__(,) __VA_ARGS__
|
||||
#define ARGS(...) $RDI __VA_OPT__(,) __VA_ARGS__
|
||||
#define THIS $RDI
|
||||
#define DECLARE_ARGS() void* $RDI = nullptr;
|
||||
#else
|
||||
#define PARAMS(...) const void* $STACK1 __VA_OPT__(,) __VA_ARGS__
|
||||
#define ARGS(...) $STACK1 __VA_OPT__(,) __VA_ARGS__
|
||||
#define THIS $STACK1
|
||||
#define DECLARE_ARGS() void* $STACK1 = nullptr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using AppId_t = uint32_t;
|
||||
using HSteamPipe = uint32_t;
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
"store_name": "Steam",
|
||||
"store_sdk": "Steamworks",
|
||||
"store_sdk_full": "Steamworks SDK",
|
||||
"sdk_dll_names": "`steam_api.dll` or `steam_api64.dll`",
|
||||
"sdk_dll_orig_names": "`steam_api_o.dll` or `steam_api64_o.dll`",
|
||||
"sdk_libs_win": "`steam_api.dll` or `steam_api64.dll`",
|
||||
"sdk_libs_linux": "`libsteam_api.so`",
|
||||
"sdk_libs_orig_win": "`steam_api_o.dll` or `steam_api64_o.dll`",
|
||||
"sdk_libs_orig_linux": "`libsteam_api_o.so`",
|
||||
"show_3rd_party_point": true,
|
||||
"unlocker_dll_names": "`smoke_api32.dll` or `smoke_api64.dll`",
|
||||
"unlocker_libs_win": "`smoke_api32.dll` or `smoke_api64.dll`",
|
||||
"unlocker_libs_linux": "`libsmoke_api32.so` or `libsmoke_api64.so`",
|
||||
"config_filename": "SmokeAPI.config.json",
|
||||
"github_repo_url": "https://github.com/acidicoala/SmokeAPI",
|
||||
"forum_topic_url": "https://cs.rin.ru/forum/viewtopic.php?p=2597932#p2597932",
|
||||
|
||||
+3
-23
@@ -1,33 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.24)
|
||||
|
||||
project(smoke-api-tools LANGUAGES CXX)
|
||||
|
||||
### Thread pool library
|
||||
|
||||
## https://github.com/bshoshany/thread-pool
|
||||
CPMAddPackage(
|
||||
NAME BS_thread_pool
|
||||
GITHUB_REPOSITORY bshoshany/thread-pool
|
||||
VERSION 5.0.0
|
||||
EXCLUDE_FROM_ALL
|
||||
SYSTEM
|
||||
)
|
||||
add_library(BS_thread_pool INTERFACE)
|
||||
target_include_directories(BS_thread_pool INTERFACE ${BS_thread_pool_SOURCE_DIR}/include)
|
||||
project(SmokeAPITools LANGUAGES CXX)
|
||||
|
||||
### Steamworks Downloader executable
|
||||
|
||||
CPMAddPackage("gh:serge1/ELFIO#Release_3.12")
|
||||
add_executable(steamworks_downloader src/steamworks_downloader.cpp)
|
||||
target_link_libraries(steamworks_downloader PRIVATE
|
||||
KoalaBox
|
||||
elfio
|
||||
)
|
||||
target_link_libraries(steamworks_downloader PRIVATE KoalaBoxTools)
|
||||
|
||||
### Steamworks Parser executable
|
||||
|
||||
add_executable(steamworks_parser src/steamworks_parser.cpp)
|
||||
target_link_libraries(steamworks_parser PRIVATE
|
||||
KoalaBox
|
||||
BS_thread_pool
|
||||
)
|
||||
target_link_libraries(steamworks_parser PRIVATE KoalaBoxTools)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/path.hpp>
|
||||
#include <koalabox/str.hpp>
|
||||
#include <koalabox/zip.hpp>
|
||||
#include <koalabox_tools/zip.hpp>
|
||||
|
||||
namespace {
|
||||
namespace fs = std::filesystem;
|
||||
@@ -90,7 +90,7 @@ namespace {
|
||||
}
|
||||
|
||||
void unzip_sdk(const fs::path& zip_file_path, const fs::path& unzip_dir) {
|
||||
kb::zip::extract_files(
|
||||
kb::tools::zip::extract_files(
|
||||
zip_file_path,
|
||||
[&](const std::string& name, const bool) {
|
||||
if(name.starts_with("sdk/public/steam/") && name.ends_with(".h")) {
|
||||
|
||||
@@ -8,13 +8,15 @@
|
||||
|
||||
#include <koalabox/io.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/parser.hpp>
|
||||
#include <koalabox/path.hpp>
|
||||
#include <koalabox/str.hpp>
|
||||
|
||||
#include <koalabox_tools/parser.hpp>
|
||||
|
||||
namespace {
|
||||
namespace fs = std::filesystem;
|
||||
namespace kb = koalabox;
|
||||
namespace parser = kb::tools::parser;
|
||||
|
||||
std::string_view unquote_if_quoted(const std::string_view& s) {
|
||||
if(s.size() >= 2 && s.front() == '"' && s.back() == '"') {
|
||||
@@ -26,13 +28,13 @@ namespace {
|
||||
}
|
||||
|
||||
void parse_header(const std::string_view& source, nlohmann::ordered_json& lookup) {
|
||||
const auto tree = kb::parser::parse_source(source);
|
||||
const auto tree = parser::parse_source(source);
|
||||
const auto root = tree.getRootNode();
|
||||
|
||||
nlohmann::ordered_json current_lookup = {};
|
||||
std::string interface_version;
|
||||
|
||||
kb::parser::walk(
|
||||
parser::walk(
|
||||
root,
|
||||
[&](const ts::Node& current_node) {
|
||||
const auto current_type = current_node.getType();
|
||||
@@ -43,7 +45,7 @@ namespace {
|
||||
std::string interface_name;
|
||||
[[maybe_unused]] int vt_idx = 0;
|
||||
|
||||
kb::parser::walk(
|
||||
parser::walk(
|
||||
current_node,
|
||||
[&](const ts::Node& class_node) {
|
||||
const auto type = class_node.getType();
|
||||
@@ -53,12 +55,12 @@ namespace {
|
||||
interface_name = value;
|
||||
LOG_DEBUG("Found interface: {}", interface_name);
|
||||
|
||||
return kb::parser::visit_result::Continue;
|
||||
return parser::visit_result::Continue;
|
||||
}
|
||||
|
||||
if(type == "field_declaration" && value.starts_with("virtual ")) {
|
||||
if(value.starts_with("virtual ")) {
|
||||
kb::parser::walk(
|
||||
parser::walk(
|
||||
class_node,
|
||||
[&](const ts::Node& decl_node) {
|
||||
if(decl_node.getType() == "field_identifier") {
|
||||
@@ -71,29 +73,29 @@ namespace {
|
||||
// functions. Hence, no fixes have been implemented so far.
|
||||
|
||||
current_lookup[function_name] = vt_idx++;
|
||||
return kb::parser::visit_result::Stop;
|
||||
return parser::visit_result::Stop;
|
||||
}
|
||||
return kb::parser::visit_result::Continue;
|
||||
return parser::visit_result::Continue;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return kb::parser::visit_result::SkipChildren;
|
||||
return parser::visit_result::SkipChildren;
|
||||
}
|
||||
|
||||
return kb::parser::visit_result::Continue;
|
||||
return parser::visit_result::Continue;
|
||||
}
|
||||
);
|
||||
} else if(current_type == "preproc_def") {
|
||||
kb::parser::walk(
|
||||
parser::walk(
|
||||
current_node,
|
||||
[&](const ts::Node& preproc_node) {
|
||||
if(preproc_node.getType() == "identifier") {
|
||||
const auto identifier = preproc_node.getSourceRange(source);
|
||||
|
||||
return identifier.ends_with("INTERFACE_VERSION")
|
||||
? kb::parser::visit_result::Continue
|
||||
: kb::parser::visit_result::Stop;
|
||||
? parser::visit_result::Continue
|
||||
: parser::visit_result::Stop;
|
||||
}
|
||||
|
||||
if(preproc_node.getType() == "preproc_arg") {
|
||||
@@ -102,17 +104,17 @@ namespace {
|
||||
interface_version = unquote_if_quoted(trimmed_version);
|
||||
LOG_DEBUG("Interface version: {}", interface_version);
|
||||
|
||||
return kb::parser::visit_result::Stop;
|
||||
return parser::visit_result::Stop;
|
||||
}
|
||||
|
||||
return kb::parser::visit_result::Continue;
|
||||
return parser::visit_result::Continue;
|
||||
}
|
||||
);
|
||||
} else if(current_type == "translation_unit" || current_type == "preproc_ifdef") {
|
||||
return kb::parser::visit_result::Continue;
|
||||
return parser::visit_result::Continue;
|
||||
}
|
||||
|
||||
return kb::parser::visit_result::SkipChildren;
|
||||
return parser::visit_result::SkipChildren;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -155,7 +157,6 @@ namespace {
|
||||
for(const auto& entry : fs::directory_iterator(headers_dir)) {
|
||||
if(const auto& header_path = entry.path(); header_path.extension() == ".h") {
|
||||
const auto task = pool.submit_task(
|
||||
// NOLINT(*-unused-local-non-trivial-variable)
|
||||
[&, header_path] {
|
||||
try {
|
||||
LOG_DEBUG("Parsing header: {}", kb::path::to_str(header_path));
|
||||
@@ -164,7 +165,7 @@ namespace {
|
||||
parse_header(processed_header, lookup);
|
||||
} catch(std::exception& e) {
|
||||
LOG_CRITICAL(e.what());
|
||||
exit(-1);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user