mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 22:30:42 -07:00
cd0ba51b5a
## Link to GitHub Issue or related Pull Request, if one exists
n/a
## Description of change
Adds a flat-C, headers-only library for writing DLL plugins with spice.
This is meant to be an alternative to writing applications over spice
API which doesn't suit some scenarios like writing custom
high-performance I/O modules.
All you have to do is:
1. Create a 32-bit or 64-bit DLL with `spice_sdk_entry_point` as a
DLLExport
1. Include `spicesdk.h`, and optionally `spicesdk_io.h` (see
`extras\sdk\include`)
1. `spice_sdk_entry_point` will be called when hooks get initialized.
Call `init` with valid parameters.
1. When `init` returns, `SPICE_SDK_V0` will be filled out with a series
of function pointers; your DLL can now start calling into it.
1. Compile your DLL and add it as a DLL hook (`-k`) in spice when
launching the game.
See `v0_cpp.cpp` for an example.
V0 implements the following functions:
```
log;
get_game_info;
get_avs_info;
get_button;
set_button;
get_analog;
set_analog;
get_light;
set_light;
set_touch;
clear_touch;
insert_card;
set_keypad;
```
V0 is focused on providing common utility functions needed in a lot of
DLL hooks (get AVS info, log messages to file), and implementing I/O.
In the future, we could have more interesting things like:
* scanning and modifying memory
* installing DLL hooks
* having direct hooks into I/O emulation modules
* getting full tape LEDs
* having a callback into DX9 `Present` call
* drawing an ImGui window
More detailed documentation is coming soon in form of a wiki page.
## Testing
See included sample DLL.
58 lines
1.3 KiB
C++
58 lines
1.3 KiB
C++
#include <chrono>
|
|
#include <thread>
|
|
|
|
#include "sdk/include/spicesdk.h"
|
|
#include "sdk/include/spicesdk_io.h"
|
|
|
|
#define LOG_INFO(message) spice.log(SPICE_SDK_LOG_LEVEL_INFO, "sample_v0_cpp", message)
|
|
|
|
static SPICE_SDK_V0 spice = {};
|
|
static spice_sdk_destroy_callback_func destroy_callback;
|
|
static std::jthread worker_thread;
|
|
|
|
static void worker_thread_main(std::stop_token stop_token) {
|
|
while (!stop_token.stop_requested()) {
|
|
|
|
static bool state = false;
|
|
bool new_state;
|
|
spice.get_button(IIDX_Button_P1_Start, &new_state, nullptr);
|
|
if (!state && new_state) {
|
|
LOG_INFO("user pressed P1 Start button!");
|
|
}
|
|
state = new_state;
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
}
|
|
}
|
|
|
|
SPICE_SDK_ENTRY_POINT
|
|
spice_sdk_entry_point(
|
|
spice_sdk_init_func *init
|
|
)
|
|
{
|
|
SPICE_SDK_STATUS_CODE status;
|
|
|
|
spice.size = sizeof(spice);
|
|
status = init(0, destroy_callback, &spice);
|
|
if (status != SPICE_SDK_STATUS_SUCCESS) {
|
|
return 0;
|
|
}
|
|
|
|
LOG_INFO("plugin loaded");
|
|
worker_thread = std::jthread(worker_thread_main);
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
__cdecl
|
|
destroy_callback(
|
|
void
|
|
)
|
|
{
|
|
LOG_INFO("plugin unloading");
|
|
if (worker_thread.joinable()) {
|
|
worker_thread.request_stop();
|
|
worker_thread.join();
|
|
}
|
|
}
|