diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 31071dd..1a62352 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -35,6 +35,8 @@
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ebfd3b8..5975e23 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -35,19 +35,21 @@ configure_build_config(extra_build_config)
set(
SMOKE_API_SOURCES
- src/core/config.cpp
- src/core/config.hpp
+ src/core/api.cpp
+ src/core/api.hpp
src/core/globals.cpp
src/core/globals.hpp
- src/core/macros.hpp
src/core/paths.cpp
src/core/paths.hpp
src/core/types.cpp
src/core/types.hpp
- src/smoke_api/smoke_api.cpp
- src/smoke_api/smoke_api.hpp
src/smoke_api/app_cache.cpp
src/smoke_api/app_cache.hpp
+ src/smoke_api/config.cpp
+ src/smoke_api/config.hpp
+ src/smoke_api/smoke_api.cpp
+ src/smoke_api/smoke_api.hpp
+ src/steam_api_exports/steam_api_exports.hpp
src/steam_api_exports/steam_api_flat.cpp
src/steam_api_exports/steam_api_internal.cpp
src/steam_api_exports/steam_api_unversioned.cpp
@@ -55,6 +57,7 @@ set(
src/steam_api_virtuals/isteamclient.cpp
src/steam_api_virtuals/isteaminventory.cpp
src/steam_api_virtuals/isteamuser.cpp
+ src/steam_api_virtuals/steam_api_virtuals.hpp
src/steam_impl/steam_apps.cpp
src/steam_impl/steam_apps.hpp
src/steam_impl/steam_client.cpp
@@ -63,8 +66,8 @@ set(
src/steam_impl/steam_inventory.hpp
src/steam_impl/steam_user.cpp
src/steam_impl/steam_user.hpp
- src/steam_functions/steam_functions.cpp
- src/steam_functions/steam_functions.hpp
+ src/steam_impl/steam_impl.cpp
+ src/steam_impl/steam_impl.hpp
src/steamclient_exports/steamclient.cpp
src/main.cpp
${GENERATED_LINKER_EXPORTS}
@@ -74,20 +77,18 @@ set(
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
set(
SMOKE_API_SOURCES ${SMOKE_API_SOURCES}
- src/koalageddon/cache.hpp
- src/koalageddon/cache.cpp
+ src/koalageddon/kg_cache.hpp
+ src/koalageddon/kg_cache.cpp
src/koalageddon/koalageddon.hpp
src/koalageddon/koalageddon.cpp
- src/koalageddon/steamclient.cpp
- src/koalageddon/steamclient.hpp
- src/koalageddon/types.hpp
src/koalageddon/vstdlib.cpp
src/koalageddon/vstdlib.hpp
- # TODO: Move to koalageddon package
- src/steamclient_virtuals/client_app_manager.cpp
- src/steamclient_virtuals/client_apps.cpp
- src/steamclient_virtuals/client_inventory.cpp
- src/steamclient_virtuals/client_user.cpp
+ src/koalageddon/steamclient/client_app_manager.cpp
+ src/koalageddon/steamclient/client_apps.cpp
+ src/koalageddon/steamclient/client_inventory.cpp
+ src/koalageddon/steamclient/client_user.cpp
+ src/koalageddon/steamclient/steamclient.cpp
+ src/koalageddon/steamclient/steamclient.hpp
)
endif ()
diff --git a/KoalaBox b/KoalaBox
index 960ad86..2e68320 160000
--- a/KoalaBox
+++ b/KoalaBox
@@ -1 +1 @@
-Subproject commit 960ad86f2c9327165c103be812af1e94930bd555
+Subproject commit 2e6832007f2f2ba7c09141597ee97680febd77a2
diff --git a/res/SmokeAPI.json b/res/SmokeAPI.json
index 68e75ac..deb8151 100644
--- a/res/SmokeAPI.json
+++ b/res/SmokeAPI.json
@@ -14,16 +14,14 @@
"16384": "original"
},
"extra_dlcs": {
- "extra_dlcs": {
- "1234": {
- "dlcs": {
- "56789": "Example DLC 1"
- }
- },
- "4321": {
- "dlcs": {
- "98765": "Example DLC 2"
- }
+ "1234": {
+ "dlcs": {
+ "56789": "Example DLC 1"
+ }
+ },
+ "4321": {
+ "dlcs": {
+ "98765": "Example DLC 2"
}
}
},
diff --git a/src/core/api.cpp b/src/core/api.cpp
new file mode 100644
index 0000000..11bfc9e
--- /dev/null
+++ b/src/core/api.cpp
@@ -0,0 +1,48 @@
+#include
+#include
+#include
+
+namespace api {
+
+ struct SteamResponse {
+ uint32_t success = 0;
+ Vector dlcs;
+
+ NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(SteamResponse, success, dlcs) // NOLINT(misc-const-correctness)
+ };
+
+ std::optional> fetch_dlcs_from_github(AppId_t app_id) noexcept {
+ try {
+ const auto* url =
+ "https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/dlc.json";
+ const auto json = koalabox::http_client::fetch_json(url);
+ const auto response = json.get();
+
+ return DLC::get_dlcs_from_apps(response, app_id);
+ } catch (const Json::exception& e) {
+ LOG_ERROR("Failed to fetch dlc list from GitHub: {}", e.what())
+ return std::nullopt;
+ }
+ }
+
+ std::optional> 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 json = koalabox::http_client::fetch_json(url);
+
+ LOG_TRACE("Steam response: \n{}", json.dump(2))
+
+ const auto response = json.get();
+
+ if (response.success != 1) {
+ throw std::runtime_error("Web API responded with 'success' != 1");
+ }
+
+ return response.dlcs;
+ } catch (const Exception& e) {
+ LOG_ERROR("Failed to fetch dlc list from Steam: {}", e.what())
+ return std::nullopt;
+ }
+ }
+
+}
diff --git a/src/core/api.hpp b/src/core/api.hpp
new file mode 100644
index 0000000..ca7d229
--- /dev/null
+++ b/src/core/api.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include
+
+namespace api {
+
+ std::optional> fetch_dlcs_from_github(AppId_t app_id) noexcept;
+
+ std::optional> fetch_dlcs_from_steam(AppId_t app_id) noexcept;
+
+}
diff --git a/src/core/macros.hpp b/src/core/macros.hpp
deleted file mode 100644
index 835622e..0000000
--- a/src/core/macros.hpp
+++ /dev/null
@@ -1,58 +0,0 @@
-#pragma once
-
-#include
-#include
-
-/**
- * By default, virtual functions are declared with __thiscall
- * convention, which is normal since they are class members.
- * But it presents an issue for us, since we cannot pass *this
- * pointer as a function argument. This is because *this
- * pointer is passed via register ECX in __thiscall
- * convention. Hence, to resolve this issue we declare our
- * hooked functions with __fastcall convention, to trick
- * the compiler into reading ECX & EDX registers as 1st
- * and 2nd function arguments respectively. Similarly, __fastcall
- * makes the compiler push the first argument into the ECX register,
- * which mimics the __thiscall calling convention. Register EDX
- * is not used anywhere in this case, but we still pass it along
- * to conform to the __fastcall convention. This all applies
- * to the x86 architecture.
- *
- * 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
- * have to omit it from the function signature.
- *
- * The macros below implement the above-mentioned considerations.
- */
-#ifdef _WIN64
-#define PARAMS(...) void* RCX, __VA_ARGS__
-#define ARGS(...) RCX, __VA_ARGS__
-#define THIS RCX
-#else
-#define PARAMS(...) const void* ECX, const void* EDX, __VA_ARGS__
-#define ARGS(...) ECX, EDX, __VA_ARGS__
-#define THIS ECX
-#endif
-
-// Names beginning with $ designate macros that are not meant to be used directly by the sources consuming this file
-
-#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec( dllexport ) TYPE __cdecl
-#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall
-
-#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \
- static const auto FUNC##_o = koalabox::hook::get_original_hooked_function(globals::address_map, #FUNC, FUNC);
-
-#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \
- static const auto FUNC##_o = koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC);
-
-
-#define DETOUR_ADDRESS(FUNC, ADDRESS) \
- koalabox::hook::detour_or_warn(globals::address_map, ADDRESS, #FUNC, reinterpret_cast(FUNC));
-
-#define $DETOUR(FUNC, NAME, MODULE_HANDLE) \
- koalabox::hook::detour_or_warn(globals::address_map, MODULE_HANDLE, NAME, reinterpret_cast(FUNC));
-
-#define DETOUR_STEAMCLIENT(FUNC) $DETOUR(FUNC, #FUNC, globals::steamclient_module)
-#define DETOUR_VSTDLIB(FUNC) $DETOUR(vstdlib::FUNC, #FUNC, globals::vstdlib_module)
diff --git a/src/core/types.hpp b/src/core/types.hpp
index 05e303c..b2c4a8e 100644
--- a/src/core/types.hpp
+++ b/src/core/types.hpp
@@ -1,7 +1,63 @@
#pragma once
#include
+#include
#include
+#include
+
+/**
+ * By default, virtual functions are declared with __thiscall
+ * convention, which is normal since they are class members.
+ * But it presents an issue for us, since we cannot pass *this
+ * pointer as a function argument. This is because *this
+ * pointer is passed via register ECX in __thiscall
+ * convention. Hence, to resolve this issue we declare our
+ * hooked functions with __fastcall convention, to trick
+ * the compiler into reading ECX & EDX registers as 1st
+ * and 2nd function arguments respectively. Similarly, __fastcall
+ * makes the compiler push the first argument into the ECX register,
+ * which mimics the __thiscall calling convention. Register EDX
+ * is not used anywhere in this case, but we still pass it along
+ * to conform to the __fastcall convention. This all applies
+ * to the x86 architecture.
+ *
+ * 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
+ * have to omit it from the function signature.
+ *
+ * The macros below implement the above-mentioned considerations.
+ */
+#ifdef _WIN64
+#define PARAMS(...) void* RCX, __VA_ARGS__
+#define ARGS(...) RCX, __VA_ARGS__
+#define THIS RCX
+#else
+#define PARAMS(...) const void* ECX, const void* EDX, __VA_ARGS__
+#define ARGS(...) ECX, EDX, __VA_ARGS__
+#define THIS ECX
+#endif
+
+// Names beginning with $ designate macros that are not meant to be used directly by the sources consuming this file
+
+#define DLL_EXPORT(TYPE) extern "C" [[maybe_unused]] __declspec( dllexport ) TYPE __cdecl
+#define VIRTUAL(TYPE) __declspec(noinline) TYPE __fastcall
+
+#define GET_ORIGINAL_HOOKED_FUNCTION(FUNC) \
+ static const auto FUNC##_o = koalabox::hook::get_original_hooked_function(globals::address_map, #FUNC, FUNC);
+
+#define GET_ORIGINAL_FUNCTION_STEAMAPI(FUNC) \
+ static const auto FUNC##_o = koalabox::hook::get_original_function(globals::steamapi_module, #FUNC, FUNC);
+
+
+#define DETOUR_ADDRESS(FUNC, ADDRESS) \
+ koalabox::hook::detour_or_warn(globals::address_map, ADDRESS, #FUNC, reinterpret_cast(FUNC));
+
+#define $DETOUR(FUNC, NAME, MODULE_HANDLE) \
+ koalabox::hook::detour_or_warn(globals::address_map, MODULE_HANDLE, NAME, reinterpret_cast(FUNC));
+
+#define DETOUR_STEAMCLIENT(FUNC) $DETOUR(FUNC, #FUNC, globals::steamclient_module)
+#define DETOUR_VSTDLIB(FUNC) $DETOUR(vstdlib::FUNC, #FUNC, globals::vstdlib_module)
#ifdef _WIN64
#define COMPILE_KOALAGEDDON 0
@@ -9,6 +65,12 @@
#define COMPILE_KOALAGEDDON 1
#endif
+constexpr auto STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION";
+constexpr auto STEAM_CLIENT = "SteamClient";
+constexpr auto STEAM_USER = "SteamUser";
+constexpr auto STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V";
+constexpr auto CLIENT_ENGINE = "CLIENTENGINE_INTERFACE_VERSION";
+
using AppId_t = uint32_t;
using SteamInventoryResult_t = uint32_t;
using SteamItemInstanceID_t = uint64_t;
@@ -33,11 +95,8 @@ enum EUserHasLicenseForAppResult {
};
class ISteamClient;
-
class ISteamApps;
-
class ISteamUser;
-
class ISteamInventory;
// These aliases exist solely to increase code readability
diff --git a/src/koalageddon/cache.cpp b/src/koalageddon/kg_cache.cpp
similarity index 92%
rename from src/koalageddon/cache.cpp
rename to src/koalageddon/kg_cache.cpp
index 3ada77d..88ad5b0 100644
--- a/src/koalageddon/cache.cpp
+++ b/src/koalageddon/kg_cache.cpp
@@ -1,10 +1,10 @@
-#include
+#include
#include
#include
constexpr auto KEY_KG_CONFIG = "koalageddon_config";
-namespace koalageddon::cache {
+namespace koalageddon::kg_cache {
std::optional get_koalageddon_config() {
try {
diff --git a/src/koalageddon/cache.hpp b/src/koalageddon/kg_cache.hpp
similarity index 67%
rename from src/koalageddon/cache.hpp
rename to src/koalageddon/kg_cache.hpp
index 9c23471..4b6c8fe 100644
--- a/src/koalageddon/cache.hpp
+++ b/src/koalageddon/kg_cache.hpp
@@ -1,8 +1,8 @@
#pragma once
-#include
+#include
-namespace koalageddon::cache {
+namespace koalageddon::kg_cache {
std::optional get_koalageddon_config();
diff --git a/src/koalageddon/koalageddon.cpp b/src/koalageddon/koalageddon.cpp
index ad711e5..737254f 100644
--- a/src/koalageddon/koalageddon.cpp
+++ b/src/koalageddon/koalageddon.cpp
@@ -1,9 +1,9 @@
#include
#include
-#include
+#include
#include
-#include
-#include
+#include
+#include
#include
#include
#include
@@ -17,10 +17,10 @@ namespace koalageddon {
* @return A string representing the source of the config.
*/
String init_koalageddon_config() {
- if (!config::instance.koalageddon_config.is_null()) {
+ if (!smoke_api::config::instance.koalageddon_config.is_null()) {
try {
// First try to read a local config override
- config = config::instance.koalageddon_config.get();
+ config = smoke_api::config::instance.koalageddon_config.get();
return "local config override";
} catch (const Exception& ex) {
@@ -33,7 +33,7 @@ namespace koalageddon {
const String url = "https://raw.githubusercontent.com/acidicoala/public-entitlements/main/koalageddon/v2/steam.json";
config = koalabox::http_client::fetch_json(url).get();
- cache::save_koalageddon_config(config);
+ kg_cache::save_koalageddon_config(config);
return "GitHub repository";
} catch (const Exception& ex) {
@@ -43,7 +43,7 @@ namespace koalageddon {
try {
// Then try to get a cached copy of a previously fetched config.
// We expect this unboxing to throw exception if no koalageddon config is present.
- config = cache::get_koalageddon_config().value();
+ config = kg_cache::get_koalageddon_config().value();
return "disk cache";
} catch (const Exception& ex) {
@@ -71,7 +71,7 @@ namespace koalageddon {
globals::vstdlib_module = module_handle;
- if (config::instance.unlock_family_sharing) {
+ if (smoke_api::config::instance.unlock_family_sharing) {
DETOUR_VSTDLIB(Coroutine_Create)
}
} else if (name < equals > STEAMCLIENT_DLL) {
@@ -87,8 +87,9 @@ namespace koalageddon {
}
} catch (const Exception& ex) {
LOG_ERROR(
- "Koalageddon mode dll monitor process_interface_selector error. Module: '{}', Message: {}",
- name, ex.what())
+ "Error listening to DLL load events. Module: '{}', Message: {}",
+ name, ex.what()
+ )
}
}
);
diff --git a/src/koalageddon/koalageddon.hpp b/src/koalageddon/koalageddon.hpp
index feac193..8790c9e 100644
--- a/src/koalageddon/koalageddon.hpp
+++ b/src/koalageddon/koalageddon.hpp
@@ -1,8 +1,30 @@
#pragma once
-#include
+#include
namespace koalageddon {
+ // 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.
+ struct KoalageddonConfig {
+ uint32_t client_engine_steam_client_internal_ordinal = 12;
+ uint32_t steam_client_internal_interface_selector_ordinal = 18;
+ uint32_t vstdlib_callback_address_offset = 20;
+ uint32_t vstdlib_callback_data_offset = 0;
+ uint32_t vstdlib_callback_interceptor_address_offset = 1;
+ 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
+ NLOHMANN_DEFINE_TYPE_INTRUSIVE(
+ KoalageddonConfig, // NOLINT(misc-const-correctness)
+ client_engine_steam_client_internal_ordinal,
+ steam_client_internal_interface_selector_ordinal,
+ vstdlib_callback_address_offset,
+ vstdlib_callback_data_offset,
+ vstdlib_callback_interceptor_address_offset,
+ vstdlib_callback_name_offset
+ )
+ };
/// We need this interface in other IClient* functions in order to query original DLC status
extern const void* client_app_manager_interface;
diff --git a/src/koalageddon/steamclient.hpp b/src/koalageddon/steamclient.hpp
deleted file mode 100644
index 0bc73f3..0000000
--- a/src/koalageddon/steamclient.hpp
+++ /dev/null
@@ -1,7 +0,0 @@
-#pragma once
-
-namespace koalageddon::steamclient {
-
- void process_client_engine(uintptr_t interface);
-
-}
diff --git a/src/steamclient_virtuals/client_app_manager.cpp b/src/koalageddon/steamclient/client_app_manager.cpp
similarity index 79%
rename from src/steamclient_virtuals/client_app_manager.cpp
rename to src/koalageddon/steamclient/client_app_manager.cpp
index 5f80e48..bb3020a 100644
--- a/src/steamclient_virtuals/client_app_manager.cpp
+++ b/src/koalageddon/steamclient/client_app_manager.cpp
@@ -1,7 +1,4 @@
#include
-#include
-#include
-#include
VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t app_id, AppId_t dlc_id)) {
return steam_apps::IsDlcUnlocked(
diff --git a/src/steamclient_virtuals/client_apps.cpp b/src/koalageddon/steamclient/client_apps.cpp
similarity index 93%
rename from src/steamclient_virtuals/client_apps.cpp
rename to src/koalageddon/steamclient/client_apps.cpp
index 82b5d79..f143494 100644
--- a/src/steamclient_virtuals/client_apps.cpp
+++ b/src/koalageddon/steamclient/client_apps.cpp
@@ -1,8 +1,6 @@
-#include
-#include
#include
#include
-#include
+#include
VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t appId)) {
return steam_apps::GetDLCCount(
diff --git a/src/steamclient_virtuals/client_inventory.cpp b/src/koalageddon/steamclient/client_inventory.cpp
similarity index 97%
rename from src/steamclient_virtuals/client_inventory.cpp
rename to src/koalageddon/steamclient/client_inventory.cpp
index e987351..26d75f5 100644
--- a/src/steamclient_virtuals/client_inventory.cpp
+++ b/src/koalageddon/steamclient/client_inventory.cpp
@@ -1,7 +1,5 @@
-#include
-#include
+#include
#include
-#include
VIRTUAL(EResult) IClientInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) {
return steam_inventory::GetResultStatus(
diff --git a/src/steamclient_virtuals/client_user.cpp b/src/koalageddon/steamclient/client_user.cpp
similarity index 85%
rename from src/steamclient_virtuals/client_user.cpp
rename to src/koalageddon/steamclient/client_user.cpp
index 128a0e8..0881226 100644
--- a/src/steamclient_virtuals/client_user.cpp
+++ b/src/koalageddon/steamclient/client_user.cpp
@@ -1,4 +1,4 @@
-#include
+#include
#include
VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t app_id)) {
diff --git a/src/koalageddon/steamclient.cpp b/src/koalageddon/steamclient/steamclient.cpp
similarity index 94%
rename from src/koalageddon/steamclient.cpp
rename to src/koalageddon/steamclient/steamclient.cpp
index 5f7beb8..b776e34 100644
--- a/src/koalageddon/steamclient.cpp
+++ b/src/koalageddon/steamclient/steamclient.cpp
@@ -1,8 +1,9 @@
+#include
#include
-#include
#include
#include
#include
+
#include
#include
@@ -85,9 +86,9 @@ namespace koalageddon::steamclient {
const auto& operand = instruction.operands[0];
return instruction.mnemonic == ZYDIS_MNEMONIC_PUSH &&
- operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
- operand.visibility == ZYDIS_OPERAND_VISIBILITY_EXPLICIT &&
- operand.encoding == ZYDIS_OPERAND_ENCODING_SIMM16_32_32;
+ operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE &&
+ operand.visibility == ZYDIS_OPERAND_VISIBILITY_EXPLICIT &&
+ operand.encoding == ZYDIS_OPERAND_ENCODING_SIMM16_32_32;
}
std::optional get_string_argument(const ZydisDecodedInstruction& instruction) {
@@ -141,9 +142,9 @@ namespace koalageddon::steamclient {
const auto is_mov_base_esp = [](const ZydisDecodedInstruction& instruction) {
return instruction.mnemonic == ZYDIS_MNEMONIC_MOV &&
- instruction.operand_count == 2 &&
- instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
- instruction.operands[1].reg.value == ZYDIS_REGISTER_ESP;
+ instruction.operand_count == 2 &&
+ instruction.operands[0].type == ZYDIS_OPERAND_TYPE_REGISTER &&
+ instruction.operands[1].reg.value == ZYDIS_REGISTER_ESP;
};
// Initialize with a dummy previous instruction
@@ -158,7 +159,7 @@ namespace koalageddon::steamclient {
&instruction
))) {
LOG_TRACE(
- "{} visiting {} | {}", __func__,
+ "{} visiting {} │ {}", __func__,
(void*) current_address, *get_instruction_string(instruction, current_address)
)
@@ -168,8 +169,8 @@ namespace koalageddon::steamclient {
// Save base register
context.base_register = instruction.operands[0].reg.value;
} else if (is_push_immediate(last_instruction) &&
- is_push_immediate(instruction) &&
- !context.function_name) {
+ is_push_immediate(instruction) &&
+ !context.function_name) {
// The very first 2 consecutive pushes indicate interface and function names.
// However, subsequent pushes may contain irrelevant strings.
const auto push_string_1 = get_string_argument(last_instruction);
@@ -198,7 +199,7 @@ namespace koalageddon::steamclient {
// But not continue forward, in order to avoid duplicate processing
return;
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
- instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) {
+ instruction.operands[0].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) {
// On unconditional jump we should recurse as well
const auto jump_destination = get_absolute_address(instruction, current_address);
@@ -341,7 +342,7 @@ namespace koalageddon::steamclient {
))) {
visited_addresses.insert(current_address);
LOG_TRACE(
- "{} visiting {} | {}", __func__,
+ "{} visiting {} │ {}", __func__,
(void*) current_address, *get_instruction_string(instruction, current_address)
)
@@ -376,7 +377,7 @@ namespace koalageddon::steamclient {
LOG_TRACE("Breaking recursion due to conditional branch")
return;
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
- operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE
+ operand.type == ZYDIS_OPERAND_TYPE_IMMEDIATE
) {
const auto jump_destination = get_absolute_address(instruction, current_address);
@@ -385,9 +386,9 @@ namespace koalageddon::steamclient {
LOG_TRACE("Breaking recursion due to unconditional branch")
return;
} else if (instruction.mnemonic == ZYDIS_MNEMONIC_JMP &&
- operand.type == ZYDIS_OPERAND_TYPE_MEMORY &&
- operand.mem.scale == sizeof(uintptr_t) &&
- operand.mem.disp.has_displacement
+ operand.type == ZYDIS_OPERAND_TYPE_MEMORY &&
+ operand.mem.scale == sizeof(uintptr_t) &&
+ operand.mem.disp.has_displacement
) {
// Special handling for jump tables. Guaranteed to be present in the interface selector.
const auto* table = (uintptr_t*) operand.mem.disp.value;
diff --git a/src/koalageddon/steamclient/steamclient.hpp b/src/koalageddon/steamclient/steamclient.hpp
new file mode 100644
index 0000000..152a1e4
--- /dev/null
+++ b/src/koalageddon/steamclient/steamclient.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include
+
+// IClientAppManager
+VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t, AppId_t));
+
+// IClientApps
+VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t));
+VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(PARAMS(AppId_t, int, AppId_t*, bool*, char*, int));
+
+// IClientInventory
+VIRTUAL(EResult) IClientInventory_GetResultStatus(PARAMS(SteamInventoryResult_t));
+VIRTUAL(bool) IClientInventory_GetResultItems(
+ PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t, uint32_t *)
+);
+VIRTUAL(bool) IClientInventory_GetResultItemProperty(
+ PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t, uint32_t*)
+);
+VIRTUAL(bool) IClientInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID));
+VIRTUAL(bool) IClientInventory_GetAllItems(PARAMS(SteamInventoryResult_t*));
+VIRTUAL(bool) IClientInventory_GetItemsByID(PARAMS(SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t));
+VIRTUAL(bool) IClientInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t, uint32_t *));
+VIRTUAL(bool) IClientInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t, uint32_t *));
+
+// IClientUser
+VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t));
+
+namespace koalageddon::steamclient {
+
+ void process_client_engine(uintptr_t interface);
+
+}
diff --git a/src/koalageddon/types.hpp b/src/koalageddon/types.hpp
deleted file mode 100644
index 7758f0b..0000000
--- a/src/koalageddon/types.hpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#pragma once
-
-#include
-
-// 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.
-struct KoalageddonConfig {
- uint32_t client_engine_steam_client_internal_ordinal = 12;
- uint32_t steam_client_internal_interface_selector_ordinal = 18;
- uint32_t vstdlib_callback_address_offset = 20;
- uint32_t vstdlib_callback_data_offset = 0;
- uint32_t vstdlib_callback_interceptor_address_offset = 1;
- 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
- NLOHMANN_DEFINE_TYPE_INTRUSIVE(
- KoalageddonConfig, // NOLINT(misc-const-correctness)
- client_engine_steam_client_internal_ordinal,
- steam_client_internal_interface_selector_ordinal,
- vstdlib_callback_address_offset,
- vstdlib_callback_data_offset,
- vstdlib_callback_interceptor_address_offset,
- vstdlib_callback_name_offset
- )
-};
diff --git a/src/koalageddon/vstdlib.cpp b/src/koalageddon/vstdlib.cpp
index 69c0b6c..03157a2 100644
--- a/src/koalageddon/vstdlib.cpp
+++ b/src/koalageddon/vstdlib.cpp
@@ -1,5 +1,4 @@
#include
-#include
#include
#include
diff --git a/src/koalageddon/vstdlib.hpp b/src/koalageddon/vstdlib.hpp
index c4c0fa9..3a74986 100644
--- a/src/koalageddon/vstdlib.hpp
+++ b/src/koalageddon/vstdlib.hpp
@@ -1,4 +1,3 @@
-#include
#include
namespace koalageddon::vstdlib {
diff --git a/src/core/config.cpp b/src/smoke_api/config.cpp
similarity index 97%
rename from src/core/config.cpp
rename to src/smoke_api/config.cpp
index bc07557..9c290a7 100644
--- a/src/core/config.cpp
+++ b/src/smoke_api/config.cpp
@@ -1,9 +1,9 @@
-#include
+#include
#include
#include
#include
-namespace config {
+namespace smoke_api::config {
Config instance; // NOLINT(cert-err58-cpp)
// TODO: Reloading via export
diff --git a/src/core/config.hpp b/src/smoke_api/config.hpp
similarity index 97%
rename from src/core/config.hpp
rename to src/smoke_api/config.hpp
index 44c33cf..c560d31 100644
--- a/src/core/config.hpp
+++ b/src/smoke_api/config.hpp
@@ -3,8 +3,7 @@
#include
#include
-// TODO: move to smoke_api namespace
-namespace config {
+namespace smoke_api::config {
enum class AppStatus {
LOCKED,
UNLOCKED,
diff --git a/src/smoke_api/smoke_api.cpp b/src/smoke_api/smoke_api.cpp
index f0b7cff..700b629 100644
--- a/src/smoke_api/smoke_api.cpp
+++ b/src/smoke_api/smoke_api.cpp
@@ -1,9 +1,8 @@
#include
#include
-#include
+#include
#include
#include
-#include
#include
#include
#include
@@ -11,6 +10,7 @@
#include
#include
#include
+#include
#if COMPILE_KOALAGEDDON
#include
diff --git a/src/steam_api_exports/steam_api_exports.hpp b/src/steam_api_exports/steam_api_exports.hpp
new file mode 100644
index 0000000..175d533
--- /dev/null
+++ b/src/steam_api_exports/steam_api_exports.hpp
@@ -0,0 +1,35 @@
+#pragma once
+
+#include
+
+// Flat
+DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(ISteamApps*, AppId_t);
+DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(ISteamApps*, AppId_t);
+DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(ISteamApps*);
+DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(ISteamApps*, int, AppId_t*, bool*, char*, int);
+DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(ISteamUser*, CSteamID, AppId_t);
+DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(ISteamClient*, HSteamUser, HSteamPipe, const char*);
+DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(ISteamInventory*, SteamInventoryResult_t);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(
+ ISteamInventory*, SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*
+);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty(
+ ISteamInventory*, SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*
+);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(ISteamInventory*, SteamInventoryResult_t, CSteamID);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(ISteamInventory*, SteamInventoryResult_t*);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
+ ISteamInventory*, SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t
+);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(ISteamInventory*, SteamInventoryResult_t, void*, uint32_t*);
+DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(ISteamInventory*, SteamItemDef_t*, uint32_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();
diff --git a/src/steam_api_exports/steam_api_flat.cpp b/src/steam_api_exports/steam_api_flat.cpp
index 0085f9e..e5c225a 100644
--- a/src/steam_api_exports/steam_api_flat.cpp
+++ b/src/steam_api_exports/steam_api_flat.cpp
@@ -1,12 +1,8 @@
-#include
-#include
+#include
#include
#include
#include
#include
-#include
-
-using namespace koalabox;
// ISteamApps
diff --git a/src/steam_api_exports/steam_api_internal.cpp b/src/steam_api_exports/steam_api_internal.cpp
index bd63bf3..9255e29 100644
--- a/src/steam_api_exports/steam_api_internal.cpp
+++ b/src/steam_api_exports/steam_api_internal.cpp
@@ -1,9 +1,5 @@
-#include
-#include
+#include
#include
-#include
-
-using namespace koalabox;
DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser hSteamUser, const char* version) {
return steam_client::GetGenericInterface(
diff --git a/src/steam_api_exports/steam_api_unversioned.cpp b/src/steam_api_exports/steam_api_unversioned.cpp
index e679295..a5cf207 100644
--- a/src/steam_api_exports/steam_api_unversioned.cpp
+++ b/src/steam_api_exports/steam_api_unversioned.cpp
@@ -1,13 +1,10 @@
+#include
#include
-#include
#include
#include
#include
-#include
#include
-using namespace koalabox;
-
/**
* Searches the `.rdata` section of the original dll for the full interface version string
* Results are cached for performance.
@@ -17,7 +14,7 @@ String get_versioned_interface(const String& version_prefix, const String& fallb
if (not version_map.contains(version_prefix)) {
try {
- const String rdata = win_util::get_pe_section_data_or_throw(globals::steamapi_module, ".rdata");
+ const String rdata = koalabox::win_util::get_pe_section_data_or_throw(globals::steamapi_module, ".rdata");
const std::regex regex(version_prefix + "\\d{3}");
std::smatch match;
@@ -26,7 +23,7 @@ String get_versioned_interface(const String& version_prefix, const String& fallb
return version_map[version_prefix];
}
- throw util::exception("No match found for '{}'", version_prefix);
+ throw koalabox::util::exception("No match found for '{}'", version_prefix);
} catch (const Exception& ex) {
LOG_ERROR(
"Failed to get versioned interface: {}."
@@ -41,7 +38,7 @@ String get_versioned_interface(const String& version_prefix, const String& fallb
}
DLL_EXPORT(void*) SteamClient() {
- static auto version = get_versioned_interface(steam_functions::STEAM_CLIENT, "006");
+ static auto version = get_versioned_interface(STEAM_CLIENT, "006");
return steam_client::GetGenericInterface(
__func__, version, [&]() {
@@ -53,7 +50,7 @@ DLL_EXPORT(void*) SteamClient() {
}
DLL_EXPORT(void*) SteamApps() {
- static auto version = get_versioned_interface(steam_functions::STEAM_APPS, "002");
+ static auto version = get_versioned_interface(STEAM_APPS, "002");
return steam_client::GetGenericInterface(
__func__, version, [&]() {
@@ -65,7 +62,7 @@ DLL_EXPORT(void*) SteamApps() {
}
DLL_EXPORT(void*) SteamUser() {
- static auto version = get_versioned_interface(steam_functions::STEAM_USER, "012");
+ static auto version = get_versioned_interface(STEAM_USER, "012");
return steam_client::GetGenericInterface(
__func__, version, [&]() {
@@ -77,7 +74,7 @@ DLL_EXPORT(void*) SteamUser() {
}
DLL_EXPORT(void*) SteamInventory() {
- static auto version = get_versioned_interface(steam_functions::STEAM_INVENTORY, "001");
+ static auto version = get_versioned_interface(STEAM_INVENTORY, "001");
return steam_client::GetGenericInterface(
__func__, version, [&]() {
diff --git a/src/steam_api_virtuals/isteamapps.cpp b/src/steam_api_virtuals/isteamapps.cpp
index d32d11e..f0e5f9f 100644
--- a/src/steam_api_virtuals/isteamapps.cpp
+++ b/src/steam_api_virtuals/isteamapps.cpp
@@ -1,5 +1,5 @@
+#include
#include
-#include
VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t appID)) {
return steam_apps::IsDlcUnlocked(
diff --git a/src/steam_api_virtuals/isteamclient.cpp b/src/steam_api_virtuals/isteamclient.cpp
index df38a53..4844358 100644
--- a/src/steam_api_virtuals/isteamclient.cpp
+++ b/src/steam_api_virtuals/isteamclient.cpp
@@ -1,5 +1,5 @@
+#include
#include
-#include
VIRTUAL(void*) ISteamClient_GetISteamApps(
PARAMS(
diff --git a/src/steam_api_virtuals/isteaminventory.cpp b/src/steam_api_virtuals/isteaminventory.cpp
index d4a49fb..be80b60 100644
--- a/src/steam_api_virtuals/isteaminventory.cpp
+++ b/src/steam_api_virtuals/isteaminventory.cpp
@@ -1,5 +1,5 @@
+#include
#include
-#include
VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t resultHandle)) {
return steam_inventory::GetResultStatus(
diff --git a/src/steam_api_virtuals/isteamuser.cpp b/src/steam_api_virtuals/isteamuser.cpp
index 6f47e0a..e6eda64 100644
--- a/src/steam_api_virtuals/isteamuser.cpp
+++ b/src/steam_api_virtuals/isteamuser.cpp
@@ -1,5 +1,5 @@
+#include
#include
-#include
VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID steamID, AppId_t appID)) {
return steam_user::UserHasLicenseForApp(
diff --git a/src/steam_api_virtuals/steam_api_virtuals.hpp b/src/steam_api_virtuals/steam_api_virtuals.hpp
new file mode 100644
index 0000000..fe52c8f
--- /dev/null
+++ b/src/steam_api_virtuals/steam_api_virtuals.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include
+
+// ISteamApps
+VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t));
+VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t));
+VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS());
+VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(PARAMS(int, AppId_t*, bool*, char*, int));
+
+// ISteamClient
+VIRTUAL(void*) ISteamClient_GetISteamApps(PARAMS(HSteamUser, HSteamPipe, const char*));
+VIRTUAL(void*) ISteamClient_GetISteamUser(PARAMS(HSteamUser, HSteamPipe, const char*));
+VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(PARAMS(HSteamUser, HSteamPipe, const char*));
+VIRTUAL(void*) ISteamClient_GetISteamInventory(PARAMS(HSteamUser, HSteamPipe, const char*));
+
+
+// ISteamInventory
+VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t));
+VIRTUAL(bool) ISteamInventory_GetResultItems(PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*));
+VIRTUAL(bool) ISteamInventory_GetResultItemProperty(
+ PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*)
+);
+VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t*));
+VIRTUAL(bool) ISteamInventory_GetItemsByID(PARAMS(SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t));
+VIRTUAL(bool) ISteamInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t*));
+VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t*));
+VIRTUAL(bool) ISteamInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID));
+
+// ISteamUser
+VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t));
diff --git a/src/steam_functions/steam_functions.hpp b/src/steam_functions/steam_functions.hpp
deleted file mode 100644
index 778be77..0000000
--- a/src/steam_functions/steam_functions.hpp
+++ /dev/null
@@ -1,102 +0,0 @@
-#pragma once
-
-#include
-#include
-
-// TODO: Refactor into multiple headers
-
-// ISteamClient
-VIRTUAL(void*) ISteamClient_GetISteamApps(PARAMS(HSteamUser, HSteamPipe, const char*));
-VIRTUAL(void*) ISteamClient_GetISteamUser(PARAMS(HSteamUser, HSteamPipe, const char*));
-VIRTUAL(void*) ISteamClient_GetISteamGenericInterface(PARAMS(HSteamUser, HSteamPipe, const char*));
-VIRTUAL(void*) ISteamClient_GetISteamInventory(PARAMS(HSteamUser, HSteamPipe, const char*));
-
-// ISteamApps
-VIRTUAL(bool) ISteamApps_BIsSubscribedApp(PARAMS(AppId_t));
-VIRTUAL(bool) ISteamApps_BIsDlcInstalled(PARAMS(AppId_t));
-VIRTUAL(int) ISteamApps_GetDLCCount(PARAMS());
-VIRTUAL(bool) ISteamApps_BGetDLCDataByIndex(PARAMS(int, AppId_t*, bool*, char*, int));
-
-// ISteamUser
-VIRTUAL(EUserHasLicenseForAppResult) ISteamUser_UserHasLicenseForApp(PARAMS(CSteamID, AppId_t));
-
-// ISteamInventory
-VIRTUAL(EResult) ISteamInventory_GetResultStatus(PARAMS(SteamInventoryResult_t));
-VIRTUAL(bool) ISteamInventory_GetResultItems(PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*));
-VIRTUAL(bool) ISteamInventory_GetResultItemProperty(
- PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*)
-);
-VIRTUAL(bool) ISteamInventory_GetAllItems(PARAMS(SteamInventoryResult_t*));
-VIRTUAL(bool) ISteamInventory_GetItemsByID(PARAMS(SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t));
-VIRTUAL(bool) ISteamInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t*));
-VIRTUAL(bool) ISteamInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t*));
-VIRTUAL(bool) ISteamInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID));
-
-// API
-
-DLL_EXPORT(void*) CreateInterface(const char*, int*);
-DLL_EXPORT(void*) SteamInternal_FindOrCreateUserInterface(HSteamUser, const char*);
-DLL_EXPORT(void*) SteamInternal_CreateInterface(const char*);
-DLL_EXPORT(void*) SteamApps();
-DLL_EXPORT(void*) SteamClient();
-DLL_EXPORT(void*) SteamUser();
-
-// Flat interfaces
-
-DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsSubscribedApp(ISteamApps*, AppId_t);
-DLL_EXPORT(bool) SteamAPI_ISteamApps_BIsDlcInstalled(ISteamApps*, AppId_t);
-DLL_EXPORT(int) SteamAPI_ISteamApps_GetDLCCount(ISteamApps*);
-DLL_EXPORT(bool) SteamAPI_ISteamApps_BGetDLCDataByIndex(ISteamApps*, int, AppId_t*, bool*, char*, int);
-DLL_EXPORT(EUserHasLicenseForAppResult) SteamAPI_ISteamUser_UserHasLicenseForApp(ISteamUser*, CSteamID, AppId_t);
-DLL_EXPORT(void*) SteamAPI_ISteamClient_GetISteamGenericInterface(ISteamClient*, HSteamUser, HSteamPipe, const char*);
-DLL_EXPORT(EResult) SteamAPI_ISteamInventory_GetResultStatus(ISteamInventory*, SteamInventoryResult_t);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItems(
- ISteamInventory*, SteamInventoryResult_t, SteamItemDetails_t*, uint32_t*
-);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetResultItemProperty(
- ISteamInventory*, SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t*
-);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_CheckResultSteamID(ISteamInventory*, SteamInventoryResult_t, CSteamID);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetAllItems(ISteamInventory*, SteamInventoryResult_t*);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemsByID(
- ISteamInventory*, SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t
-);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_SerializeResult(ISteamInventory*, SteamInventoryResult_t, void*, uint32_t*);
-DLL_EXPORT(bool) SteamAPI_ISteamInventory_GetItemDefinitionIDs(ISteamInventory*, SteamItemDef_t*, uint32_t*);
-
-// IClientApps
-VIRTUAL(int) IClientApps_GetDLCCount(PARAMS(AppId_t));
-VIRTUAL(bool) IClientApps_BGetDLCDataByIndex(PARAMS(AppId_t, int, AppId_t*, bool*, char*, int));
-
-// IClientAppManager
-VIRTUAL(bool) IClientAppManager_IsAppDlcInstalled(PARAMS(AppId_t, AppId_t));
-
-// IClientUser
-VIRTUAL(bool) IClientUser_BIsSubscribedApp(PARAMS(AppId_t));
-
-// IClientInventory
-VIRTUAL(EResult) IClientInventory_GetResultStatus(PARAMS(SteamInventoryResult_t));
-VIRTUAL(bool) IClientInventory_GetResultItems(
- PARAMS(SteamInventoryResult_t, SteamItemDetails_t*, uint32_t, uint32_t *)
-);
-VIRTUAL(bool) IClientInventory_GetResultItemProperty(
- PARAMS(SteamInventoryResult_t, uint32_t, const char*, char*, uint32_t, uint32_t*)
-);
-VIRTUAL(bool) IClientInventory_CheckResultSteamID(PARAMS(SteamInventoryResult_t, CSteamID));
-VIRTUAL(bool) IClientInventory_GetAllItems(PARAMS(SteamInventoryResult_t*));
-VIRTUAL(bool) IClientInventory_GetItemsByID(PARAMS(SteamInventoryResult_t*, const SteamItemInstanceID_t*, uint32_t));
-VIRTUAL(bool) IClientInventory_SerializeResult(PARAMS(SteamInventoryResult_t, void*, uint32_t, uint32_t *));
-VIRTUAL(bool) IClientInventory_GetItemDefinitionIDs(PARAMS(SteamItemDef_t*, uint32_t, uint32_t *));
-
-namespace steam_functions {
- using namespace koalabox;
-
- const String STEAM_APPS = "STEAMAPPS_INTERFACE_VERSION"; // NOLINT(cert-err58-cpp)
- const String STEAM_CLIENT = "SteamClient"; // NOLINT(cert-err58-cpp)
- const String STEAM_USER = "SteamUser"; // NOLINT(cert-err58-cpp)
- const String STEAM_INVENTORY = "STEAMINVENTORY_INTERFACE_V"; // NOLINT(cert-err58-cpp)
- const String CLIENT_ENGINE = "CLIENTENGINE_INTERFACE_VERSION"; // NOLINT(cert-err58-cpp)
-
- void hook_virtuals(void* interface, const String& version_string);
- uint32_t get_app_id_or_throw();
-}
diff --git a/src/steam_impl/steam_apps.cpp b/src/steam_impl/steam_apps.cpp
index bf06885..f1cfe96 100644
--- a/src/steam_impl/steam_apps.cpp
+++ b/src/steam_impl/steam_apps.cpp
@@ -1,23 +1,13 @@
#include
-#include
+#include
#include
-#include
+#include
#include
#include
-#include
#include
-#include
+#include
namespace steam_apps {
- // TODO: Needs to go to API
-
- struct SteamResponse {
- uint32_t success = 0;
- Vector dlcs;
-
- NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(SteamResponse, success, dlcs) // NOLINT(misc-const-correctness)
- };
-
/// Steamworks may max GetDLCCount value at 64, depending on how much unowned DLCs the user has.
/// Despite this limit, some games with more than 64 DLCs still keep using this method.
/// This means we have to get extra DLC IDs from local config, remote config, or cache.
@@ -26,38 +16,8 @@ namespace steam_apps {
Map> app_dlcs; // NOLINT(cert-err58-cpp)
Set fully_fetched; // NOLINT(cert-err58-cpp)
- std::optional> fetch_from_github(AppId_t app_id) noexcept {
- try {
- const auto* url
- = "https://raw.githubusercontent.com/acidicoala/public-entitlements/main/steam/v2/dlc.json";
- const auto json = koalabox::http_client::fetch_json(url);
- const auto response = json.get();
-
- return DLC::get_dlcs_from_apps(response, app_id);
- } catch (const Json::exception& e) {
- LOG_ERROR("Failed to fetch dlc list from GitHub: {}", e.what())
- return std::nullopt;
- }
- }
-
- std::optional> fetch_from_steam(AppId_t app_id) noexcept {
- try {
- const auto url = fmt::format("https://store.steampowered.com/dlc/{}/ajaxgetdlclist", app_id);
- const auto json = koalabox::http_client::fetch_json(url);
-
- LOG_TRACE("Steam response: \n{}", json.dump(2))
-
- const auto response = json.get();
-
- if (response.success != 1) {
- throw std::runtime_error("Web API responded with 'success' != 1");
- }
-
- return response.dlcs;
- } catch (const Exception& e) {
- LOG_ERROR("Failed to fetch dlc list from Steam: {}", e.what())
- return std::nullopt;
- }
+ String get_app_id_log(const AppId_t app_id) {
+ return app_id ? fmt::format("App ID: {:>8}, ", app_id) : "";
}
/**
@@ -72,7 +32,7 @@ namespace steam_apps {
// No app id means we are operating in game mode.
// Hence, we need to use utility functions to get app id.
try {
- app_id = steam_functions::get_app_id_or_throw();
+ app_id = steam_impl::get_app_id_or_throw();
LOG_INFO("Detected App ID: {}", app_id)
} catch (const Exception& ex) {
LOG_ERROR("Failed to get app ID: {}", ex.what())
@@ -96,19 +56,19 @@ namespace steam_apps {
aggregated_dlcs < append > source;
};
- append_dlcs(config::get_extra_dlcs(app_id), "local config");
+ append_dlcs(smoke_api::config::get_extra_dlcs(app_id), "local config");
- const auto github_dlcs = fetch_from_github(app_id);
- if (github_dlcs) {
- append_dlcs(*github_dlcs, "GitHub repository");
+ const auto github_dlcs_opt = api::fetch_dlcs_from_github(app_id);
+ if (github_dlcs_opt) {
+ append_dlcs(*github_dlcs_opt, "GitHub repository");
}
- const auto steam_dlcs = fetch_from_steam(app_id);
- if (steam_dlcs) {
- append_dlcs(*steam_dlcs, "Steam API");
+ const auto steam_dlcs_opt = api::fetch_dlcs_from_steam(app_id);
+ if (steam_dlcs_opt) {
+ append_dlcs(*steam_dlcs_opt, "Steam API");
}
- if (github_dlcs && steam_dlcs) {
+ if (github_dlcs_opt && steam_dlcs_opt) {
fully_fetched.insert(app_id);
} else {
append_dlcs(smoke_api::app_cache::get_dlcs(app_id), "disk cache");
@@ -121,10 +81,6 @@ namespace steam_apps {
smoke_api::app_cache::save_dlcs(app_id, aggregated_dlcs);
}
- String get_app_id_log(const AppId_t app_id) {
- return app_id ? fmt::format("App ID: {:>8}, ", app_id) : "";
- }
-
bool IsDlcUnlocked(
const String& function_name,
AppId_t app_id,
@@ -132,7 +88,7 @@ namespace steam_apps {
const Function& original_function
) {
try {
- const auto unlocked = config::is_dlc_unlocked(app_id, dlc_id, original_function);
+ const auto unlocked = smoke_api::config::is_dlc_unlocked(app_id, dlc_id, original_function);
LOG_INFO("{} -> {}DLC ID: {:>8}, Unlocked: {}", function_name, get_app_id_log(app_id), dlc_id, unlocked)
@@ -196,7 +152,7 @@ namespace steam_apps {
const auto inject_dlc = [&](const DLC& dlc) {
// Fill the output pointers
*pDlcId = dlc.get_id();
- *pbAvailable = config::is_dlc_unlocked(
+ *pbAvailable = smoke_api::config::is_dlc_unlocked(
app_id, *pDlcId, [&]() {
return is_originally_unlocked(*pDlcId);
}
@@ -223,7 +179,9 @@ namespace steam_apps {
const auto success = original_function();
if (success) {
- *pbAvailable = config::is_dlc_unlocked(app_id, *pDlcId, [&]() { return *pbAvailable; });
+ *pbAvailable = smoke_api::config::is_dlc_unlocked(
+ app_id, *pDlcId, [&]() { return *pbAvailable; }
+ );
print_dlc_info("original");
} else {
LOG_WARN("{} -> original call failed for index: {}", function_name, iDLC)
diff --git a/src/steam_impl/steam_apps.hpp b/src/steam_impl/steam_apps.hpp
index 7f7dea2..ae9bb3d 100644
--- a/src/steam_impl/steam_apps.hpp
+++ b/src/steam_impl/steam_apps.hpp
@@ -1,7 +1,6 @@
#pragma once
#include
-#include
namespace steam_apps {
diff --git a/src/steam_impl/steam_client.cpp b/src/steam_impl/steam_client.cpp
index da5986c..ca1b05c 100644
--- a/src/steam_impl/steam_client.cpp
+++ b/src/steam_impl/steam_client.cpp
@@ -1,6 +1,6 @@
#include
+#include
#include
-#include
namespace steam_client {
@@ -13,7 +13,7 @@ namespace steam_client {
LOG_DEBUG("{} -> '{}' @ {}", function_name, interface_version, interface)
- steam_functions::hook_virtuals(interface, interface_version);
+ steam_impl::hook_virtuals(interface, interface_version);
return interface;
}
diff --git a/src/steam_impl/steam_client.hpp b/src/steam_impl/steam_client.hpp
index b9d64fb..210a62b 100644
--- a/src/steam_impl/steam_client.hpp
+++ b/src/steam_impl/steam_client.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include
+#include
namespace steam_client {
diff --git a/src/steam_functions/steam_functions.cpp b/src/steam_impl/steam_impl.cpp
similarity index 89%
rename from src/steam_functions/steam_functions.cpp
rename to src/steam_impl/steam_impl.cpp
index 983afb5..7bfeac8 100644
--- a/src/steam_functions/steam_functions.cpp
+++ b/src/steam_impl/steam_impl.cpp
@@ -1,4 +1,7 @@
-#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -7,10 +10,10 @@
#include
#if COMPILE_KOALAGEDDON
-#include
+#include
#endif
-namespace steam_functions {
+namespace steam_impl {
typedef Map> FunctionOrdinalMap;
@@ -19,7 +22,7 @@ namespace steam_functions {
{
{6, 16},
{7, 18},
- {8, 15},
+ {8, 15},
{9, 16},
{12, 15},
}
@@ -105,7 +108,7 @@ namespace steam_functions {
return version_number;
} catch (const std::exception& ex) {
- util::panic("Failed to extract version number from: '{}'", version_string);
+ koalabox::util::panic("Failed to extract version number from: '{}'", version_string);
}
}
@@ -120,11 +123,11 @@ namespace steam_functions {
}
}
- util::panic("Invalid interface version ({}) for function {}", interface_version, function_name);
+ koalabox::util::panic("Invalid interface version ({}) for function {}", interface_version, function_name);
}
#define HOOK_VIRTUALS(MAP, FUNC) \
- hook::swap_virtual_func( \
+ koalabox::hook::swap_virtual_func( \
globals::address_map, \
interface, \
#FUNC, \
@@ -209,14 +212,14 @@ namespace steam_functions {
}
HSteamPipe get_steam_pipe_or_throw() {
- const auto& steam_api_module = win_util::get_module_handle_or_throw(STEAMAPI_DLL);
+ const auto& steam_api_module = koalabox::win_util::get_module_handle_or_throw(STEAMAPI_DLL);
void* GetHSteamPipe_address;
try {
- GetHSteamPipe_address = (void*) win_util::get_proc_address_or_throw(
+ GetHSteamPipe_address = (void*) koalabox::win_util::get_proc_address_or_throw(
steam_api_module, "SteamAPI_GetHSteamPipe"
);
} catch (const Exception& ex) {
- GetHSteamPipe_address = (void*) win_util::get_proc_address_or_throw(
+ GetHSteamPipe_address = (void*) koalabox::win_util::get_proc_address_or_throw(
steam_api_module, "GetHSteamPipe"
);
}
@@ -245,8 +248,8 @@ namespace steam_functions {
AppId_t get_app_id_or_throw() {
// Get CreateInterface
- const auto& steam_client_module = win_util::get_module_handle_or_throw(STEAMCLIENT_DLL);
- auto* CreateInterface_address = (void*) win_util::get_proc_address_or_throw(
+ const auto& steam_client_module = koalabox::win_util::get_module_handle_or_throw(STEAMCLIENT_DLL);
+ auto* CreateInterface_address = (void*) koalabox::win_util::get_proc_address_or_throw(
steam_client_module, "CreateInterface"
);
auto* CreateInterface_o = PLH::FnCast(CreateInterface_address, CreateInterface);
@@ -255,7 +258,7 @@ namespace steam_functions {
int result;
auto* i_steam_client = CreateInterface_o("SteamClient006", &result);
if (i_steam_client == nullptr) {
- throw util::exception("Failed to obtain SteamClient006 interface. Result: {}", result);
+ throw koalabox::util::exception("Failed to obtain SteamClient006 interface. Result: {}", result);
}
// Get GetISteamUtils
diff --git a/src/steam_impl/steam_impl.hpp b/src/steam_impl/steam_impl.hpp
new file mode 100644
index 0000000..79d3899
--- /dev/null
+++ b/src/steam_impl/steam_impl.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include
+
+namespace steam_impl {
+
+ void hook_virtuals(void* interface, const String& version_string);
+
+ uint32_t get_app_id_or_throw();
+
+}
diff --git a/src/steam_impl/steam_inventory.cpp b/src/steam_impl/steam_inventory.cpp
index 6a530d5..02c70d9 100644
--- a/src/steam_impl/steam_inventory.cpp
+++ b/src/steam_impl/steam_inventory.cpp
@@ -1,5 +1,5 @@
#include
-#include
+#include
#include
namespace steam_inventory {
@@ -53,11 +53,11 @@ namespace steam_inventory {
)
static uint32_t original_count = 0;
- const auto injected_count = config::instance.extra_inventory_items.size();
+ const auto injected_count = smoke_api::config::instance.extra_inventory_items.size();
// Automatically get inventory items from steam
static Vector auto_inventory_items;
- if (config::instance.auto_inject_inventory) {
+ if (smoke_api::config::instance.auto_inject_inventory) {
CALL_ONCE({
uint32_t count = 0;
if (get_item_definition_ids(nullptr, &count)) {
@@ -103,7 +103,7 @@ namespace steam_inventory {
for (int i = 0; i < injected_count; i++) {
auto& item = pOutItemsArray[original_count + auto_injected_count + i];
- const auto item_def_id = config::instance.extra_inventory_items[i];
+ const auto item_def_id = smoke_api::config::instance.extra_inventory_items[i];
item = new_item(item_def_id);
diff --git a/src/steam_impl/steam_user.cpp b/src/steam_impl/steam_user.cpp
index d6efaf8..3f68320 100644
--- a/src/steam_impl/steam_user.cpp
+++ b/src/steam_impl/steam_user.cpp
@@ -1,5 +1,5 @@
#include
-#include
+#include
#include
namespace steam_user {
@@ -16,7 +16,7 @@ namespace steam_user {
return result;
}
- const auto has_license = config::is_dlc_unlocked(
+ const auto has_license = smoke_api::config::is_dlc_unlocked(
0, appID, [&]() {
return result == k_EUserHasLicenseResultHasLicense;
}
diff --git a/src/steamclient_exports/steamclient.cpp b/src/steamclient_exports/steamclient.cpp
index 453ca38..3312072 100644
--- a/src/steamclient_exports/steamclient.cpp
+++ b/src/steamclient_exports/steamclient.cpp
@@ -1,4 +1,3 @@
-#include
#include
DLL_EXPORT(void*) CreateInterface(const char* interface_string, int* out_result) {