mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-09-29 10:17:56 +03:00
sdk: add get_module_info, get_plugin_directory, d3d9 callbacks (#908)
## Link to GitHub Issue or related Pull Request, if one exists n/a ## Description of change To make plugin development easier, add `get_module_info` and `get_plugin_directory` to deal with common tasks for hooking DLLs and reading INI files. Also, add the ability to register for d3d9 present callbacks via `register_d3d9`, which makes it significantly easier for plugins to draw things on screen. ## Testing See sample code.
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
#include <format>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <windows.h>
|
||||
|
||||
#include "v0_cpp_imgui.h"
|
||||
#include "sdk/include/spicesdk.h"
|
||||
#include "sdk/include/spicesdk_io.h"
|
||||
|
||||
@@ -17,6 +21,24 @@ static spice_sdk_destroy_callback_func destroy_callback;
|
||||
static std::jthread worker_thread;
|
||||
static void worker_thread_main(std::stop_token stop_token);
|
||||
|
||||
static std::optional<std::string> utf16_to_utf8(const wchar_t *text) {
|
||||
const auto bytes = WideCharToMultiByte(
|
||||
CP_UTF8, WC_ERR_INVALID_CHARS, text, -1, nullptr, 0, nullptr, nullptr);
|
||||
if (bytes == 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string result(bytes, '\0');
|
||||
if (WideCharToMultiByte(
|
||||
CP_UTF8, WC_ERR_INVALID_CHARS, text, -1,
|
||||
result.data(), bytes, nullptr, nullptr) != bytes) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
result.pop_back();
|
||||
return result;
|
||||
}
|
||||
|
||||
// main entry point into the DLL
|
||||
// spice executable will call into this shortly after the game is partially
|
||||
// initialized (but not quite fully booted just yet)
|
||||
@@ -42,6 +64,37 @@ spice_sdk_entry_point(
|
||||
|
||||
LOG_INFO("plugin loaded");
|
||||
|
||||
if (spice.get_plugin_directory) {
|
||||
std::array<wchar_t, 32768> directory{};
|
||||
uint32_t size = static_cast<uint32_t>(directory.size());
|
||||
if (spice.get_plugin_directory(&spice, directory.data(), &size) ==
|
||||
SPICE_SDK_STATUS_SUCCESS) {
|
||||
if (const auto path = utf16_to_utf8(directory.data())) {
|
||||
LOG_INFO(std::format("plugin directory: {}", *path).c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (spice.get_module_info) {
|
||||
SPICE_SDK_MODULE_INFO info{};
|
||||
info.size = sizeof(info);
|
||||
if (spice.get_module_info(L"kernel32.dll", &info) == SPICE_SDK_STATUS_SUCCESS) {
|
||||
LOG_INFO(std::format(
|
||||
"kernel32 PE: {:x}_{:x}, base={:x}, size={:x}",
|
||||
info.timestamp, info.entry_point, info.base, info.image_size).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (spice.register_d3d9) {
|
||||
status = sample_imgui::initialize(spice);
|
||||
if (status != SPICE_SDK_STATUS_SUCCESS) {
|
||||
LOG_INFO(std::format(
|
||||
"D3D9 registration failed: {}", static_cast<int>(status)).c_str());
|
||||
} else {
|
||||
LOG_INFO("D3D9 renderer registered; Ctrl+Enter toggles the sample window");
|
||||
}
|
||||
}
|
||||
|
||||
// spin up a worker thread
|
||||
worker_thread = std::jthread(worker_thread_main);
|
||||
return 1;
|
||||
@@ -77,10 +130,18 @@ static ArrowButton arrow_buttons[] = {
|
||||
// worker thread for I/O
|
||||
static void worker_thread_main(std::stop_token stop_token) {
|
||||
bool coin_previous_state[10] = {};
|
||||
bool window_toggle_previous_state = false;
|
||||
while (!stop_token.stop_requested()) {
|
||||
|
||||
// insert coin
|
||||
const bool control_pressed = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
const bool window_toggle_pressed = control_pressed &&
|
||||
((GetAsyncKeyState(VK_RETURN) & 0x8000) != 0);
|
||||
if (window_toggle_pressed && !window_toggle_previous_state) {
|
||||
sample_imgui::toggle();
|
||||
}
|
||||
window_toggle_previous_state = window_toggle_pressed;
|
||||
|
||||
// insert coin
|
||||
for (uint8_t amount = 0; amount < 10; amount++) {
|
||||
const bool coin_pressed = control_pressed &&
|
||||
((GetAsyncKeyState('0' + amount) & 0x8000) != 0);
|
||||
|
||||
Reference in New Issue
Block a user