mirror of https://github.com/acidicoala/SmokeAPI
Renamed koalageddon mode to store mode
parent
dfbce391a7
commit
4f93515bac
@ -1 +1 @@
|
||||
Subproject commit c1e97c8101fe0369985aad85298b1b6b3e3c9ca6
|
||||
Subproject commit 44b0553105af8a7352def9e879f59e1da26bcba6
|
@ -1,12 +0,0 @@
|
||||
Copyright (c) 2022 by acidicoala
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
@ -0,0 +1,275 @@
|
||||
= 🐨 SmokeAPI ♨
|
||||
|
||||
_Legit DLC Unlocker for Steamworks_
|
||||
|
||||
image::https://www.gstatic.com/android/keyboard/emojikitchen/20201001/u1f428/u1f428_u2615.png[,256,align="center"]
|
||||
|
||||
== ✨ Features
|
||||
|
||||
* 🔓 Legit DLC Unlocking
|
||||
* 🛅 Inventory emulation
|
||||
* 📝 Config-less operation
|
||||
* Multiple installation methods:
|
||||
** 🛍️ Store mode
|
||||
** 🎮 Game mode
|
||||
*** 🪝 Hook mode
|
||||
*** 🔀 Proxy mode
|
||||
|
||||
== 🔗 Links
|
||||
|
||||
:forum-topic: https://cs.rin.ru/forum/viewtopic.php?p=2597932#p2597932[SmokeAPI forum topic]
|
||||
|
||||
* 📥 https://github.com/acidicoala/SmokeAPI/releases/latest[Download the latest release]
|
||||
|
||||
* 💬 {forum-topic}
|
||||
|
||||
== 📖 Introduction
|
||||
|
||||
=== What is SmokeAPI?
|
||||
|
||||
SmokeAPI is a DLC unlocker for the games that are legitimately owned in your Steam account.
|
||||
It attempts to spoof games that use Steamworks SDK into believing that you own desired DLCs.
|
||||
However, SmokeAPI does not modify the rest of the Steamworks SDK, hence features like multiplayer, achievements, etc. remain fully functional.
|
||||
|
||||
.Supported versions
|
||||
[%collapsible]
|
||||
====
|
||||
SmokeAPI aims to support all released SteamAPI versions.
|
||||
When it encountered a new, unsupported interface version, it will fall back on the latest supported version.
|
||||
Below is a list of supported interface versions:
|
||||
|
||||
* ISteamClient v6 — v20. (Versions before 6 did not contain any DLC related interfaces)
|
||||
* ISteamApps v2 — v8. (Version 1 did not contain any DLC related functions)
|
||||
* ISteamUser v12 — v21. (Versions before 12 did not contain any DLC related functions)
|
||||
* ISteamInventory v1 — v3.
|
||||
|
||||
Steam inventory does not work in all games with steam inventory because of custom implementation, and online checks.
|
||||
A list of games where inventory emulation has been shown to work is as follows:
|
||||
|
||||
* Project Winter
|
||||
* Euro Truck Simulator 2
|
||||
* Hero Siege (if you bypass EAC)
|
||||
====
|
||||
|
||||
== 🛠 Installation Instructions
|
||||
|
||||
WARNING: Please proceed with installation at your own risk.
|
||||
Usage of this unlocker entails breaking one or more terms of service, which might result in a permanent loss of your account.
|
||||
|
||||
:smokeapi_release: https://github.com/acidicoala/SmokeAPI/releases/latest[SmokeAPI Releases]
|
||||
|
||||
SmokeAPI supports 2 main modes of installation: *Store* mode and *Game* mode, which are described in the next section.
|
||||
|
||||
NOTE: It is worth noting that the following instructions describe a _manual_ installation method.
|
||||
You can benefit from _automatic_ installation and GUI configuration from Koalageddon v2 (Coming soon).
|
||||
|
||||
=== 🛍️ Store mode
|
||||
|
||||
In this installation mode, SmokeAPI is loaded into the Steam process, which makes it able to affect all Steam games.
|
||||
|
||||
:steam-dir: the Steam directoryfootnote:fn-steam-dir[The root directory where Steam is installed]
|
||||
|
||||
. Download the latest Koaloader release zip from https://github.com/acidicoala/Koaloader/releases/latest[Koaloader Releases].
|
||||
. From Koaloader archive unpack `version.dll` from `version-32`, and place it in {steam-dir}.
|
||||
. In {steam-dir} create the following Koaloader configuration file:
|
||||
+
|
||||
.`Koaloader.json`
|
||||
[%collapsible]
|
||||
====
|
||||
[source,json]
|
||||
----
|
||||
{
|
||||
"auto_load": false,
|
||||
"targets": [
|
||||
"Steam.exe"
|
||||
],
|
||||
"modules": [
|
||||
{
|
||||
"path": "SmokeAPI.dll",
|
||||
"required": true
|
||||
}
|
||||
]
|
||||
}
|
||||
----
|
||||
====
|
||||
. Download the latest SmokeAPI release zip from {smokeapi_release}.
|
||||
. From SmokeAPI archive unpack `steam_api.dll`, rename it to `SmokeAPI.dll`, and place it in {steam-dir}.
|
||||
|
||||
=== 🎮 Game mode
|
||||
|
||||
In this installation mode, SmokeAPI is loaded into a game process, which makes limits it to that particular game only.
|
||||
This mode itself supports 2 modes: hook mode and proxy mode.
|
||||
Try installing the unlocker in hook mode first.
|
||||
If it doesn't work, try installing it in proxy mode.
|
||||
|
||||
==== 🪝 Hook mode
|
||||
|
||||
. Download the latest Koaloader release zip from https://github.com/acidicoala/Koaloader/releases/latest[Koaloader Releases].
|
||||
. From Koaloader archive unpack `version.dll` from version-32/64, depending on the game bitness, and place it next to the game exe file.
|
||||
. Download the latest SmokeAPI release zip from {smokeapi_release}.
|
||||
. From SmokeAPI archive unpack `steam_api.dll`/`steam_api64.dll`, depending on the game bitness, rename it to `SmokeAPI.dll`, and place it next to the game exe file.
|
||||
|
||||
==== 🔀 Proxy mode
|
||||
|
||||
. Find `steam_api.dll`/`steam_api64.dll` file in game directory, and add `_o` to its name, e.g. `steam_api64_o.dll`.
|
||||
. Download the latest SmokeAPI release zip from {smokeapi_release}.
|
||||
. From SmokeAPI archive unpack `steam_api.dll`/`steam_api64.dll`, depending on the game bitness, and place it next to the original steam_api DLL file.
|
||||
|
||||
If the unlocker is not working as expected, then please fully read the https://gist.github.com/acidicoala/2c131cb90e251f97c0c1dbeaf2c174dc[Generic Unlocker Installation Instructions] before seeking support in the {forum-topic}.
|
||||
|
||||
== ⚙ Configuration
|
||||
|
||||
NOTE: This document describes configuration for version 2 of SmokeAPI.
|
||||
You can find the version 1 documentation https://github.com/acidicoala/SmokeAPI/blob/v1.0.3/README.md#-configuration[here].
|
||||
|
||||
:steam_config: https://github.com/acidicoala/public-entitlements/blob/main/steam/v2/store_config.json
|
||||
:fn-app-id: footnote:fn-app-id[App/DLC IDs can be obtained from https://steamdb.info. Keep in mind that you need to be signed in with a steam account in order to see accurate inventory item IDs on that website.]
|
||||
|
||||
SmokeAPI does not require any manual configuration.
|
||||
By default, it uses the most reasonable options and tries to unlock all DLCs that it can.
|
||||
However, there might be circumstances in which you need more custom-tailored behaviour, such as disabling certain DLCs, or selectively enabling just a few of them.
|
||||
In this case you can use a configuration file link:res/SmokeAPI.config.json[SmokeAPI.config.json] that you can find here in this repository or in the release zip.
|
||||
To use it, simply place it next to the SmokeAPI DLL.
|
||||
It will be read upon each launch of a game or the store.
|
||||
In the absence of the config file, default values specified below will be used.
|
||||
The configuration file is expected to conform to the Json standard.
|
||||
|
||||
`logging`:: Toggles generation of a `SmokeAPI.log.log` file.
|
||||
+
|
||||
[horizontal]
|
||||
Type::: Boolean
|
||||
Default::: `false`
|
||||
|
||||
`unlock_family_sharing`:: Toggles Family Sharing bypass, which enables the borrower of a shared library to start and continue playing games when library owner is playing as well.
|
||||
+
|
||||
[horizontal]
|
||||
Type::: Boolean
|
||||
Default::: `true`
|
||||
|
||||
`default_app_status`:: This option sets the default DLC unlocking behaviour.
|
||||
+
|
||||
[horizontal]
|
||||
Possible values:::
|
||||
+
|
||||
[horizontal]
|
||||
`original`:::: Leaves DLC unlock status unmodified, unless specified otherwise.
|
||||
`unlocked`:::: Unlocks all DLCs in all games, unless specified otherwise.
|
||||
Type::: String
|
||||
Default::: `unlocked`
|
||||
|
||||
`override_app_status`:: This option overrides the status of all DLCs that belong to a specified app ID{fn-app-id}.
|
||||
+
|
||||
[horizontal]
|
||||
Possible values::: An object with key-value pairs, where the key corresponds to the app ID, and value to the app status.
|
||||
Possible app status values are defined in the `default_app_status` option.
|
||||
Type::: Object
|
||||
Default::: `{}`
|
||||
|
||||
`override_dlc_status`:: This option overrides the status of individual DLCs, regardless of the corresponding app status.
|
||||
+
|
||||
[horizontal]
|
||||
Possible values::: An object with key-value pairs, where the key corresponds to the app ID, and value to the app status.
|
||||
Possible app status values are defined in the `default_app_status` option.
|
||||
Furthermore, it is possible to lock even the legitimately locked DLCs by setting the corresponding app status value to `locked`.
|
||||
Type::: Object (Map of String to String)
|
||||
Default::: `{}`
|
||||
|
||||
`auto_inject_inventory`:: Toggles whether SmokeAPI should automatically inject a list of all registered inventory items, when a game queries user inventory
|
||||
+
|
||||
[horizontal]
|
||||
Type::: Boolean
|
||||
Default::: `true`
|
||||
|
||||
`extra_inventory_items`:: A list of inventory items IDs{fn-app-id} that will be added in addition to the automatically injected items.
|
||||
+
|
||||
[horizontal]
|
||||
Type::: Array (of Integers)
|
||||
Default::: `[]`
|
||||
|
||||
=== Advanced options
|
||||
|
||||
`$version`:: A technical field reserved for use by tools like GUI config editors.
|
||||
Do not modify this value.
|
||||
+
|
||||
[horizontal]
|
||||
Type::: Integer
|
||||
Default::: `2`
|
||||
|
||||
`extra_dlcs`:: See <<How SmokeAPI works in games with large number of DLCs>> to understand the use case for this option.
|
||||
+
|
||||
[horizontal]
|
||||
Possible values::: An object with key-value pairs, where the key corresponds to the app ID, and value to the object that contains DLC IDs.
|
||||
The format is the same as in the aforementioned GitHub config.
|
||||
Type::: Object (Map of String to Object)
|
||||
Default::: `{}`
|
||||
|
||||
`store_config`:: An object that specifies offsets required for store mode operation.
|
||||
It will override the config fetched from {steam_config}[remote source] or local cache.
|
||||
Do not modify this value.
|
||||
+
|
||||
[horizontal]
|
||||
Type::: Object (Map of String to Integer)
|
||||
Default::: See {steam_config}[online config]
|
||||
|
||||
== 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.
|
||||
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.
|
||||
Unfortunately, even the web API does not solve all of our problems, because it will only return DLCs that are available in Steam store.
|
||||
This means that DLCs without a dedicated store offer, such as pre-order DLCs will be left out.
|
||||
That's where the `extra_dlcs` config option comes into play.
|
||||
You can specify those missing DLC IDs there, and SmokeAPI will make them available to the game.
|
||||
However, this introduces the need for manual configuration, which goes against the ideals of this project.
|
||||
To remedy this issue SmokeAPI will also fetch a https://github.com/acidicoala/public-entitlements/blob/main/steam/v2/dlc.json[manually maintained list of extra DLCs] stored in a GitHub repository.
|
||||
The purpose of this document is to contain all the DLC IDs that are lacking a Steam store page.
|
||||
This enables SmokeAPI to unlock all DLCs without any config file at all.
|
||||
Feel free to report in the {forum-topic} games that have more than 64 DLCs,
|
||||
_and_ have DLCs without a dedicated store page.
|
||||
They will be added to the list of missing DLC IDs to facilitate config-less operation.
|
||||
|
||||
== 🏗️ Building from source
|
||||
|
||||
=== ✅ Requirements
|
||||
|
||||
:fn-lower-ver: footnote:lower-versions[Older versions may be supported as well.]
|
||||
|
||||
* CMake v3.24 (Make sure that cmake is available from powershell)
|
||||
* Visual Studio 2022{fn-lower-ver}.
|
||||
* Tested on Windows 11 SDK (10.0.22621.0){fn-lower-ver}.
|
||||
|
||||
=== 👨💻 Commands
|
||||
|
||||
Build the project
|
||||
|
||||
----
|
||||
.\build.ps1 <arch> <config>
|
||||
----
|
||||
|
||||
where
|
||||
|
||||
[horizontal]
|
||||
arch::: `32` or `64`
|
||||
config::: `Debug` or `Release`
|
||||
|
||||
For example:
|
||||
|
||||
----
|
||||
.\build.ps1 32 Debug
|
||||
----
|
||||
|
||||
== 👋 Acknowledgements
|
||||
|
||||
SmokeAPI makes use of the following open source projects:
|
||||
|
||||
- https://github.com/libcpr/cpr[C++ Requests]
|
||||
- https://github.com/nlohmann/json[JSON for Modern C++]
|
||||
- https://github.com/stevemk14ebr/PolyHook_2_0[PolyHook 2]
|
||||
- https://github.com/gabime/spdlog[spdlog]
|
||||
|
||||
== 📄 License
|
||||
|
||||
This software is licensed under the https://unlicense.org/[Unlicense], terms of which are available in link:UNLICENSE.txt[UNLICENSE.txt]
|
@ -0,0 +1,24 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <https://unlicense.org>
|
@ -1,4 +1,4 @@
|
||||
#include <smoke_api/app_cache.hpp>
|
||||
#include <common/app_cache.hpp>
|
||||
#include <core/paths.hpp>
|
||||
#include <koalabox/cache.hpp>
|
||||
#include <koalabox/logger.hpp>
|
@ -1,3 +1,4 @@
|
||||
#include <common/steamclient_exports.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
|
||||
DLL_EXPORT(void*) CreateInterface(const char* interface_string, int* out_result) {
|
@ -0,0 +1,3 @@
|
||||
#include <core/types.hpp>
|
||||
|
||||
DLL_EXPORT(void*) CreateInterface(const char* interface_string, int* out_result);
|
@ -1,4 +1,3 @@
|
||||
#include <steam_api_exports/steam_api_exports.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
|
||||
DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser hSteamUser, const char* version) {
|
@ -1,4 +1,3 @@
|
||||
#include <steam_api_exports/steam_api_exports.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
@ -1,4 +1,4 @@
|
||||
#include <steam_api_virtuals/steam_api_virtuals.hpp>
|
||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
|
||||
VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t appID)) {
|
@ -1,4 +1,4 @@
|
||||
#include <steam_api_virtuals/steam_api_virtuals.hpp>
|
||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
|
||||
VIRTUAL(void*) ISteamClient_GetISteamApps(
|
@ -1,4 +1,4 @@
|
||||
#include <steam_api_virtuals/steam_api_virtuals.hpp>
|
||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
|
||||
VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) {
|
@ -1,10 +1,18 @@
|
||||
#include <steam_api_virtuals/steam_api_virtuals.hpp>
|
||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||
#include <steam_impl/steam_user.hpp>
|
||||
#include <steam_impl/steam_impl.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t dlcID)) {
|
||||
AppId_t app_id = 0;
|
||||
try {
|
||||
app_id = steam_impl::get_app_id_or_throw();
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("{} -> Error getting app id: {}", __func__, e.what())
|
||||
}
|
||||
|
||||
return steam_user::UserHasLicenseForApp(
|
||||
__func__, steam_impl::get_app_id_or_throw(), dlcID, [&]() {
|
||||
__func__, app_id, dlcID, [&]() {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(ISteamUser_UserHasLicenseForApp)
|
||||
|
||||
return ISteamUser_UserHasLicenseForApp_o(ARGS(steamID, dlcID));
|
@ -1,33 +0,0 @@
|
||||
#include <koalageddon/kg_cache.hpp>
|
||||
#include <koalabox/cache.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
constexpr auto KEY_KG_CONFIG = "koalageddon_config";
|
||||
|
||||
namespace koalageddon::kg_cache {
|
||||
|
||||
std::optional<KoalageddonConfig> get_koalageddon_config() {
|
||||
try {
|
||||
const auto config_json = koalabox::cache::read_from_cache(KEY_KG_CONFIG);
|
||||
|
||||
return config_json.get<KoalageddonConfig>();
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("Failed to get cached koalageddon config: {}", e.what())
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
bool save_koalageddon_config(const KoalageddonConfig& config) {
|
||||
try {
|
||||
LOG_DEBUG("Caching koalageddon config")
|
||||
|
||||
return koalabox::cache::save_to_cache(KEY_KG_CONFIG, Json(config));
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("Failed to cache koalageddon config: {}", e.what())
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
|
||||
namespace koalageddon::kg_cache {
|
||||
|
||||
std::optional<KoalageddonConfig> get_koalageddon_config();
|
||||
|
||||
bool save_koalageddon_config(const KoalageddonConfig& config);
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
|
||||
namespace koalageddon::vstdlib {
|
||||
|
||||
struct CallbackData {
|
||||
uintptr_t get_callback_intercept_address() {
|
||||
return reinterpret_cast<uintptr_t*>(this)[koalageddon::config.vstdlib_callback_interceptor_address_offset];
|
||||
}
|
||||
|
||||
uintptr_t get_callback_address() {
|
||||
return reinterpret_cast<uintptr_t*>(this)[koalageddon::config.vstdlib_callback_address_offset];
|
||||
}
|
||||
};
|
||||
|
||||
struct CoroutineData {
|
||||
CallbackData* get_callback_data() {
|
||||
return reinterpret_cast<CallbackData**>(this)[koalageddon::config.vstdlib_callback_data_offset];
|
||||
}
|
||||
|
||||
const char* get_callback_name() {
|
||||
return reinterpret_cast<const char**>(this)[koalageddon::config.vstdlib_callback_name_offset];
|
||||
}
|
||||
};
|
||||
|
||||
typedef uint32_t HCoroutine;
|
||||
DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, CoroutineData* data);
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/types.hpp>
|
||||
|
||||
// Flat
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(void*, AppId_t);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(void*, AppId_t);
|
||||
DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(void*);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(void*, int, AppId_t*, bool*, char*, int);
|
||||
|
||||
DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(void*, HSteamUser, HSteamPipe, const char*);
|
||||
|
||||
DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(void*, SteamInventoryResult_t);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(void*, SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty(
|
||||
void*, SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*
|
||||
);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(void*, SteamInventoryResult_t, CSteamID);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(void*, SteamInventoryResult_t*);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
|
||||
void*, SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t
|
||||
);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(void*, SteamInventoryResult_t, void*, uint32_t*);
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(void*, SteamItemDef_t*, uint32_t*);
|
||||
|
||||
DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(void*, CSteamID, AppId_t);
|
||||
|
||||
// Internal
|
||||
DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser, const char*);
|
||||
DLL_EXPORT(void*) SteamInternal_CreateInterface(const char*);
|
||||
|
||||
// Unversioned
|
||||
DLL_EXPORT(void*) CreateInterface(const char*, int*);
|
||||
DLL_EXPORT(void*) SteamApps();
|
||||
DLL_EXPORT(void*) SteamClient();
|
||||
DLL_EXPORT(void*) SteamUser();
|
@ -1,3 +1,4 @@
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
|
||||
VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t app_id, AppId_t dlc_id)) {
|
@ -1,4 +1,4 @@
|
||||
#include <koalageddon/steamclient/steamclient.hpp>
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
|
||||
VIRTUAL(EResult) IClientInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) {
|
@ -1,8 +1,8 @@
|
||||
#include <koalageddon/steamclient/steamclient.hpp>
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
|
||||
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t dlc_id)) {
|
||||
const auto* utils_interface = koalageddon::steamclient::interface_name_to_address_map["IClientUtils"];
|
||||
const auto* utils_interface = store::steamclient::interface_name_to_address_map["IClientUtils"];
|
||||
|
||||
const auto app_id = utils_interface ? IClientUtils_GetAppID(utils_interface, EDX) : 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <koalageddon/steamclient/steamclient.hpp>
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
|
||||
VIRTUAL(AppId_t) IClientUtils_GetAppID(PARAMS()) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(IClientUtils_GetAppID)
|
@ -0,0 +1,19 @@
|
||||
#include <store_mode/store_api.hpp>
|
||||
#include <koalabox/http_client.hpp>
|
||||
|
||||
namespace store::api {
|
||||
|
||||
std::optional<StoreConfig> fetch_store_config() noexcept {
|
||||
try {
|
||||
const String url =
|
||||
"https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/store_config.json";
|
||||
const auto kg_config_json = koalabox::http_client::fetch_json(url);
|
||||
|
||||
return kg_config_json.get<StoreConfig>();
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("Failed to fetch Store config from GitHub: {}", e.what())
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/types.hpp>
|
||||
#include <store_mode/store.hpp>
|
||||
|
||||
namespace store::api {
|
||||
|
||||
std::optional<store::StoreConfig> fetch_store_config() noexcept;
|
||||
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
#include <store_mode/store_cache.hpp>
|
||||
#include <koalabox/cache.hpp>
|
||||
|
||||
constexpr auto KEY_KG_CONFIG = "store_config";
|
||||
|
||||
namespace store::store_cache {
|
||||
|
||||
std::optional<StoreConfig> get_store_config() {
|
||||
try {
|
||||
const auto config_json = koalabox::cache::read_from_cache(KEY_KG_CONFIG);
|
||||
|
||||
return config_json.get<StoreConfig>();
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("Failed to get cached store_mode config: {}", e.what())
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
bool save_store_config(const StoreConfig& config) {
|
||||
try {
|
||||
LOG_DEBUG("Caching store_mode config")
|
||||
|
||||
return koalabox::cache::save_to_cache(KEY_KG_CONFIG, Json(config));
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("Failed to cache store_mode config: {}", e.what())
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <store_mode/store.hpp>
|
||||
|
||||
namespace store::store_cache {
|
||||
|
||||
std::optional<StoreConfig> get_store_config();
|
||||
|
||||
bool save_store_config(const StoreConfig& config);
|
||||
|
||||
}
|
@ -1,47 +1,32 @@
|
||||
#include <koalageddon/vstdlib.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <store_mode/vstdlib/vstdlib.hpp>
|
||||
|
||||
using namespace koalageddon;
|
||||
|
||||
namespace koalageddon::vstdlib {
|
||||
using namespace koalabox;
|
||||
|
||||
VIRTUAL(bool) SharedLicensesLockStatus(PARAMS(void* arg)
|
||||
) {
|
||||
namespace store::vstdlib {
|
||||
VIRTUAL(bool) SharedLicensesLockStatus(PARAMS(void* arg)) {
|
||||
LOG_DEBUG("{}(this={}, arg={})", __func__, THIS, arg)
|
||||
ARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
VIRTUAL(bool) SharedLibraryStopPlaying(PARAMS(void* arg)
|
||||
) {
|
||||
VIRTUAL(bool) SharedLibraryStopPlaying(PARAMS(void* arg)) {
|
||||
LOG_DEBUG("{}(this={}, arg={})", __func__, THIS, arg)
|
||||
ARGS();
|
||||
return true;
|
||||
}
|
||||
|
||||
VIRTUAL(void) VStdLib_Callback_Interceptor(PARAMS(const char** name_ptr)
|
||||
) {
|
||||
VIRTUAL(void) VStdLib_Callback_Interceptor(PARAMS(const char** name_ptr)) {
|
||||
GET_ORIGINAL_HOOKED_FUNCTION(VStdLib_Callback_Interceptor)
|
||||
VStdLib_Callback_Interceptor_o(ARGS(name_ptr));
|
||||
|
||||
static auto lock_status_hooked = false;
|
||||
static auto stop_playing_hooked = false;
|
||||
|
||||
if (
|
||||
lock_status_hooked && stop_playing_hooked
|
||||
) {
|
||||
if (lock_status_hooked && stop_playing_hooked) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto* const data = (CoroutineData*) THIS;
|
||||
|
||||
if (
|
||||
data && data
|
||||
->
|
||||
get_callback_name()
|
||||
) {
|
||||
if (data && data->get_callback_name()) {
|
||||
const auto name = String(data->get_callback_name());
|
||||
LOG_TRACE("{}(ecx={}, edx={}, name='{}')", __func__, ARGS(), name)
|
||||
if (name == "SharedLicensesLockStatus" && !lock_status_hooked) {
|
@ -0,0 +1,27 @@
|
||||
#include <store_mode/store.hpp>
|
||||
|
||||
namespace store::vstdlib {
|
||||
|
||||
struct CallbackData {
|
||||
uintptr_t get_callback_intercept_address() {
|
||||
return reinterpret_cast<uintptr_t*>(this)[store::config.vstdlib_callback_interceptor_address_offset];
|
||||
}
|
||||
|
||||
uintptr_t get_callback_address() {
|
||||
return reinterpret_cast<uintptr_t*>(this)[store::config.vstdlib_callback_address_offset];
|
||||
}
|
||||
};
|
||||
|
||||
struct CoroutineData {
|
||||
CallbackData* get_callback_data() {
|
||||
return reinterpret_cast<CallbackData**>(this)[store::config.vstdlib_callback_data_offset];
|
||||
}
|
||||
|
||||
const char* get_callback_name() {
|
||||
return reinterpret_cast<const char**>(this)[store::config.vstdlib_callback_name_offset];
|
||||
}
|
||||
};
|
||||
|
||||
typedef uint32_t HCoroutine;
|
||||
DLL_EXPORT(HCoroutine) Coroutine_Create(void* callback_address, CoroutineData* data);
|
||||
}
|
Loading…
Reference in New Issue