mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-02 06:40:42 -07:00
sdk: introduce Spice SDK (#676)
## 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.
This commit is contained in:
@@ -0,0 +1,273 @@
|
||||
#pragma once
|
||||
#ifndef SPICE_SDK_H
|
||||
#define SPICE_SDK_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define SPICE_SDK_ENTRY_POINT extern "C" __declspec(dllexport) int __cdecl
|
||||
#else
|
||||
#define SPICE_SDK_ENTRY_POINT __declspec(dllexport) int __cdecl
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum SPICE_SDK_STATUS_CODE {
|
||||
SPICE_SDK_STATUS_SUCCESS = 0,
|
||||
|
||||
// 000: generic
|
||||
SPICE_SDK_STATUS_GENERIC_ERROR = 1,
|
||||
SPICE_SDK_STATUS_NOT_INITIALIZED = 2,
|
||||
SPICE_SDK_STATUS_NOT_SUPPORTED = 3,
|
||||
SPICE_SDK_STATUS_TOO_SMALL = 4,
|
||||
SPICE_SDK_STATUS_TOO_LATE = 5,
|
||||
|
||||
// 1000: invalid args
|
||||
SPICE_SDK_STATUS_INVALID_ARGUMENT_1 = 1001,
|
||||
SPICE_SDK_STATUS_INVALID_ARGUMENT_2 = 1002,
|
||||
SPICE_SDK_STATUS_INVALID_ARGUMENT_3 = 1003,
|
||||
SPICE_SDK_STATUS_INVALID_ARGUMENT_4 = 1004,
|
||||
SPICE_SDK_STATUS_INVALID_ARGUMENT_5 = 1005,
|
||||
|
||||
} SPICE_SDK_STATUS_CODE;
|
||||
|
||||
typedef enum SPICE_SDK_LOG_LEVEL {
|
||||
SPICE_SDK_LOG_LEVEL_MISC = 0,
|
||||
SPICE_SDK_LOG_LEVEL_INFO = 1,
|
||||
SPICE_SDK_LOG_LEVEL_WARNING = 2,
|
||||
SPICE_SDK_LOG_LEVEL_FATAL = 3,
|
||||
} SPICE_SDK_LOG_LEVEL;
|
||||
|
||||
typedef struct SPICE_SDK_TOUCH_POINT {
|
||||
uint32_t id;
|
||||
int x;
|
||||
int y;
|
||||
} SPICE_SDK_TOUCH_POINT;
|
||||
|
||||
typedef struct SPICE_SDK_GAME_INFO {
|
||||
char name[64]; // null-terminated
|
||||
} SPICE_SDK_GAME_INFO;
|
||||
|
||||
typedef struct SPICE_SDK_AVS_INFO {
|
||||
char model[4]; // "MDX", null-terminated
|
||||
char dest; // J
|
||||
char spec; // A
|
||||
char rev; // A
|
||||
char ext[11]; // "2025061002", null-terminated
|
||||
} SPICE_SDK_AVS_INFO;
|
||||
|
||||
// get_game_info (v0.1 and up)
|
||||
//
|
||||
// get info about the currently running game
|
||||
//
|
||||
// info: receives game info
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_get_game_info_func)(
|
||||
SPICE_SDK_GAME_INFO *info
|
||||
);
|
||||
|
||||
// get_avs_info (v0.1 and up)
|
||||
//
|
||||
// get AVS info (model, dest, spec, rev, ext)
|
||||
//
|
||||
// info: receives AVS info
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_get_avs_info_func)(
|
||||
SPICE_SDK_AVS_INFO *info
|
||||
);
|
||||
|
||||
// log (v0.1 and up)
|
||||
// logs a message to the log
|
||||
// writing a FATAL message will terminate spice, only use in catastrophic failure
|
||||
//
|
||||
// level: see log level enum
|
||||
// module: short string that identifies the facility / module / submodule
|
||||
// message: the message to log
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_log_func)(
|
||||
SPICE_SDK_LOG_LEVEL level,
|
||||
const char *module,
|
||||
const char *message
|
||||
);
|
||||
|
||||
// get_button (v0.1 and up)
|
||||
// gets the button state
|
||||
//
|
||||
// button_id: ID of the button; see spicesdk_io.h for named values
|
||||
// pressed: (optional) is the button pressed?
|
||||
// velocity: (optional) MIDI velocity of the button
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_get_button_func)(
|
||||
uint32_t button_id,
|
||||
bool *pressed,
|
||||
float *velocity
|
||||
);
|
||||
|
||||
// set_button (v0.1 and up)
|
||||
// sets or clears the button override
|
||||
//
|
||||
// make sure to hold the button long enough for the game's I/O engine to pick up
|
||||
// usually, one or two frames
|
||||
//
|
||||
// button_id: ID of the button; see spicesdk_io.h for named values
|
||||
// pressed: true to set the button override (permanently set the button to be ON until cleared),
|
||||
// false to clear the override (allow user's controller to provide input again)
|
||||
// velocity: MIDI velocity of the button; only valid when pressed is true
|
||||
// can be between 0.0 and 1.0, inclusive
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_set_button_func)(
|
||||
uint32_t button_id,
|
||||
bool pressed,
|
||||
float velocity
|
||||
);
|
||||
|
||||
// get_analog (v0.1 and up)
|
||||
// gets the analog state
|
||||
//
|
||||
// button_id: ID of the button; see spicesdk_io.h for named values
|
||||
// value: receives the state of the analog
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_get_analog_func)(
|
||||
uint32_t analog_id,
|
||||
float *value
|
||||
);
|
||||
|
||||
// set_analog (v0.1 and up)
|
||||
// sets or clears the analog override
|
||||
//
|
||||
// analog_id: ID of the analog; see spicesdk_io.h for named values
|
||||
// override_active: true to set override (gain exclusive control)
|
||||
// false to clear it (allow user's controller provide input again)
|
||||
// value: value of the analog; only valid when override_active is true
|
||||
// can be between 0.0 and 1.0, inclusive
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_set_analog_func)(
|
||||
uint32_t analog_id,
|
||||
bool override_active,
|
||||
float value
|
||||
);
|
||||
|
||||
// get_light (v0.1 and up)
|
||||
// gets the last observed value of a light
|
||||
//
|
||||
// light_id: ID of the light; see spicesdk_io.h for named values
|
||||
// value: output parameter for the light value; 0.0 to 1.0
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_get_light_func)(
|
||||
uint32_t light_id,
|
||||
float *value
|
||||
);
|
||||
|
||||
// set_light (v0.1 and up)
|
||||
// sets or clears the light override
|
||||
//
|
||||
// light_id: ID of the light; see spicesdk_io.h for named values
|
||||
// light_value: output parameter for the light value; 0.0 to 1.0
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_set_light_func)(
|
||||
uint32_t light_id,
|
||||
bool override_active,
|
||||
float light_value
|
||||
);
|
||||
|
||||
// set_touch (v0.1 and up)
|
||||
// adds or updates touch points
|
||||
//
|
||||
// points: array of touch points to add or update
|
||||
// count: number of touch points in the array
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_set_touch_func)(
|
||||
const SPICE_SDK_TOUCH_POINT *points,
|
||||
uint32_t count
|
||||
);
|
||||
|
||||
// clear_touch (v0.1 and up)
|
||||
// clears touch points (i.e., no longer being touched)
|
||||
//
|
||||
// ids: array of touch point IDs to clear
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_clear_touch_func)(
|
||||
const uint32_t *ids,
|
||||
uint32_t count
|
||||
);
|
||||
|
||||
// insert_card (v0.1 and up)
|
||||
// simulates inserting an e-amuse card with the given ID
|
||||
//
|
||||
// unit: 0 for player 1, 1 for player 2
|
||||
// card_id: null-terminated string of the card ID
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_insert_card_func)(
|
||||
uint8_t unit,
|
||||
const char *card_id
|
||||
);
|
||||
|
||||
// set_keypad (v0.1 and up)
|
||||
// sets keypad state
|
||||
//
|
||||
// make sure to hold the button long enough for the game to pick up
|
||||
// 70ms is usually sufficient, except for DDR which needs 150ms
|
||||
//
|
||||
// unit: 0 for player 1, 1 for player 2
|
||||
// key: '0' to '9' for numbers, 'A' for 00, 'D' for decimal point, 0 or '\0' to release all keys
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_set_keypad_func)(
|
||||
uint8_t unit,
|
||||
char key
|
||||
);
|
||||
|
||||
typedef struct SPICE_SDK_V0 {
|
||||
uint32_t size;
|
||||
|
||||
spice_sdk_log_func *log;
|
||||
|
||||
spice_sdk_get_game_info_func *get_game_info;
|
||||
spice_sdk_get_avs_info_func *get_avs_info;
|
||||
|
||||
spice_sdk_get_button_func *get_button;
|
||||
spice_sdk_set_button_func *set_button;
|
||||
|
||||
spice_sdk_get_analog_func *get_analog;
|
||||
spice_sdk_set_analog_func *set_analog;
|
||||
|
||||
spice_sdk_get_light_func *get_light;
|
||||
spice_sdk_set_light_func *set_light;
|
||||
|
||||
spice_sdk_set_touch_func *set_touch;
|
||||
spice_sdk_clear_touch_func *clear_touch;
|
||||
|
||||
spice_sdk_insert_card_func *insert_card;
|
||||
spice_sdk_set_keypad_func *set_keypad;
|
||||
|
||||
} SPICE_SDK_V0;
|
||||
|
||||
typedef void (__cdecl spice_sdk_destroy_callback_func)(
|
||||
void
|
||||
);
|
||||
|
||||
// init (v0.1 and up)
|
||||
//
|
||||
// version: supply 0
|
||||
// destroy_callback: supply a function pointer that will be called when spice
|
||||
// is shutting down
|
||||
// sdk_functions: supply a pointer to SPICE_SDK_V0; ensure size field is initialized
|
||||
// to sizeof(SPICE_SDK_V0) before calling this function
|
||||
|
||||
typedef SPICE_SDK_STATUS_CODE (__cdecl spice_sdk_init_func)(
|
||||
uint32_t version,
|
||||
spice_sdk_destroy_callback_func *destroy_callback,
|
||||
void *sdk_functions
|
||||
);
|
||||
|
||||
typedef int (__cdecl spice_sdk_entry_point_func)(
|
||||
spice_sdk_init_func *init
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // SPICE_SDK_H
|
||||
Reference in New Issue
Block a user