mirror of
https://github.com/acidicoala/SmokeAPI.git
synced 2026-01-25 05:52:51 -05:00
Renamed koalageddon mode to store mode
This commit is contained in:
@@ -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) {
|
||||
3
src/common/steamclient_exports.hpp
Normal file
3
src/common/steamclient_exports.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#include <core/types.hpp>
|
||||
|
||||
DLL_EXPORT(void*) CreateInterface(const char* interface_string, int* out_result);
|
||||
@@ -27,7 +27,7 @@ namespace api {
|
||||
|
||||
std::optional<Vector<DLC>> fetch_dlcs_from_steam(AppId_t app_id) noexcept {
|
||||
try {
|
||||
const auto url = fmt::format("https://store.steampowered.com/dlc/{}/ajaxgetdlclist", app_id);
|
||||
const auto url = fmt::format("https://store_mode.steampowered.com/dlc/{}/ajaxgetdlclist", app_id);
|
||||
const auto json = koalabox::http_client::fetch_json(url);
|
||||
|
||||
const auto response = json.get<SteamResponse>();
|
||||
@@ -43,17 +43,4 @@ namespace api {
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<koalageddon::KoalageddonConfig> fetch_koalageddon_config() noexcept {
|
||||
try {
|
||||
const String url =
|
||||
"https://raw.githubusercontent.com/acidicoala/public-entitlements/main/koalageddon/v2/steam.json";
|
||||
const auto kg_config_json = koalabox::http_client::fetch_json(url);
|
||||
|
||||
return kg_config_json.get<koalageddon::KoalageddonConfig>();
|
||||
} catch (const Exception& e) {
|
||||
LOG_ERROR("Failed to fetch Koalageddon config from GitHub: {}", e.what())
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <core/types.hpp>
|
||||
|
||||
namespace api {
|
||||
|
||||
@@ -8,6 +8,4 @@ namespace api {
|
||||
|
||||
std::optional<Vector<DLC>> fetch_dlcs_from_steam(AppId_t app_id) noexcept;
|
||||
|
||||
std::optional<koalageddon::KoalageddonConfig> fetch_koalageddon_config() noexcept;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <koalabox/core.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <core/globals.hpp>
|
||||
#include <koalabox/core.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
/**
|
||||
* By default, virtual functions are declared with __thiscall
|
||||
@@ -23,7 +24,7 @@
|
||||
*
|
||||
* In x86-64 however, there is only one calling convention,
|
||||
* so __fastcall is simply ignored. However, RDX in this case
|
||||
* will store the 1st actual argument to the function, so we
|
||||
* will store_mode the 1st actual argument to the function, so we
|
||||
* have to omit it from the function signature.
|
||||
*
|
||||
* The macros below implement the above-mentioned considerations.
|
||||
@@ -60,9 +61,9 @@
|
||||
#define DETOUR_VSTDLIB(FUNC) $DETOUR(vstdlib::FUNC, #FUNC, globals::vstdlib_module)
|
||||
|
||||
#ifdef _WIN64
|
||||
#define COMPILE_KOALAGEDDON 0
|
||||
#define COMPILE_STORE_MODE 0
|
||||
#else
|
||||
#define COMPILE_KOALAGEDDON 1
|
||||
#define COMPILE_STORE_MODE 1
|
||||
#endif
|
||||
|
||||
constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION";
|
||||
@@ -134,5 +135,6 @@ public:
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(DLC, appid, name)
|
||||
|
||||
static Vector<DLC> get_dlcs_from_apps(const AppDlcNameMap& apps, AppId_t app_id);
|
||||
|
||||
static DlcNameMap get_dlc_map_from_vector(const Vector<DLC>& vector);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include <steam_api_exports/steam_api_exports.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
#include <steam_impl/steam_client.hpp>
|
||||
#include <steam_impl/steam_inventory.hpp>
|
||||
#include <steam_impl/steam_user.hpp>
|
||||
#include <steam_impl/steam_impl.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
|
||||
// ISteamApps
|
||||
|
||||
@@ -92,6 +92,20 @@ DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(
|
||||
void* self,
|
||||
SteamItemDef_t* pItemDefIDs,
|
||||
uint32_t* punItemDefIDsArraySize
|
||||
) {
|
||||
return steam_inventory::GetItemDefinitionIDs(
|
||||
__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemDefinitionIDs)
|
||||
|
||||
return SteamAPI_ISteamInventory_GetItemDefinitionIDs_o(self, pItemDefIDs, punItemDefIDsArraySize);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(
|
||||
void* self,
|
||||
SteamInventoryResult_t resultHandle,
|
||||
@@ -189,20 +203,6 @@ DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(
|
||||
);
|
||||
}
|
||||
|
||||
DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(
|
||||
void* self,
|
||||
SteamItemDef_t* pItemDefIDs,
|
||||
uint32_t* punItemDefIDsArraySize
|
||||
) {
|
||||
return steam_inventory::GetItemDefinitionIDs(
|
||||
__func__, pItemDefIDs, punItemDefIDsArraySize, [&]() {
|
||||
GET_ORIGINAL_FUNCTION_STEAMAPI(SteamAPI_ISteamInventory_GetItemDefinitionIDs)
|
||||
|
||||
return SteamAPI_ISteamInventory_GetItemDefinitionIDs_o(self, pItemDefIDs, punItemDefIDsArraySize);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// ISteamUser
|
||||
|
||||
DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(
|
||||
@@ -210,8 +210,15 @@ DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp
|
||||
CSteamID steamID,
|
||||
AppId_t dlcID
|
||||
) {
|
||||
AppId_t app_id;
|
||||
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_FUNCTION_STEAMAPI(SteamAPI_ISteamUser_UserHasLicenseForApp)
|
||||
|
||||
return SteamAPI_ISteamUser_UserHasLicenseForApp_o(self, steamID, dlcID);
|
||||
@@ -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);
|
||||
}
|
||||
@@ -7,7 +7,7 @@
|
||||
namespace smoke_api::config {
|
||||
Config instance; // NOLINT(cert-err58-cpp)
|
||||
|
||||
void init() {
|
||||
void init_config() {
|
||||
const auto path = paths::get_config_path();
|
||||
|
||||
if (exists(path)) {
|
||||
@@ -66,6 +66,6 @@ namespace smoke_api::config {
|
||||
DLL_EXPORT(void) ReloadConfig() {
|
||||
LOG_INFO("Reloading config")
|
||||
|
||||
init();
|
||||
init_config();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/types.hpp>
|
||||
#include <koalabox/core.hpp>
|
||||
|
||||
namespace smoke_api::config {
|
||||
|
||||
@@ -30,7 +29,7 @@ namespace smoke_api::config {
|
||||
bool auto_inject_inventory = true;
|
||||
Vector<uint32_t> extra_inventory_items;
|
||||
// We have to use general json type here since the library doesn't support std::optional
|
||||
Json koalageddon_config;
|
||||
Json store_config;
|
||||
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(
|
||||
Config, // NOLINT(misc-const-correctness)
|
||||
@@ -43,13 +42,13 @@ namespace smoke_api::config {
|
||||
extra_dlcs,
|
||||
auto_inject_inventory,
|
||||
extra_inventory_items,
|
||||
koalageddon_config
|
||||
store_config
|
||||
)
|
||||
};
|
||||
|
||||
extern Config instance;
|
||||
|
||||
void init();
|
||||
void init_config();
|
||||
|
||||
Vector<DLC> get_extra_dlcs(AppId_t app_id);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <smoke_api/config.hpp>
|
||||
#include <core/globals.hpp>
|
||||
#include <core/paths.hpp>
|
||||
#include <common/steamclient_exports.hpp>
|
||||
#include <koalabox/dll_monitor.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
@@ -10,12 +11,30 @@
|
||||
#include <koalabox/loader.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <steam_api_exports/steam_api_exports.hpp>
|
||||
//#include <steam_api_exports/steam_api_exports.hpp>
|
||||
|
||||
#if COMPILE_KOALAGEDDON
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#if COMPILE_STORE_MODE
|
||||
#include <store_mode/store.hpp>
|
||||
#endif
|
||||
|
||||
// Hooking steam_api has shown itself to be less desirable than steamclient
|
||||
// for the reasons outlined below:
|
||||
//
|
||||
// Calling original in flat functions will actually call the hooked functions
|
||||
// because the original function redirects the execution to a function taken
|
||||
// from self pointer, which would have been hooked by SteamInternal_*Interface
|
||||
// functions.
|
||||
//
|
||||
// Furthermore, turns out that many flat functions share the same body,
|
||||
// which looks like the following snippet:
|
||||
//
|
||||
// mov rax, qword ptr ds:[rcx]
|
||||
// jmp qword ptr ds:[rax+immediate]
|
||||
//
|
||||
// This means that we end up inadvertently hooking unintended functions.
|
||||
// Given that hooking steam_api has no apparent benefits, but has inherent flaws,
|
||||
// the support for it has been dropped from this project.
|
||||
|
||||
void init_proxy_mode() {
|
||||
LOG_INFO("🔀 Detected proxy mode")
|
||||
|
||||
@@ -34,24 +53,6 @@ void init_hook_mode() {
|
||||
koalabox::dll_monitor::shutdown_listener();
|
||||
}
|
||||
);
|
||||
|
||||
// Hooking steam_api has shown itself to be less desirable than steamclient
|
||||
// for the reasons outlined below:
|
||||
//
|
||||
// Calling original in flat functions will actually call the hooked functions
|
||||
// because the original function redirects the execution to a function taken
|
||||
// from self pointer, which would have been hooked by SteamInternal_*Interface
|
||||
// functions.
|
||||
//
|
||||
// Furthermore, turns out that many flat functions share the same body,
|
||||
// which looks like the following snippet:
|
||||
//
|
||||
// mov rax, qword ptr ds:[rcx]
|
||||
// jmp qword ptr ds:[rax+immediate]
|
||||
//
|
||||
// This means that we end up inadvertently hooking unintended functions.
|
||||
// Given that hooking steam_api has no apparent benefits, but has inherent flaws,
|
||||
// the support for it has been dropped from this project.
|
||||
}
|
||||
|
||||
bool is_valve_steam(const String& exe_name) noexcept {
|
||||
@@ -82,7 +83,7 @@ namespace smoke_api {
|
||||
|
||||
globals::smokeapi_handle = module_handle;
|
||||
|
||||
config::init();
|
||||
config::init_config();
|
||||
|
||||
if (config::instance.logging) {
|
||||
koalabox::logger::init_file_logger(paths::get_log_path());
|
||||
@@ -103,9 +104,9 @@ namespace smoke_api {
|
||||
koalabox::hook::init(true);
|
||||
|
||||
if (is_valve_steam(exe_name)) {
|
||||
#if COMPILE_KOALAGEDDON
|
||||
LOG_INFO("🐨💥 Detected Koalageddon mode")
|
||||
koalageddon::init();
|
||||
#if COMPILE_STORE_MODE
|
||||
LOG_INFO("🛍️ Detected Store mode")
|
||||
store::init_store_mode();
|
||||
#endif
|
||||
} else {
|
||||
init_hook_mode();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace smoke_api {
|
||||
|
||||
void init(HMODULE module_handle);
|
||||
|
||||
void shutdown();
|
||||
|
||||
}
|
||||
|
||||
@@ -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,6 +1,6 @@
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
#include <steam_impl/steam_impl.hpp>
|
||||
#include <smoke_api/app_cache.hpp>
|
||||
#include <common/app_cache.hpp>
|
||||
#include <smoke_api/config.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
#include <steam_impl/steam_impl.hpp>
|
||||
#include <steam_api_virtuals/steam_api_virtuals.hpp>
|
||||
#include <steam_api_exports/steam_api_exports.hpp>
|
||||
#include <game_mode/virtuals/steam_api_virtuals.hpp>
|
||||
#include <common/steamclient_exports.hpp>
|
||||
#include <core/globals.hpp>
|
||||
#include <build_config.h>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
#include <polyhook2/Misc.hpp>
|
||||
|
||||
#if COMPILE_KOALAGEDDON
|
||||
#include <koalageddon/steamclient/steamclient.hpp>
|
||||
#if COMPILE_STORE_MODE
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
#endif
|
||||
|
||||
namespace steam_impl {
|
||||
@@ -201,8 +200,8 @@ namespace steam_impl {
|
||||
HOOK_STEAM_INVENTORY(ISteamInventory_GetResultItemProperty)
|
||||
}
|
||||
} else if (version_string.starts_with(CLIENT_ENGINE)) {
|
||||
#if COMPILE_KOALAGEDDON
|
||||
koalageddon::steamclient::process_client_engine(reinterpret_cast<uintptr_t>(interface));
|
||||
#if COMPILE_STORE_MODE
|
||||
store::steamclient::process_client_engine(reinterpret_cast<uintptr_t>(interface));
|
||||
#endif
|
||||
} else {
|
||||
return;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/types.hpp>
|
||||
#include <koalabox/core.hpp>
|
||||
|
||||
namespace steam_inventory {
|
||||
|
||||
|
||||
@@ -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,5 +1,5 @@
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
#include <steam_impl/steam_apps.hpp>
|
||||
#include <koalageddon/steamclient/steamclient.hpp>
|
||||
|
||||
VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) {
|
||||
return steam_apps::GetDLCCount(
|
||||
@@ -31,7 +31,7 @@ VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(
|
||||
);
|
||||
},
|
||||
[&](AppId_t dlc_id) {
|
||||
const auto* app_manager_interface = koalageddon::steamclient::interface_name_to_address_map["IClientAppManager"];
|
||||
const auto* app_manager_interface = store::steamclient::interface_name_to_address_map["IClientAppManager"];
|
||||
if (app_manager_interface) {
|
||||
IClientAppManager_IsAppDlcInstalled(app_manager_interface, EDX, appID, dlc_id);
|
||||
return true;
|
||||
@@ -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)
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <koalageddon/steamclient/steamclient.hpp>
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <store_mode/steamclient/steamclient.hpp>
|
||||
#include <store_mode/store.hpp>
|
||||
#include <koalabox/hook.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/util.hpp>
|
||||
@@ -7,7 +7,7 @@
|
||||
#include <Zydis/Zydis.h>
|
||||
#include <Zydis/DecoderTypes.h>
|
||||
|
||||
namespace koalageddon::steamclient {
|
||||
namespace store::steamclient {
|
||||
using namespace koalabox;
|
||||
|
||||
Map<String, void*> interface_name_to_address_map; // NOLINT(cert-err58-cpp)
|
||||
@@ -431,10 +431,10 @@ namespace koalageddon::steamclient {
|
||||
|
||||
void process_client_engine(uintptr_t interface) {
|
||||
const auto* steam_client_internal = ((uintptr_t***) interface)[
|
||||
koalageddon::config.client_engine_steam_client_internal_ordinal
|
||||
store::config.client_engine_steam_client_internal_ordinal
|
||||
];
|
||||
const auto interface_selector_address = (*steam_client_internal)[
|
||||
koalageddon::config.steam_client_internal_interface_selector_ordinal
|
||||
store::config.steam_client_internal_interface_selector_ordinal
|
||||
];
|
||||
|
||||
LOG_DEBUG("Found interface selector at: {}", (void*) interface_selector_address)
|
||||
@@ -29,7 +29,7 @@ VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t));
|
||||
// IClientUtils
|
||||
VIRTUAL(AppId_t) IClientUtils_GetAppID(PARAMS());
|
||||
|
||||
namespace koalageddon::steamclient {
|
||||
namespace store::steamclient {
|
||||
|
||||
/// We need this interface in other IClient* functions in order to call other functions
|
||||
extern Map<String, void*> interface_name_to_address_map;
|
||||
@@ -1,29 +1,28 @@
|
||||
#include <koalageddon/koalageddon.hpp>
|
||||
#include <koalageddon/vstdlib.hpp>
|
||||
#include <koalageddon/kg_cache.hpp>
|
||||
#include <build_config.h>
|
||||
#include <store_mode/store.hpp>
|
||||
#include <store_mode/vstdlib/vstdlib.hpp>
|
||||
#include <store_mode/store_cache.hpp>
|
||||
#include <store_mode/store_api.hpp>
|
||||
#include <smoke_api/config.hpp>
|
||||
#include <steam_api_exports/steam_api_exports.hpp>
|
||||
#include <core/api.hpp>
|
||||
#include <build_config.h>
|
||||
#include <koalabox/dll_monitor.hpp>
|
||||
#include <koalabox/logger.hpp>
|
||||
#include <koalabox/win_util.hpp>
|
||||
#include <koalabox/ipc.hpp>
|
||||
#include <common/steamclient_exports.hpp>
|
||||
|
||||
namespace koalageddon {
|
||||
namespace store {
|
||||
|
||||
KoalageddonConfig config; // NOLINT(cert-err58-cpp)
|
||||
StoreConfig config; // NOLINT(cert-err58-cpp)
|
||||
|
||||
/**
|
||||
* @return A string representing the source of the config.
|
||||
*/
|
||||
void init_koalageddon_config() {
|
||||
void init_store_config() {
|
||||
const auto print_source = [](const String& source) {
|
||||
LOG_INFO("Loaded Koalageddon config from the {}", source)
|
||||
LOG_INFO("Loaded Store config from the {}", source)
|
||||
};
|
||||
|
||||
// First try to read a local config override
|
||||
const auto& kg_config = smoke_api::config::instance.koalageddon_config;
|
||||
const auto& kg_config = smoke_api::config::instance.store_config;
|
||||
if (!kg_config.is_null()) {
|
||||
try {
|
||||
config = kg_config.get<decltype(config)>();
|
||||
@@ -31,17 +30,17 @@ namespace koalageddon {
|
||||
print_source("local config override");
|
||||
return;
|
||||
} catch (const Exception& ex) {
|
||||
LOG_ERROR("Failed to get local koalageddon config: {}", ex.what())
|
||||
LOG_ERROR("Failed to get local store_mode config: {}", ex.what())
|
||||
}
|
||||
}
|
||||
|
||||
// Then try to get a cached copy of a previously fetched config.
|
||||
try {
|
||||
config = kg_cache::get_koalageddon_config().value();
|
||||
config = store_cache::get_store_config().value();
|
||||
|
||||
print_source("disk cache");
|
||||
} catch (const Exception& ex) {
|
||||
LOG_ERROR("Failed to get cached koalageddon config: {}", ex.what())
|
||||
LOG_ERROR("Failed to get cached store_mode config: {}", ex.what())
|
||||
|
||||
print_source("default config bundled in the binary");
|
||||
|
||||
@@ -53,40 +52,40 @@ namespace koalageddon {
|
||||
// if a new config has been fetched
|
||||
NEW_THREAD({
|
||||
try {
|
||||
const auto github_config_opt = api::fetch_koalageddon_config();
|
||||
const auto github_config_opt = api::fetch_store_config();
|
||||
if (!github_config_opt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto github_config = *github_config_opt;
|
||||
|
||||
kg_cache::save_koalageddon_config(github_config);
|
||||
store_cache::save_store_config(github_config);
|
||||
|
||||
if (github_config == config) {
|
||||
LOG_DEBUG("Fetched Koalageddon config is equal to existing config")
|
||||
LOG_DEBUG("Fetched Store config is equal to existing config")
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_DEBUG("Fetched a new Koalageddon config")
|
||||
LOG_DEBUG("Fetched a new Store config")
|
||||
|
||||
::MessageBox(
|
||||
nullptr,
|
||||
TEXT(
|
||||
"SmokeAPI has downloaded an updated config for Koalageddon mode. "
|
||||
"Please restart Steam in order to apply the new Koalageddon config. "
|
||||
"SmokeAPI has downloaded an updated config for Store mode. "
|
||||
"Please restart Steam in order to apply the new Store config. "
|
||||
),
|
||||
TEXT("SmokeAPI - Koalageddon"),
|
||||
TEXT("SmokeAPI - Store"),
|
||||
MB_SETFOREGROUND | MB_ICONINFORMATION | MB_OK
|
||||
);
|
||||
} catch (const Exception& ex) {
|
||||
LOG_ERROR("Failed to get remote koalageddon config: {}", ex.what())
|
||||
LOG_ERROR("Failed to get remote store_mode config: {}", ex.what())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
void init() {
|
||||
init_koalageddon_config();
|
||||
void init_store_mode() {
|
||||
init_store_config();
|
||||
|
||||
koalabox::dll_monitor::init_listener(
|
||||
{VSTDLIB_DLL, STEAMCLIENT_DLL}, [](const HMODULE& module_handle, const String& name) {
|
||||
@@ -120,7 +119,7 @@ namespace koalageddon {
|
||||
);
|
||||
|
||||
NEW_THREAD({
|
||||
koalabox::ipc::init_pipe_server("smoke_api.koalageddon", [](const koalabox::ipc::Request& request) {
|
||||
koalabox::ipc::init_pipe_server("smoke_api.store_mode", [](const koalabox::ipc::Request& request) {
|
||||
koalabox::ipc::Response response;
|
||||
|
||||
if (request.name < equals > "config::reload") {
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
#include <core/types.hpp>
|
||||
|
||||
namespace koalageddon {
|
||||
namespace store {
|
||||
// Offset values are interpreted according to pointer arithmetic rules, i.e.
|
||||
// 1 unit offset represents 4 and 8 bytes in 32-bit and 64-bit architectures respectively.
|
||||
class KoalageddonConfig {
|
||||
class StoreConfig {
|
||||
public:
|
||||
uint32_t client_engine_steam_client_internal_ordinal = 12;
|
||||
uint32_t steam_client_internal_interface_selector_ordinal = 18;
|
||||
@@ -15,9 +15,9 @@ namespace koalageddon {
|
||||
uint32_t vstdlib_callback_name_offset = 4;
|
||||
|
||||
// We do not use *_WITH_DEFAULT macro to ensure that overriding
|
||||
// the koalageddon config requires definition of all keys
|
||||
// the store_mode config requires definition of all keys
|
||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(
|
||||
KoalageddonConfig, // NOLINT(misc-const-correctness)
|
||||
StoreConfig, // NOLINT(misc-const-correctness)
|
||||
client_engine_steam_client_internal_ordinal,
|
||||
steam_client_internal_interface_selector_ordinal,
|
||||
vstdlib_callback_address_offset,
|
||||
@@ -26,11 +26,11 @@ namespace koalageddon {
|
||||
vstdlib_callback_name_offset
|
||||
)
|
||||
|
||||
bool operator==(const KoalageddonConfig& other) const = default;
|
||||
bool operator==(const StoreConfig& other) const = default;
|
||||
};
|
||||
|
||||
extern KoalageddonConfig config;
|
||||
extern StoreConfig config;
|
||||
|
||||
void init();
|
||||
void init_store_mode();
|
||||
|
||||
}
|
||||
19
src/store_mode/store_api.cpp
Normal file
19
src/store_mode/store_api.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
10
src/store_mode/store_api.hpp
Normal file
10
src/store_mode/store_api.hpp
Normal file
@@ -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;
|
||||
|
||||
}
|
||||
32
src/store_mode/store_cache.cpp
Normal file
32
src/store_mode/store_cache.cpp
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
11
src/store_mode/store_cache.hpp
Normal file
11
src/store_mode/store_cache.hpp
Normal file
@@ -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) {
|
||||
27
src/store_mode/vstdlib/vstdlib.hpp
Normal file
27
src/store_mode/vstdlib/vstdlib.hpp
Normal file
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user