forked from Dniel97/segatools
Merge pull request 'Include chu2to3 engine' (#1) from CrazyRedMachine/segatools:chuniio into chuniio
Reviewed-on: Dniel97/segatools#1
This commit is contained in:
commit
16bbd87c73
@ -97,11 +97,16 @@ static DWORD CALLBACK chuni_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = led15093_hook_init(&chuni_hook_cfg.led15093,
|
||||
chuni_dll.led_init, chuni_dll.led_set_leds, 10, 2, 2, 1);
|
||||
if ( chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL )
|
||||
{
|
||||
dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n");
|
||||
} else {
|
||||
hr = led15093_hook_init(&chuni_hook_cfg.led15093,
|
||||
chuni_dll.led_init, chuni_dll.led_set_leds, 10, 2, 2, 1);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&chuni_hook_cfg.aime, 12, 1, chuni_hook_mod);
|
||||
|
357
chuniio/chu2to3.c
Normal file
357
chuniio/chu2to3.c
Normal file
@ -0,0 +1,357 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <process.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "chuniio/chu2to3.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
// Check windows
|
||||
#if _WIN32 || _WIN64
|
||||
#if _WIN64
|
||||
#define ENV64BIT
|
||||
#else
|
||||
#define ENV32BIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Check GCC
|
||||
#if __GNUC__
|
||||
#if __x86_64__ || __ppc64__
|
||||
#define ENV64BIT
|
||||
#else
|
||||
#define ENV32BIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* chuniio.dll dynamic loading */
|
||||
HMODULE hinstLib;
|
||||
typedef uint16_t (*chuni_io_get_api_version_t)(void);
|
||||
typedef HRESULT (*chuni_io_jvs_init_t)(void);
|
||||
typedef void (*chuni_io_jvs_poll_t)(uint8_t*, uint8_t*);
|
||||
typedef void (*chuni_io_jvs_read_coin_counter_t)(uint16_t *);
|
||||
typedef HRESULT (*chuni_io_slider_init_t)(void);
|
||||
typedef void (*chuni_io_slider_set_leds_t)(const uint8_t *);
|
||||
typedef void (*chuni_io_slider_start_t)(chuni_io_slider_callback_t);
|
||||
typedef void (*chuni_io_slider_stop_t)(void);
|
||||
typedef HRESULT (*chuni_io_led_init_t)(void);
|
||||
typedef void (*chuni_io_led_set_colors_t)(uint8_t, uint8_t *);
|
||||
|
||||
chuni_io_get_api_version_t _chuni_io_get_api_version;
|
||||
chuni_io_jvs_init_t _chuni_io_jvs_init;
|
||||
chuni_io_jvs_poll_t _chuni_io_jvs_poll;
|
||||
chuni_io_jvs_read_coin_counter_t _chuni_io_jvs_read_coin_counter;
|
||||
chuni_io_slider_init_t _chuni_io_slider_init;
|
||||
chuni_io_slider_set_leds_t _chuni_io_slider_set_leds;
|
||||
chuni_io_slider_start_t _chuni_io_slider_start;
|
||||
chuni_io_slider_stop_t _chuni_io_slider_stop;
|
||||
chuni_io_led_init_t _chuni_io_led_init;
|
||||
chuni_io_led_set_colors_t _chuni_io_led_set_colors;
|
||||
|
||||
/* SHMEM Handling */
|
||||
#define BUF_SIZE 1024
|
||||
#define SHMEM_WRITE(buf, size) CopyMemory((PVOID)g_pBuf, buf, size)
|
||||
#define SHMEM_READ(buf, size) CopyMemory(buf,(PVOID)g_pBuf, size)
|
||||
TCHAR g_shmem_name[]=TEXT("Local\\Chu2to3Shmem");
|
||||
HANDLE g_hMapFile;
|
||||
LPVOID g_pBuf;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct shared_data_s {
|
||||
uint16_t coin_counter;
|
||||
uint8_t opbtn;
|
||||
uint8_t beams;
|
||||
uint16_t version;
|
||||
} shared_data_t;
|
||||
|
||||
shared_data_t g_shared_data;
|
||||
|
||||
bool shmem_create()
|
||||
{
|
||||
g_hMapFile = CreateFileMapping(
|
||||
INVALID_HANDLE_VALUE, // use paging file
|
||||
NULL, // default security
|
||||
PAGE_READWRITE, // read/write access
|
||||
0, // maximum object size (high-order DWORD)
|
||||
BUF_SIZE, // maximum object size (low-order DWORD)
|
||||
g_shmem_name); // name of mapping object
|
||||
|
||||
if (g_hMapFile == NULL)
|
||||
{
|
||||
dprintf("shmem_create : Could not create file mapping object (%d).\n",
|
||||
GetLastError());
|
||||
return 0;
|
||||
}
|
||||
g_pBuf = MapViewOfFile(g_hMapFile, // handle to map object
|
||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||
0,
|
||||
0,
|
||||
BUF_SIZE);
|
||||
|
||||
if (g_pBuf == NULL)
|
||||
{
|
||||
dprintf("shmem_create : Could not map view of file (%d).\n",
|
||||
GetLastError());
|
||||
|
||||
CloseHandle(g_hMapFile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool shmem_load()
|
||||
{
|
||||
g_hMapFile = OpenFileMapping(
|
||||
FILE_MAP_ALL_ACCESS, // read/write access
|
||||
FALSE, // do not inherit the name
|
||||
g_shmem_name); // name of mapping object
|
||||
|
||||
if (g_hMapFile == NULL)
|
||||
{
|
||||
dprintf("shmem_load : Could not open file mapping object (%d).\n", GetLastError());
|
||||
return 0;
|
||||
}
|
||||
|
||||
g_pBuf = MapViewOfFile(g_hMapFile, // handle to map object
|
||||
FILE_MAP_ALL_ACCESS, // read/write permission
|
||||
0,
|
||||
0,
|
||||
BUF_SIZE);
|
||||
|
||||
if (g_pBuf == NULL)
|
||||
{
|
||||
dprintf("shmem_load : Could not map view of file (%d).\n", GetLastError());
|
||||
CloseHandle(g_hMapFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dprintf("shmem_load : shmem loaded succesfully.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
void shmem_free()
|
||||
{
|
||||
UnmapViewOfFile(g_pBuf);
|
||||
CloseHandle(g_hMapFile);
|
||||
}
|
||||
|
||||
/* jvs polling thread (to forward info to x64 dll) */
|
||||
static HANDLE jvs_poll_thread;
|
||||
static bool jvs_poll_stop_flag;
|
||||
|
||||
static unsigned int __stdcall jvs_poll_thread_proc(void *ctx)
|
||||
{
|
||||
while (1) {
|
||||
_chuni_io_jvs_read_coin_counter(&g_shared_data.coin_counter);
|
||||
g_shared_data.opbtn = 0;
|
||||
_chuni_io_jvs_poll(&g_shared_data.opbtn, &g_shared_data.beams);
|
||||
SHMEM_WRITE(&g_shared_data, sizeof(shared_data_t));
|
||||
Sleep(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t chu2to3_load_dll(wchar_t *dllname)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x64 must just open the shmem and do nothing else */
|
||||
int errcount = 0;
|
||||
while (!shmem_load())
|
||||
{
|
||||
if (errcount >= 10)
|
||||
return -1;
|
||||
Sleep(5000);
|
||||
errcount++;
|
||||
}
|
||||
Sleep(1000);
|
||||
return S_OK;
|
||||
#endif
|
||||
|
||||
/* this is the first function called so let's setup the chuniio forwarding */
|
||||
hinstLib = LoadLibraryW(dllname);
|
||||
if (hinstLib == NULL) {
|
||||
dprintf("ERROR: unable to load %S (error %d)\n",dllname, GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
_chuni_io_get_api_version = (chuni_io_get_api_version_t)GetProcAddress(hinstLib, "chuni_io_get_api_version");
|
||||
_chuni_io_jvs_init = (chuni_io_jvs_init_t)GetProcAddress(hinstLib, "chuni_io_jvs_init");
|
||||
_chuni_io_jvs_poll = (chuni_io_jvs_poll_t)GetProcAddress(hinstLib, "chuni_io_jvs_poll");
|
||||
_chuni_io_jvs_read_coin_counter = (chuni_io_jvs_read_coin_counter_t)GetProcAddress(hinstLib, "chuni_io_jvs_read_coin_counter");
|
||||
_chuni_io_slider_init = (chuni_io_slider_init_t)GetProcAddress(hinstLib, "chuni_io_slider_init");
|
||||
_chuni_io_slider_set_leds = (chuni_io_slider_set_leds_t)GetProcAddress(hinstLib, "chuni_io_slider_set_leds");
|
||||
_chuni_io_slider_start = (chuni_io_slider_start_t)GetProcAddress(hinstLib, "chuni_io_slider_start");
|
||||
_chuni_io_slider_stop = (chuni_io_slider_stop_t)GetProcAddress(hinstLib, "chuni_io_slider_stop");
|
||||
_chuni_io_led_init = (chuni_io_led_init_t)GetProcAddress(hinstLib, "chuni_io_led_init");
|
||||
_chuni_io_led_set_colors = (chuni_io_led_set_colors_t)GetProcAddress(hinstLib, "chuni_io_led_set_colors");
|
||||
|
||||
/* x86 has to create the shmem */
|
||||
if (!shmem_create())
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* chuniio exports */
|
||||
uint16_t chu2to3_io_get_api_version(void)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* This might be called too soon so let's make sure x86 has time to write to the shmem */
|
||||
SHMEM_READ(&g_shared_data, sizeof(shared_data_t));
|
||||
int errcount = 0;
|
||||
while (g_shared_data.version == 0)
|
||||
{
|
||||
if (errcount >= 3)
|
||||
{
|
||||
dprintf("CHU2TO3 X64: Couldn't retrieve api version from shmem, assuming 0x0100\n");
|
||||
return 0x0100;
|
||||
}
|
||||
Sleep(5000);
|
||||
errcount++;
|
||||
SHMEM_READ(&g_shared_data, sizeof(shared_data_t));
|
||||
}
|
||||
dprintf("CHU2TO3 X64: api version is %04X\n", g_shared_data.version);
|
||||
return g_shared_data.version;
|
||||
#endif
|
||||
|
||||
if ( _chuni_io_get_api_version == NULL )
|
||||
{
|
||||
g_shared_data.version = 0x0100;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_shared_data.version = _chuni_io_get_api_version();
|
||||
}
|
||||
dprintf("CHU2TO3: api version is %04X\n", g_shared_data.version);
|
||||
|
||||
SHMEM_WRITE(&g_shared_data, sizeof(shared_data_t));
|
||||
|
||||
return g_shared_data.version;
|
||||
}
|
||||
|
||||
HRESULT chu2to3_io_jvs_init(void)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return S_OK;
|
||||
#endif
|
||||
|
||||
_chuni_io_jvs_init();
|
||||
|
||||
/* start jvs poll thread now that jvs_init is done */
|
||||
if (jvs_poll_thread != NULL) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
jvs_poll_thread = (HANDLE) _beginthreadex(NULL,
|
||||
0,
|
||||
jvs_poll_thread_proc,
|
||||
NULL,
|
||||
0,
|
||||
NULL);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void chu2to3_io_jvs_read_coin_counter(uint16_t *out)
|
||||
{
|
||||
#if defined(ENV32BIT)
|
||||
/* x86 can perform the call and update shmem (although this call never happens) */
|
||||
_chuni_io_jvs_read_coin_counter(&g_shared_data.coin_counter);
|
||||
SHMEM_WRITE(&g_shared_data, sizeof(shared_data_t));
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* x64 must read value from shmem and update arg */
|
||||
SHMEM_READ(&g_shared_data, sizeof(shared_data_t));
|
||||
if (out == NULL) {
|
||||
return;
|
||||
}
|
||||
*out = g_shared_data.coin_counter;
|
||||
}
|
||||
|
||||
void chu2to3_io_jvs_poll(uint8_t *opbtn, uint8_t *beams)
|
||||
{
|
||||
#if defined(ENV32BIT)
|
||||
/* x86 can perform the call and update shmem (although this call never happens) */
|
||||
_chuni_io_jvs_poll(&g_shared_data.opbtn, &g_shared_data.beams);
|
||||
SHMEM_WRITE(&g_shared_data, sizeof(shared_data_t));
|
||||
return;
|
||||
#endif
|
||||
|
||||
/* x64 must read value from shmem and update args */
|
||||
SHMEM_READ(&g_shared_data, sizeof(shared_data_t));
|
||||
*opbtn = g_shared_data.opbtn;
|
||||
*beams = g_shared_data.beams;
|
||||
}
|
||||
|
||||
HRESULT chu2to3_io_slider_init(void)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return S_OK;
|
||||
#endif
|
||||
|
||||
return _chuni_io_slider_init();
|
||||
}
|
||||
|
||||
void chu2to3_io_slider_start(chuni_io_slider_callback_t callback)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return;
|
||||
#endif
|
||||
|
||||
_chuni_io_slider_start(callback);
|
||||
}
|
||||
|
||||
void chu2to3_io_slider_stop(void)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return;
|
||||
#endif
|
||||
|
||||
_chuni_io_slider_stop();
|
||||
}
|
||||
|
||||
void chu2to3_io_slider_set_leds(const uint8_t *rgb)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return;
|
||||
#endif
|
||||
|
||||
_chuni_io_slider_set_leds(rgb);
|
||||
}
|
||||
|
||||
HRESULT chu2to3_io_led_init(void)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return S_OK;
|
||||
#endif
|
||||
|
||||
if (_chuni_io_led_init != NULL)
|
||||
return _chuni_io_led_init();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void chu2to3_io_led_set_colors(uint8_t board, uint8_t *rgb)
|
||||
{
|
||||
#if defined(ENV64BIT)
|
||||
/* x86 only */
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (_chuni_io_led_set_colors != NULL)
|
||||
{
|
||||
_chuni_io_led_set_colors(board, rgb);
|
||||
}
|
||||
}
|
26
chuniio/chu2to3.h
Normal file
26
chuniio/chu2to3.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
CHU2TO3 CUSTOM IO API
|
||||
|
||||
This dll just mirrors chuniio dll binds but with a dynamic library loading and
|
||||
a SHMEM system to let a single 32bit dll talk with x86 and x64 processes at once
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint16_t chu2to3_io_get_api_version(void);
|
||||
HRESULT chu2to3_io_jvs_init(void);
|
||||
void chu2to3_io_jvs_poll(uint8_t *opbtn, uint8_t *beams);
|
||||
void chu2to3_io_jvs_read_coin_counter(uint16_t *total);
|
||||
HRESULT chu2to3_io_slider_init(void);
|
||||
typedef void (*chuni_io_slider_callback_t)(const uint8_t *state);
|
||||
void chu2to3_io_slider_start(chuni_io_slider_callback_t callback);
|
||||
void chu2to3_io_slider_stop(void);
|
||||
void chu2to3_io_slider_set_leds(const uint8_t *rgb);
|
||||
HRESULT chu2to3_io_led_init(void);
|
||||
void chu2to3_io_led_set_colors(uint8_t board, uint8_t *rgb);
|
||||
uint16_t chu2to3_load_dll(wchar_t *dllname);
|
@ -8,6 +8,7 @@
|
||||
- 0x0100: Initial API version (assumed if chuni_io_get_api_version is not
|
||||
exported)
|
||||
- 0x0101: Fix IR beam mappings
|
||||
- 0x0102: Add air tower led and billboard support
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
@ -151,15 +152,24 @@ void chuni_io_slider_set_leds(const uint8_t *rgb);
|
||||
|
||||
All subsequent calls may originate from arbitrary threads and some may
|
||||
overlap with each other. Ensuring synchronization inside your IO DLL is
|
||||
your responsibility. */
|
||||
your responsibility.
|
||||
|
||||
Minimum API version: 0x0102 */
|
||||
|
||||
HRESULT chuni_io_led_init(void);
|
||||
|
||||
/* Update the RGB LEDs. rgb is a pointer to an array of 66 * 3 = 198
|
||||
bytes. The majority of these are for the marquee display, but the final
|
||||
LEDs are for the side partitions.
|
||||
/* Update the RGB LEDs. rgb is a pointer to an array of up to 63 * 3 = 189 bytes.
|
||||
|
||||
Chunithm uses two chains/boards. One is on the left side and one on the
|
||||
right side of the cab. Exact layout is TBD. */
|
||||
Chunithm uses two chains/boards with WS2811 protocol (each logical led corresponds to 3 physical leds).
|
||||
board 0 is on the left side and board 1 on the right side of the cab
|
||||
|
||||
left side has 5*10 rgb values for the billboard, followed by 3 rgb values for the air tower
|
||||
right side has 6*10 rgb values for the billboard, followed by 3 rgb values for the air tower
|
||||
|
||||
Each rgb value is comprised of 3 bytes in R,G,B order
|
||||
|
||||
NOTE: billboard strips have alternating direction (bottom to top, top to bottom, ...)
|
||||
|
||||
Minimum API version: 0x0102 */
|
||||
|
||||
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb);
|
||||
|
@ -5,6 +5,8 @@ chuniio_lib = static_library(
|
||||
implicit_include_directories : false,
|
||||
c_pch : '../precompiled.h',
|
||||
sources : [
|
||||
'chu2to3.c',
|
||||
'chu2to3.h',
|
||||
'chuniio.c',
|
||||
'chuniio.h',
|
||||
'config.c',
|
||||
|
@ -39,6 +39,50 @@ const struct dll_bind_sym chuni_dll_syms[] = {
|
||||
}
|
||||
};
|
||||
|
||||
const struct dll_bind_sym chu2to3_dll_syms[] = {
|
||||
{
|
||||
.sym = "chu2to3_io_jvs_init",
|
||||
.off = offsetof(struct chuni_dll, jvs_init),
|
||||
}, {
|
||||
.sym = "chu2to3_io_jvs_poll",
|
||||
.off = offsetof(struct chuni_dll, jvs_poll),
|
||||
}, {
|
||||
.sym = "chu2to3_io_jvs_read_coin_counter",
|
||||
.off = offsetof(struct chuni_dll, jvs_read_coin_counter),
|
||||
}, {
|
||||
.sym = "chu2to3_io_slider_init",
|
||||
.off = offsetof(struct chuni_dll, slider_init),
|
||||
}, {
|
||||
.sym = "chu2to3_io_slider_start",
|
||||
.off = offsetof(struct chuni_dll, slider_start),
|
||||
}, {
|
||||
.sym = "chu2to3_io_slider_stop",
|
||||
.off = offsetof(struct chuni_dll, slider_stop),
|
||||
}, {
|
||||
.sym = "chu2to3_io_slider_set_leds",
|
||||
.off = offsetof(struct chuni_dll, slider_set_leds),
|
||||
}, {
|
||||
.sym = "chu2to3_io_led_init",
|
||||
.off = offsetof(struct chuni_dll, led_init),
|
||||
}, {
|
||||
.sym = "chu2to3_io_led_set_colors",
|
||||
.off = offsetof(struct chuni_dll, led_set_leds),
|
||||
}
|
||||
};
|
||||
|
||||
/* Helper function to determine upon dll_bind failure whether the required functions were found
|
||||
NOTE: relies on symbols order declared above */
|
||||
static HRESULT has_enough_symbols(uint16_t version, uint8_t count)
|
||||
{
|
||||
if ( version <= 0x0101 && count == 7 )
|
||||
return S_OK;
|
||||
|
||||
if ( version >= 0x0102 && count == 9 )
|
||||
return S_OK;
|
||||
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
struct chuni_dll chuni_dll;
|
||||
|
||||
// Copypasta DLL binding and diagnostic message boilerplate.
|
||||
@ -58,7 +102,12 @@ HRESULT chuni_dll_init(const struct chuni_dll_config *cfg, HINSTANCE self)
|
||||
assert(cfg != NULL);
|
||||
assert(self != NULL);
|
||||
|
||||
if (cfg->path[0] != L'\0') {
|
||||
owned = NULL;
|
||||
src = self;
|
||||
|
||||
if (cfg->chu2to3) {
|
||||
dprintf("Chunithm IO: using chu2to3 engine for IO DLL: %S\n", cfg->path);
|
||||
} else if (cfg->path[0] != L'\0') {
|
||||
owned = LoadLibraryW(cfg->path);
|
||||
|
||||
if (owned == NULL) {
|
||||
@ -72,12 +121,18 @@ HRESULT chuni_dll_init(const struct chuni_dll_config *cfg, HINSTANCE self)
|
||||
|
||||
dprintf("Chunithm IO: Using custom IO DLL: %S\n", cfg->path);
|
||||
src = owned;
|
||||
} else {
|
||||
owned = NULL;
|
||||
src = self;
|
||||
}
|
||||
|
||||
get_api_version = (void *) GetProcAddress(src, "chuni_io_get_api_version");
|
||||
if (cfg->chu2to3) {
|
||||
if (chu2to3_load_dll(cfg->path) != 0)
|
||||
dprintf("Could not init chu2to3 engine\n");
|
||||
|
||||
get_api_version = (void *) GetProcAddress(src, "chu2to3_io_get_api_version");
|
||||
}
|
||||
else
|
||||
{
|
||||
get_api_version = (void *) GetProcAddress(src, "chuni_io_get_api_version");
|
||||
}
|
||||
|
||||
if (get_api_version != NULL) {
|
||||
chuni_dll.api_version = get_api_version();
|
||||
@ -97,17 +152,26 @@ HRESULT chuni_dll_init(const struct chuni_dll_config *cfg, HINSTANCE self)
|
||||
goto end;
|
||||
}
|
||||
|
||||
sym = chuni_dll_syms;
|
||||
sym = cfg->chu2to3 ? chu2to3_dll_syms : chuni_dll_syms;
|
||||
const struct dll_bind_sym *init_sym = &sym[0];
|
||||
|
||||
hr = dll_bind(&chuni_dll, src, &sym, _countof(chuni_dll_syms));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (src != self) {
|
||||
dprintf("Chunithm IO: Custom IO DLL does not provide function "
|
||||
"\"%s\". Please contact your IO DLL's developer for "
|
||||
"further assistance.\n",
|
||||
sym->sym);
|
||||
|
||||
goto end;
|
||||
// Might still be ok depending on external dll API version
|
||||
int bind_count = sym - init_sym;
|
||||
if ( has_enough_symbols(chuni_dll.api_version, bind_count) == S_OK )
|
||||
{
|
||||
hr = S_OK;
|
||||
} else {
|
||||
dprintf("Chunithm IO: Custom IO DLL does not provide function "
|
||||
"\"%s\". Please contact your IO DLL's developer for "
|
||||
"further assistance.\n",
|
||||
sym->sym);
|
||||
dprintf("imported %d symbols\n",bind_count);
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ struct chuni_dll {
|
||||
|
||||
struct chuni_dll_config {
|
||||
wchar_t path[MAX_PATH];
|
||||
uint8_t chu2to3;
|
||||
};
|
||||
|
||||
extern struct chuni_dll chuni_dll;
|
||||
|
@ -22,3 +22,13 @@ EXPORTS
|
||||
chuni_io_slider_stop
|
||||
chuni_io_led_init
|
||||
chuni_io_led_set_colors
|
||||
chu2to3_io_get_api_version
|
||||
chu2to3_io_jvs_init
|
||||
chu2to3_io_jvs_poll
|
||||
chu2to3_io_jvs_read_coin_counter
|
||||
chu2to3_io_slider_init
|
||||
chu2to3_io_slider_set_leds
|
||||
chu2to3_io_slider_start
|
||||
chu2to3_io_slider_stop
|
||||
chu2to3_io_led_init
|
||||
chu2to3_io_led_set_colors
|
||||
|
@ -39,16 +39,27 @@ void chuni_dll_config_load(
|
||||
|
||||
// Workaround for x64/x86 external IO dlls
|
||||
// path32 for 32bit, path64 for 64bit
|
||||
// for else.. is that possible? idk
|
||||
// path for 32bit only dlls (internal chu2to3 engine)
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"chuniio",
|
||||
L"path",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
if (cfg->path[0] != L'\0') {
|
||||
cfg->chu2to3 = 1;
|
||||
} else {
|
||||
cfg->chu2to3 = 0;
|
||||
#if defined(ENV32BIT)
|
||||
GetPrivateProfileStringW(
|
||||
L"chuniio",
|
||||
L"path32",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
GetPrivateProfileStringW(
|
||||
L"chuniio",
|
||||
L"path32",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
#elif defined(ENV64BIT)
|
||||
GetPrivateProfileStringW(
|
||||
L"chuniio",
|
||||
@ -60,7 +71,7 @@ void chuni_dll_config_load(
|
||||
#else
|
||||
#error "Unknown environment"
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void slider_config_load(struct slider_config *cfg, const wchar_t *filename)
|
||||
|
@ -129,11 +129,16 @@ static DWORD CALLBACK chusan_pre_startup(void)
|
||||
}
|
||||
}
|
||||
|
||||
hr = led15093_hook_init(&chusan_hook_cfg.led15093,
|
||||
chuni_dll.led_init, chuni_dll.led_set_leds, first_port, 2, 2, 1);
|
||||
if ( chuni_dll.led_init == NULL || chuni_dll.led_set_leds == NULL )
|
||||
{
|
||||
dprintf("IO DLL doesn't support led_init/led_set_leds, cannot start LED15093 hook\n");
|
||||
} else {
|
||||
hr = led15093_hook_init(&chusan_hook_cfg.led15093,
|
||||
chuni_dll.led_init, chuni_dll.led_set_leds, first_port, 2, 2, 1);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&chusan_hook_cfg.aime, 4, is_cvt ? 2: 3, chusan_hook_mod);
|
||||
|
6
dist/chusan/segatools.ini
vendored
6
dist/chusan/segatools.ini
vendored
@ -64,7 +64,11 @@ framed=0
|
||||
monitor=0
|
||||
|
||||
[chuniio]
|
||||
; Uncomment this if you have custom chuniio implementation.
|
||||
; Uncomment this if you have custom chuniio implementation comprised of a single 32bit DLL.
|
||||
; (will use chu2to3 engine internally)
|
||||
;path=
|
||||
|
||||
; Uncomment both of these if you have custom chuniio implementation comprised of two DLLs.
|
||||
; x86 chuniio to path32, x64 to path64. Both are necessary.
|
||||
;path32=
|
||||
;path64=
|
||||
|
Loading…
Reference in New Issue
Block a user