forked from Hay1tsme/segatools
Compare commits
7 Commits
2024-05-16
...
2024-06-30
Author | SHA1 | Date | |
---|---|---|---|
965126c68a
|
|||
050951e56f
|
|||
7e5e0f132e
|
|||
4e58d3b9a2
|
|||
b0f307f427
|
|||
7aa996193c | |||
9353c9872f |
81
board/led15070-cmd.h
Normal file
81
board/led15070-cmd.h
Normal file
@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include "board/led15070-frame.h"
|
||||
|
||||
/* Command IDs */
|
||||
|
||||
enum {
|
||||
LED_15070_CMD_RESET = 0x10,
|
||||
LED_15070_CMD_SET_INPUT = 0x28, // No known use case
|
||||
LED_15070_CMD_SET_NORMAL_12BIT = 0x30, // TODO
|
||||
LED_15070_CMD_SET_NORMAL_8BIT = 0x31,
|
||||
LED_15070_CMD_SET_MULTI_FLASH_8BIT = 0x32,
|
||||
LED_15070_CMD_SET_MULTI_FADE_8BIT = 0x33,
|
||||
LED_15070_CMD_SET_PALETTE_7_NORMAL_LED = 0x34, // No known use case
|
||||
LED_15070_CMD_SET_PALETTE_6_FLASH_LED = 0x35, // No known use case
|
||||
LED_15070_CMD_SET_15DC_OUT = 0x36, // No known use case
|
||||
LED_15070_CMD_SET_15GS_OUT = 0x37, // No known use case
|
||||
LED_15070_CMD_SET_PSC_MAX = 0x38, // No known use case
|
||||
LED_15070_CMD_SET_FET_OUTPUT = 0x39,
|
||||
LED_15070_CMD_SET_GS_PALETTE = 0x3A,
|
||||
LED_15070_CMD_DC_UPDATE = 0x3B,
|
||||
LED_15070_CMD_GS_UPDATE = 0x3C,
|
||||
LED_15070_CMD_ROTATE = 0x3E, // No known use case, wtf is this?
|
||||
LED_15070_CMD_SET_DC_DATA = 0x3F,
|
||||
LED_15070_CMD_EEPROM_WRITE = 0x7B,
|
||||
LED_15070_CMD_EEPROM_READ = 0x7C,
|
||||
LED_15070_CMD_ACK_ON = 0x7D,
|
||||
LED_15070_CMD_ACK_OFF = 0x7E,
|
||||
LED_15070_CMD_BOARD_INFO = 0xF0,
|
||||
LED_15070_CMD_BOARD_STATUS = 0xF1,
|
||||
LED_15070_CMD_FW_SUM = 0xF2,
|
||||
LED_15070_CMD_PROTOCOL_VER = 0xF3,
|
||||
LED_15070_CMD_TO_BOOT_MODE = 0xFD,
|
||||
LED_15070_CMD_FW_UPDATE = 0xFE,
|
||||
};
|
||||
|
||||
/* Response codes */
|
||||
|
||||
enum {
|
||||
LED_15070_STATUS_OK = 0x01,
|
||||
LED_15070_STATUS_SUM_ERR = 0x02,
|
||||
LED_15070_STATUS_PARITY_ERR = 0x03,
|
||||
LED_15070_STATUS_FRAMING_ERR = 0x04,
|
||||
LED_15070_STATUS_OVERRUN_ERR = 0x05,
|
||||
LED_15070_STATUS_BUFFER_OVERFLOW = 0x06,
|
||||
};
|
||||
|
||||
enum {
|
||||
LED_15070_REPORT_OK = 0x01,
|
||||
LED_15070_REPORT_WAIT = 0x02,
|
||||
LED_15070_REPORT_ERR1 = 0x03,
|
||||
LED_15070_REPORT_ERR2 = 0x04,
|
||||
};
|
||||
|
||||
/* Request data structures */
|
||||
|
||||
struct led15070_req_any {
|
||||
struct led15070_hdr hdr;
|
||||
uint8_t cmd;
|
||||
uint8_t payload[256];
|
||||
};
|
||||
|
||||
/* Response data structures */
|
||||
|
||||
struct led15070_resp_any {
|
||||
struct led15070_hdr hdr;
|
||||
uint8_t status;
|
||||
uint8_t cmd;
|
||||
uint8_t report;
|
||||
uint8_t data[32];
|
||||
};
|
||||
|
||||
struct led15070_resp_board_info {
|
||||
struct led15070_hdr hdr;
|
||||
uint8_t status;
|
||||
uint8_t cmd;
|
||||
uint8_t report;
|
||||
char board_num[8];
|
||||
uint8_t endcode; // Always 0xFF
|
||||
uint8_t fw_ver;
|
||||
};
|
194
board/led15070-frame.c
Normal file
194
board/led15070-frame.c
Normal file
@ -0,0 +1,194 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "board/led15070-frame.h"
|
||||
|
||||
#include "hook/iobuf.h"
|
||||
|
||||
static void led15070_frame_sync(struct iobuf *src);
|
||||
static HRESULT led15070_frame_accept(const struct iobuf *dest);
|
||||
static HRESULT led15070_frame_encode_byte(struct iobuf *dest, uint8_t byte);
|
||||
|
||||
/* Frame structure:
|
||||
|
||||
[0] Sync byte (0xE0)
|
||||
[1] Destination address
|
||||
[2] Source Address
|
||||
[3] Length of data/payload
|
||||
[4] Data/payload
|
||||
For requests (host to board):
|
||||
[0] Command
|
||||
... Payload
|
||||
For responses (board to host):
|
||||
[0] Status
|
||||
[1] Command
|
||||
[2] Report
|
||||
... Payload
|
||||
[n] Checksum: Sum of all prior bytes (excluding sync byte)
|
||||
|
||||
Byte stuffing:
|
||||
|
||||
0xD0 is an escape byte. Un-escape the subsequent byte by adding 1. */
|
||||
|
||||
static void led15070_frame_sync(struct iobuf *src)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0 ; i < src->pos && src->bytes[i] != 0xE0 ; i++);
|
||||
|
||||
src->pos -= i;
|
||||
memmove(&src->bytes[0], &src->bytes[i], i);
|
||||
}
|
||||
|
||||
static HRESULT led15070_frame_accept(const struct iobuf *dest)
|
||||
{
|
||||
uint8_t checksum;
|
||||
size_t i;
|
||||
|
||||
if (dest->pos < 3 || dest->pos != dest->bytes[3] + 5) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
checksum = 0;
|
||||
|
||||
for (i = 1 ; i < dest->pos - 1 ; i++) {
|
||||
checksum += dest->bytes[i];
|
||||
}
|
||||
|
||||
//dprintf("LED checksum %02x, expected %02x\n", checksum, dest->bytes[dest->pos - 1]);
|
||||
|
||||
if (checksum != dest->bytes[dest->pos - 1]) {
|
||||
return HRESULT_FROM_WIN32(ERROR_CRC);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT led15070_frame_decode(struct iobuf *dest, struct iobuf *src)
|
||||
{
|
||||
uint8_t byte;
|
||||
bool escape;
|
||||
size_t i;
|
||||
HRESULT hr;
|
||||
|
||||
assert(dest != NULL);
|
||||
assert(dest->bytes != NULL || dest->nbytes == 0);
|
||||
assert(dest->pos <= dest->nbytes);
|
||||
assert(src != NULL);
|
||||
assert(src->bytes != NULL || src->nbytes == 0);
|
||||
assert(src->pos <= src->nbytes);
|
||||
|
||||
led15070_frame_sync(src);
|
||||
|
||||
dest->pos = 0;
|
||||
escape = false;
|
||||
|
||||
for (i = 0, hr = S_FALSE ; i < src->pos && hr == S_FALSE ; i++) {
|
||||
/* Step the FSM to unstuff another byte */
|
||||
|
||||
byte = src->bytes[i];
|
||||
|
||||
if (dest->pos >= dest->nbytes) {
|
||||
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
} else if (i == 0) {
|
||||
dest->bytes[dest->pos++] = byte;
|
||||
} else if (byte == 0xE0) {
|
||||
hr = E_FAIL;
|
||||
} else if (byte == 0xD0) {
|
||||
if (escape) {
|
||||
hr = E_FAIL;
|
||||
}
|
||||
|
||||
escape = true;
|
||||
} else if (escape) {
|
||||
dest->bytes[dest->pos++] = byte + 1;
|
||||
escape = false;
|
||||
} else {
|
||||
dest->bytes[dest->pos++] = byte;
|
||||
}
|
||||
|
||||
/* Try to accept the packet we've built up so far */
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = led15070_frame_accept(dest);
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle FSM terminal state */
|
||||
|
||||
if (hr != S_FALSE) {
|
||||
/* Frame was either accepted or rejected, remove it from src */
|
||||
memmove(&src->bytes[0], &src->bytes[i], src->pos - i);
|
||||
src->pos -= i;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT led15070_frame_encode(
|
||||
struct iobuf *dest,
|
||||
const void *ptr,
|
||||
size_t nbytes)
|
||||
{
|
||||
const uint8_t *src;
|
||||
uint8_t checksum;
|
||||
uint8_t byte;
|
||||
size_t i;
|
||||
HRESULT hr;
|
||||
|
||||
assert(dest != NULL);
|
||||
assert(dest->bytes != NULL || dest->nbytes == 0);
|
||||
assert(dest->pos <= dest->nbytes);
|
||||
assert(ptr != NULL);
|
||||
|
||||
src = ptr;
|
||||
|
||||
assert(nbytes >= 3 && src[0] == 0xE0 && src[3] + 4 == nbytes);
|
||||
|
||||
if (dest->pos >= dest->nbytes) {
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
dest->bytes[dest->pos++] = 0xE0;
|
||||
checksum = 0;
|
||||
// dprintf("%02x ", 0xe0);
|
||||
|
||||
for (i = 1 ; i < nbytes ; i++) {
|
||||
byte = src[i];
|
||||
checksum += byte;
|
||||
// dprintf("%02x ", byte);
|
||||
|
||||
hr = led15070_frame_encode_byte(dest, byte);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
// dprintf("%02x \n", checksum);
|
||||
|
||||
return led15070_frame_encode_byte(dest, checksum);
|
||||
}
|
||||
|
||||
static HRESULT led15070_frame_encode_byte(struct iobuf *dest, uint8_t byte)
|
||||
{
|
||||
if (byte == 0xE0 || byte == 0xD0) {
|
||||
if (dest->pos + 2 > dest->nbytes) {
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
dest->bytes[dest->pos++] = 0xD0;
|
||||
dest->bytes[dest->pos++] = byte - 1;
|
||||
} else {
|
||||
if (dest->pos + 1 > dest->nbytes) {
|
||||
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
|
||||
}
|
||||
|
||||
dest->bytes[dest->pos++] = byte;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
26
board/led15070-frame.h
Normal file
26
board/led15070-frame.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hook/iobuf.h"
|
||||
|
||||
enum {
|
||||
LED_15070_FRAME_SYNC = 0xE0,
|
||||
};
|
||||
|
||||
struct led15070_hdr {
|
||||
uint8_t sync;
|
||||
uint8_t dest_adr;
|
||||
uint8_t src_adr;
|
||||
uint8_t nbytes;
|
||||
};
|
||||
|
||||
HRESULT led15070_frame_decode(struct iobuf *dest, struct iobuf *src);
|
||||
|
||||
HRESULT led15070_frame_encode(
|
||||
struct iobuf *dest,
|
||||
const void *ptr,
|
||||
size_t nbytes);
|
1250
board/led15070.c
Normal file
1250
board/led15070.c
Normal file
File diff suppressed because it is too large
Load Diff
29
board/led15070.h
Normal file
29
board/led15070.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct led15070_config {
|
||||
bool enable;
|
||||
unsigned int port_no;
|
||||
char board_number[8];
|
||||
uint8_t fw_ver;
|
||||
uint16_t fw_sum;
|
||||
wchar_t eeprom_path[MAX_PATH];
|
||||
};
|
||||
|
||||
typedef HRESULT (*io_led_init_t)(void);
|
||||
typedef void (*io_led_set_fet_output_t)(const uint8_t *rgb);
|
||||
typedef void (*io_led_dc_update_t)(const uint8_t *rgb);
|
||||
typedef void (*io_led_gs_update_t)(const uint8_t *rgb);
|
||||
|
||||
HRESULT led15070_hook_init(
|
||||
const struct led15070_config *cfg,
|
||||
io_led_init_t _led_init,
|
||||
io_led_set_fet_output_t _led_set_fet_output,
|
||||
io_led_dc_update_t _led_dc_update,
|
||||
io_led_gs_update_t _led_gs_update,
|
||||
unsigned int first_port,
|
||||
unsigned int num_boards);
|
@ -25,6 +25,11 @@ board_lib = static_library(
|
||||
'led15093-frame.h',
|
||||
'led15093.c',
|
||||
'led15093.h',
|
||||
'led15070-cmd.h',
|
||||
'led15070-frame.c',
|
||||
'led15070-frame.h',
|
||||
'led15070.c',
|
||||
'led15070.h',
|
||||
'sg-cmd.c',
|
||||
'sg-cmd.h',
|
||||
'sg-frame.c',
|
||||
|
@ -1,3 +1,31 @@
|
||||
/*
|
||||
"Wonderland Wars" (carol*) hook
|
||||
|
||||
Devices:
|
||||
|
||||
JVS: 837-14572 "Type 3" I/O Board
|
||||
|
||||
[Satellite]
|
||||
|
||||
USB: "WinTouch" Controller Board
|
||||
^ (DIPSW2 ON, Version 5.xx.xx or above)
|
||||
COM1: 3M Touch Systems 78-0011-2353-4 Touch Controller Board
|
||||
^ (DIPSW2 OFF)
|
||||
COM10: TN32MSEC003S "Gen 1" Aime Reader
|
||||
OR
|
||||
837-15286 "Gen 2" Aime Reader
|
||||
^ (Version 1.6x.xx or above)
|
||||
COM11: 837-15070-02 LED Controller Board
|
||||
COM12: 837-15312 Pen Controller I/O Board
|
||||
|
||||
[Terminal]
|
||||
|
||||
COM10: 837-15286 "Gen 2" Aime Reader
|
||||
|
||||
*: SEGA's abbreviation for Lewis Carroll, author of Alice's Adventures in
|
||||
Wonderland.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -1,3 +1,15 @@
|
||||
/*
|
||||
"CHUNITHM" (chuni) hook
|
||||
|
||||
Devices
|
||||
|
||||
JVS: 837-14572 "Type 3" I/O Board
|
||||
COM1: 837-15330 Ground Slider
|
||||
COM10: 837-15093-06 LED Controller Board
|
||||
COM11: 837-15093-06 LED Controller Board
|
||||
COM12: TN32MSEC003S "Gen 1" Aime Reader
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -1,3 +1,27 @@
|
||||
/*
|
||||
"CHUNITHM NEW" (chusan) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257-02 "Type 4" I/O Board
|
||||
COM1: 837-15330 Ground Slider
|
||||
|
||||
[CVT mode (DIPSW2 ON)]
|
||||
|
||||
COM2: 837-15093-06 LED Controller Board
|
||||
COM3: 837-15093-06 LED Controller Board
|
||||
COM4: 837-15286 "Gen 2" Aime Reader
|
||||
|
||||
[SP mode (DIPSW2 OFF)]
|
||||
|
||||
USB: 837-15067-02 USB Serial I/F Board
|
||||
connected to
|
||||
837-15093-06 LED Controller Board (COM20)
|
||||
837-15093-06 LED Controller Board (COM21)
|
||||
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||
COM4: 837-15396 "Gen 3" Aime Reader
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -1,3 +1,16 @@
|
||||
/*
|
||||
"Card Maker" (cm) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257-01 "Type 4" I/O Board
|
||||
USB: 838-20006 "WinTouch" Controller Board
|
||||
USB: 630-00009 Sinfonia CHC-C310 Printer
|
||||
COM1: 837-15396 "Gen 3" Aime Reader
|
||||
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||
COM3: 220-5872 AS-6DB Coin Selector
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
@ -55,6 +68,12 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&cm_hook_cfg.aime, 1, 1, cm_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
@ -67,12 +86,6 @@ static DWORD CALLBACK cm_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = cm_io4_hook_init(&cm_hook_cfg.io4);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
|
1
dist/chusan/segatools.ini
vendored
1
dist/chusan/segatools.ini
vendored
@ -43,6 +43,7 @@ default=127.0.0.1
|
||||
; Chunithm is extremely picky about its LAN environment, so leaving this
|
||||
; setting enabled is strongly recommended.
|
||||
enable=1
|
||||
|
||||
; The final octet of the local host's IP address on the virtualized subnet (so,
|
||||
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
|
||||
; local host's virtualized LAN IP is `192.168.32.11`).
|
||||
|
19
dist/idac/segatools.ini
vendored
19
dist/idac/segatools.ini
vendored
@ -75,6 +75,25 @@ dipsw3=0
|
||||
dipsw4=0
|
||||
dipsw5=0
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; LED settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[led15070]
|
||||
; Enable emulation of the 837-15070-02 controlled lights, which handle the
|
||||
; cabinet and seat LEDs.
|
||||
enable=1
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Misc. hooks settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[indrun]
|
||||
; Hooks to patch GameProject-Win64-Shipping.exe and IndRun.dll. This is needed
|
||||
; to boot version 1.60.00 and up. The hooks are not needed for version 1.50.00
|
||||
; and below.
|
||||
enable=1
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; Custom IO settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
@ -1,3 +1,14 @@
|
||||
/*
|
||||
"Hatsune Miku Project DIVA Arcade " (diva) hook
|
||||
|
||||
Devices
|
||||
|
||||
JVS: 837-14572 "Type 3" I/O Board
|
||||
COM1: 3M Touch Systems 78-0011-2353-4 Touch Controller Board
|
||||
COM10: TN32MSEC003S "Gen 1" Aime Reader
|
||||
COM11: 837-15275 Touch Slider
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -1,3 +1,20 @@
|
||||
/*
|
||||
"Fate Grand/Order Arcade" (fgo) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257 "Type 4" I/O Board
|
||||
USB: 838-15405 "WinTouch" Controller Board
|
||||
USB: 630-00008 Sinfonia CHC-C330 Printer
|
||||
USB: 837-14509-02 USB-SER I/F BD Mini-B FTDI Board
|
||||
connected to
|
||||
837-15093-06 LED Controller Board
|
||||
COM1: 200-6275 VFD GP1232A02A FUTABA Board
|
||||
COM2: 837-15345 RFID Deck Reader Noard
|
||||
COM3: 837-15396 "Gen 3" Aime Reader
|
||||
COM4: 837-15347 RFID Reader/Writer Board (inside the printer)
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -13,6 +13,43 @@
|
||||
#include "platform/config.h"
|
||||
#include "platform/platform.h"
|
||||
|
||||
|
||||
void led15070_config_load(struct led15070_config *cfg, const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
wchar_t tmpstr[16];
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"led15070", L"enable", 1, filename);
|
||||
cfg->port_no = GetPrivateProfileIntW(L"led15070", L"portNo", 0, filename);
|
||||
cfg->fw_ver = GetPrivateProfileIntW(L"led15070", L"fwVer", 0x90, filename);
|
||||
/* TODO: Unknown, no firmware file available */
|
||||
cfg->fw_sum = GetPrivateProfileIntW(L"led15070", L"fwSum", 0x0000, filename);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"led15070",
|
||||
L"boardNumber",
|
||||
L"15070-02",
|
||||
tmpstr,
|
||||
_countof(tmpstr),
|
||||
filename);
|
||||
|
||||
size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number));
|
||||
for (int i = n; i < sizeof(cfg->board_number); i++)
|
||||
{
|
||||
cfg->board_number[i] = ' ';
|
||||
}
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"led15070",
|
||||
L"eepromPath",
|
||||
L"DEVICE",
|
||||
cfg->eeprom_path,
|
||||
_countof(cfg->eeprom_path),
|
||||
filename);
|
||||
}
|
||||
|
||||
void idac_dll_config_load(
|
||||
struct idac_dll_config *cfg,
|
||||
const wchar_t *filename)
|
||||
@ -29,6 +66,16 @@ void idac_dll_config_load(
|
||||
filename);
|
||||
}
|
||||
|
||||
void indrun_config_load(
|
||||
struct indrun_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"indrun", L"enable", 1, filename);
|
||||
}
|
||||
|
||||
void idac_hook_config_load(
|
||||
struct idac_hook_config *cfg,
|
||||
const wchar_t *filename)
|
||||
@ -42,6 +89,8 @@ void idac_hook_config_load(
|
||||
zinput_config_load(&cfg->zinput, filename);
|
||||
dvd_config_load(&cfg->dvd, filename);
|
||||
io4_config_load(&cfg->io4, filename);
|
||||
led15070_config_load(&cfg->led15070, filename);
|
||||
indrun_config_load(&cfg->indrun, filename);
|
||||
}
|
||||
|
||||
void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename)
|
||||
|
@ -4,11 +4,13 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "board/config.h"
|
||||
#include "board/led15070.h"
|
||||
|
||||
#include "hooklib/dvd.h"
|
||||
|
||||
#include "idachook/idac-dll.h"
|
||||
#include "idachook/zinput.h"
|
||||
#include "idachook/indrun.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
@ -19,6 +21,8 @@ struct idac_hook_config {
|
||||
struct io4_config io4;
|
||||
struct idac_dll_config dll;
|
||||
struct zinput_config zinput;
|
||||
struct led15070_config led15070;
|
||||
struct indrun_config indrun;
|
||||
};
|
||||
|
||||
void idac_dll_config_load(
|
||||
@ -29,4 +33,10 @@ void idac_hook_config_load(
|
||||
struct idac_hook_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename);
|
||||
void zinput_config_load(
|
||||
struct zinput_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
void indrun_config_load(
|
||||
struct indrun_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
@ -1,3 +1,16 @@
|
||||
/*
|
||||
"Initial D THE ARCADE" (idac) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257 "Type 4" I/O Board
|
||||
COM1: 838-15069 MOTOR DRIVE BD RS232/422 Board
|
||||
COM2: 837-15070-02 IC BD LED Controller Board
|
||||
COM3: 837-15286 "Gen 2" Aime Reader (DIPSW2 OFF)
|
||||
OR
|
||||
837-15396 "Gen 3" Aime Reader (DIPSW2 ON)
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
@ -53,13 +66,13 @@ static DWORD CALLBACK idac_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, 3, idac_hook_mod);
|
||||
hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = idac_dll_init(&idac_hook_cfg.dll, idac_hook_mod);
|
||||
hr = sg_reader_hook_init(&idac_hook_cfg.aime, 3, 3, idac_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
@ -71,6 +84,20 @@ static DWORD CALLBACK idac_pre_startup(void)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = led15070_hook_init(&idac_hook_cfg.led15070, idac_dll.led_init,
|
||||
idac_dll.led_set_fet_output, NULL, idac_dll.led_gs_update, 2, 1);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Initialize native plugin DLL hooks
|
||||
|
||||
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
|
||||
hooked earlier in the initialization. */
|
||||
|
||||
indrun_hook_init(&idac_hook_cfg.indrun);
|
||||
|
||||
/* Initialize debug helpers */
|
||||
|
||||
spike_hook_init(L".\\segatools.ini");
|
||||
|
@ -24,6 +24,18 @@ const struct dll_bind_sym idac_dll_syms[] = {
|
||||
}, {
|
||||
.sym = "idac_io_get_analogs",
|
||||
.off = offsetof(struct idac_dll, get_analogs),
|
||||
}, {
|
||||
.sym = "idac_io_led_init",
|
||||
.off = offsetof(struct idac_dll, led_init),
|
||||
}, {
|
||||
.sym = "idac_io_led_set_fet_output",
|
||||
.off = offsetof(struct idac_dll, led_set_fet_output),
|
||||
}, {
|
||||
.sym = "idac_io_led_gs_update",
|
||||
.off = offsetof(struct idac_dll, led_gs_update),
|
||||
}, {
|
||||
.sym = "idac_io_led_set_leds",
|
||||
.off = offsetof(struct idac_dll, led_set_leds),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,6 +11,10 @@ struct idac_dll {
|
||||
void (*get_gamebtns)(uint8_t *gamebtn);
|
||||
void (*get_shifter)(uint8_t *gear);
|
||||
void (*get_analogs)(struct idac_io_analog_state *out);
|
||||
HRESULT (*led_init)(void);
|
||||
void (*led_set_fet_output)(const uint8_t *rgb);
|
||||
void (*led_gs_update)(const uint8_t *rgb);
|
||||
void (*led_set_leds)(const uint8_t *rgb);
|
||||
};
|
||||
|
||||
struct idac_dll_config {
|
||||
|
@ -17,3 +17,7 @@ EXPORTS
|
||||
idac_io_get_gamebtns
|
||||
idac_io_get_shifter
|
||||
idac_io_get_analogs
|
||||
idac_io_led_init
|
||||
idac_io_led_set_fet_output
|
||||
idac_io_led_gs_update
|
||||
idac_io_led_set_leds
|
||||
|
260
idachook/indrun.c
Normal file
260
idachook/indrun.c
Normal file
@ -0,0 +1,260 @@
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "hooklib/dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
#include "indrun.h"
|
||||
|
||||
static const wchar_t *target_modules[] = {
|
||||
L"IndRun.dll",
|
||||
};
|
||||
|
||||
static const size_t target_modules_len = _countof(target_modules);
|
||||
|
||||
static void dll_hook_insert_hooks(HMODULE target);
|
||||
static void app_hook_insert_hooks(HMODULE target);
|
||||
|
||||
static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name);
|
||||
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
|
||||
|
||||
static int WINAPI hook_GetSystemMetrics(int nIndex);
|
||||
static int (WINAPI *next_GetSystemMetrics)(int nIndex);
|
||||
|
||||
static BOOL WINAPI hook_GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize);
|
||||
static DWORD WINAPI hook_GetCurrentDirectoryW( DWORD nBufferLength, LPWSTR lpBuffer);
|
||||
static BOOL WINAPI hook_GetVersionExW(LPOSVERSIONINFOW lpVersionInformation);
|
||||
static int (WINAPI *next_GetVersionExW)(LPOSVERSIONINFOW lpVersionInformation);
|
||||
static BOOL WINAPI hook_VerifyVersionInfoW(LPOSVERSIONINFOEXW lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask);
|
||||
static BOOL (WINAPI *next_VerifyVersionInfoW)(LPOSVERSIONINFOEXW lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask);
|
||||
static BOOL WINAPI hook_K32EnumProcesses(DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded);
|
||||
static BOOL (WINAPI *next_K32EnumProcesses)(DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded);
|
||||
|
||||
static BOOL WINAPI hook_GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer);
|
||||
|
||||
static const struct hook_symbol idac_app_user32_syms[] = {
|
||||
{
|
||||
.name = "GetSystemMetrics",
|
||||
.patch = hook_GetSystemMetrics,
|
||||
.link = (void **) &next_GetSystemMetrics,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hook_symbol idac_app_kernel32_syms[] = {
|
||||
{
|
||||
.name = "GetComputerNameW",
|
||||
.patch = hook_GetComputerNameW,
|
||||
},
|
||||
{
|
||||
.name = "GetCurrentDirectoryW",
|
||||
.patch = hook_GetCurrentDirectoryW,
|
||||
},
|
||||
{
|
||||
.name = "GetVersionExW",
|
||||
.patch = hook_GetVersionExW,
|
||||
.link = (void **) &next_GetVersionExW,
|
||||
},
|
||||
{
|
||||
.name = "VerifyVersionInfoW",
|
||||
.patch = hook_VerifyVersionInfoW,
|
||||
.link = (void **) &next_VerifyVersionInfoW,
|
||||
},
|
||||
{
|
||||
.name = "K32EnumProcesses",
|
||||
.patch = hook_K32EnumProcesses,
|
||||
.link = (void **) &next_K32EnumProcesses,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hook_symbol idac_app_advapi32_syms[] = {
|
||||
{
|
||||
.name = "GetUserNameW",
|
||||
.patch = hook_GetUserNameW,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct hook_symbol indrun_kernel32_syms[] = {
|
||||
{
|
||||
.name = "LoadLibraryW",
|
||||
.patch = hook_LoadLibraryW,
|
||||
.link = (void **) &next_LoadLibraryW,
|
||||
}
|
||||
};
|
||||
|
||||
void indrun_hook_init(struct indrun_config *cfg)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
|
||||
if (!cfg->enable) {
|
||||
return;
|
||||
}
|
||||
|
||||
dprintf("IDAC: Hooks enabled.\n");
|
||||
|
||||
// GameProject-Win64-Shipping.exe hooks
|
||||
app_hook_insert_hooks(NULL);
|
||||
|
||||
// IndRun.dll hooks
|
||||
dll_hook_insert_hooks(NULL);
|
||||
}
|
||||
|
||||
static void dll_hook_insert_hooks(HMODULE target) {
|
||||
hook_table_apply(
|
||||
target,
|
||||
"kernel32.dll",
|
||||
indrun_kernel32_syms,
|
||||
_countof(indrun_kernel32_syms));
|
||||
}
|
||||
|
||||
void app_hook_insert_hooks(HMODULE target) {
|
||||
hook_table_apply(
|
||||
target,
|
||||
"user32.dll",
|
||||
idac_app_user32_syms,
|
||||
_countof(idac_app_user32_syms));
|
||||
|
||||
hook_table_apply(
|
||||
target,
|
||||
"kernel32.dll",
|
||||
idac_app_kernel32_syms,
|
||||
_countof(idac_app_kernel32_syms));
|
||||
|
||||
hook_table_apply(
|
||||
target,
|
||||
"advapi32.dll",
|
||||
idac_app_advapi32_syms,
|
||||
_countof(idac_app_advapi32_syms));
|
||||
}
|
||||
|
||||
static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name)
|
||||
{
|
||||
const wchar_t *name_end;
|
||||
const wchar_t *target_module;
|
||||
bool already_loaded;
|
||||
HMODULE result;
|
||||
size_t name_len;
|
||||
size_t target_module_len;
|
||||
|
||||
if (name == NULL) {
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check if the module is already loaded
|
||||
already_loaded = GetModuleHandleW(name) != NULL;
|
||||
|
||||
// Must call the next handler so the DLL reference count is incremented
|
||||
result = next_LoadLibraryW(name);
|
||||
|
||||
if (!already_loaded && result != NULL) {
|
||||
name_len = wcslen(name);
|
||||
|
||||
for (size_t i = 0; i < target_modules_len; i++) {
|
||||
target_module = target_modules[i];
|
||||
target_module_len = wcslen(target_module);
|
||||
|
||||
// Check if the newly loaded library is at least the length of
|
||||
// the name of the target module
|
||||
if (name_len < target_module_len) {
|
||||
continue;
|
||||
}
|
||||
|
||||
name_end = &name[name_len - target_module_len];
|
||||
|
||||
// Check if the name of the newly loaded library is one of the
|
||||
// modules the path hooks should be injected into
|
||||
if (_wcsicmp(name_end, target_module) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dprintf("IDAC: Hooked %S\n", target_module);
|
||||
|
||||
dll_hook_insert_hooks(result);
|
||||
app_hook_insert_hooks(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int WINAPI hook_GetSystemMetrics(int nIndex) {
|
||||
int ret = next_GetSystemMetrics(nIndex);
|
||||
|
||||
// Disable mouse buttons detection
|
||||
if (nIndex == SM_CMOUSEBUTTONS) {
|
||||
dprintf("IDAC: GetSystemMetrics(%d) -> 0\n", nIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_GetComputerNameW(LPWSTR lpBuffer, LPDWORD nSize) {
|
||||
dprintf("IDAC: GetComputerNameW -> ACAE01A99999999\n");
|
||||
|
||||
// Fake the computer name as ACAE01A999999999
|
||||
wcscpy(lpBuffer, L"ACAE01A999999999");
|
||||
*nSize = _countof(L"ACAE01A99999999");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DWORD WINAPI hook_GetCurrentDirectoryW(DWORD nBufferLength, LPWSTR lpBuffer) {
|
||||
dprintf("IDAC: GetCurrentDirectoryW -> X:\\\n");
|
||||
|
||||
// Fake the current diretory as X:
|
||||
wcscpy(lpBuffer, L"X");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_GetVersionExW(LPOSVERSIONINFOW lpVersionInformation) {
|
||||
int result = next_GetVersionExW(lpVersionInformation);
|
||||
|
||||
// Fake the version as Windows 10 1809
|
||||
if (result) {
|
||||
dprintf("IDAC: GetVersionExW -> Windows 10 1809\n");
|
||||
lpVersionInformation->dwMajorVersion = 10;
|
||||
lpVersionInformation->dwMinorVersion = 0;
|
||||
lpVersionInformation->dwBuildNumber = 17763;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_GetUserNameW(LPWSTR lpBuffer, LPDWORD pcbBuffer) {
|
||||
dprintf("IDAC: GetUserNameW -> AppUser\n");
|
||||
|
||||
// Fake the user name as AppUser
|
||||
wcscpy(lpBuffer, L"AppUser");
|
||||
*pcbBuffer = _countof(L"AppUser");
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_VerifyVersionInfoW(LPOSVERSIONINFOEXW lpVersionInformation, DWORD dwTypeMask, DWORDLONG dwlConditionMask) {
|
||||
BOOL result = next_VerifyVersionInfoW(lpVersionInformation, dwTypeMask, dwlConditionMask);
|
||||
|
||||
// Fake the version as Windows 10 1809
|
||||
if (lpVersionInformation->dwBuildNumber == 17763) {
|
||||
dprintf("IDAC: VerifyVersionInfoW -> Windows 10 1809\n");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_K32EnumProcesses(DWORD *lpidProcess, DWORD cb, LPDWORD lpcbNeeded) {
|
||||
BOOL result = next_K32EnumProcesses(lpidProcess, cb, lpcbNeeded);
|
||||
|
||||
// Rteurn an empy process list
|
||||
dprintf("IDAC: K32EnumProcesses -> NULL\n");
|
||||
lpidProcess = NULL;
|
||||
*lpcbNeeded = 0;
|
||||
|
||||
return TRUE;
|
||||
}
|
9
idachook/indrun.h
Normal file
9
idachook/indrun.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
struct indrun_config {
|
||||
bool enable;
|
||||
};
|
||||
|
||||
void indrun_hook_init(struct indrun_config *cfg);
|
@ -11,10 +11,12 @@
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static HRESULT idac_io4_poll(void *ctx, struct io4_state *state);
|
||||
static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len);
|
||||
static uint16_t coins;
|
||||
|
||||
static const struct io4_ops idac_io4_ops = {
|
||||
.poll = idac_io4_poll,
|
||||
.write_gpio = idac_io4_write_gpio
|
||||
};
|
||||
|
||||
static const uint16_t idac_gear_signals[] = {
|
||||
@ -128,3 +130,34 @@ static HRESULT idac_io4_poll(void *ctx, struct io4_state *state)
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT idac_io4_write_gpio(uint8_t* payload, size_t len)
|
||||
{
|
||||
// Just fast fail if there aren't enough bytes in the payload
|
||||
if (len < 3)
|
||||
return S_OK;
|
||||
|
||||
// This command is used for lights in IDAC, but it only contains button lights,
|
||||
// and only in the first 3 bytes of the payload; everything else is padding to
|
||||
// make the payload 62 bytes. The rest of the cabinet lights and the side button
|
||||
// lights are handled separately, by the 15070 lights controller.
|
||||
uint32_t lights_data = (uint32_t) ((uint8_t)(payload[0]) << 24 |
|
||||
(uint8_t)(payload[1]) << 16 |
|
||||
(uint8_t)(payload[2]) << 8);
|
||||
|
||||
// Since Sega uses an odd ordering for the first part of the bitfield,
|
||||
// let's normalize the data and just send over bytes for the receiver
|
||||
// to interpret as ON/OFF values.
|
||||
uint8_t rgb_out[6] = {
|
||||
lights_data & IDAC_IO_LED_START ? 0xFF : 0x00,
|
||||
lights_data & IDAC_IO_LED_VIEW_CHANGE ? 0xFF : 0x00,
|
||||
lights_data & IDAC_IO_LED_UP ? 0xFF : 0x00,
|
||||
lights_data & IDAC_IO_LED_DOWN ? 0xFF : 0x00,
|
||||
lights_data & IDAC_IO_LED_RIGHT ? 0xFF : 0x00,
|
||||
lights_data & IDAC_IO_LED_LEFT ? 0xFF : 0x00,
|
||||
};
|
||||
|
||||
idac_dll.led_set_leds(rgb_out);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -28,5 +28,7 @@ shared_library(
|
||||
'io4.h',
|
||||
'zinput.c',
|
||||
'zinput.h',
|
||||
'indrun.c',
|
||||
'indrun.h',
|
||||
],
|
||||
)
|
||||
|
@ -19,7 +19,7 @@ static bool idac_io_coin;
|
||||
|
||||
uint16_t idac_io_get_api_version(void)
|
||||
{
|
||||
return 0x0100;
|
||||
return 0x0101;
|
||||
}
|
||||
|
||||
HRESULT idac_io_init(void)
|
||||
@ -118,3 +118,44 @@ void idac_io_get_analogs(struct idac_io_analog_state *out)
|
||||
out->accel = tmp.accel;
|
||||
out->brake = tmp.brake;
|
||||
}
|
||||
|
||||
HRESULT idac_io_led_init(void)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void idac_io_led_set_fet_output(const uint8_t *rgb)
|
||||
{
|
||||
#if 0
|
||||
dprintf("IDAC LED: LEFT SEAT LED: %02X\n", rgb[0]);
|
||||
dprintf("IDAC LED: RIGHT SEAT LED: %02X\n", rgb[1]);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void idac_io_led_gs_update(const uint8_t *rgb)
|
||||
{
|
||||
#if 0
|
||||
for (int i = 0; i < 9; i++) {
|
||||
dprintf("IDAC LED: LED %d: %02X %02X %02X Speed: %02X\n",
|
||||
i, rgb[i * 4], rgb[i * 4 + 1], rgb[i * 4 + 2], rgb[i * 4 + 3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void idac_io_led_set_leds(const uint8_t *rgb)
|
||||
{
|
||||
#if 0
|
||||
dprintf("IDAC LED: START: %02X\n", rgb[0]);
|
||||
dprintf("IDAC LED: VIEW CHANGE: %02X\n", rgb[1]);
|
||||
dprintf("IDAC LED: UP: %02X\n", rgb[2]);
|
||||
dprintf("IDAC LED: DOWN: %02X\n", rgb[3]);
|
||||
dprintf("IDAC LED: RIGHT: %02X\n", rgb[4]);
|
||||
dprintf("IDAC LED: LEFT: %02X\n", rgb[5]);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -6,3 +6,7 @@ EXPORTS
|
||||
idac_io_get_gamebtns
|
||||
idac_io_get_shifter
|
||||
idac_io_get_analogs
|
||||
idac_io_led_init
|
||||
idac_io_led_set_fet_output
|
||||
idac_io_led_gs_update
|
||||
idac_io_led_set_leds
|
||||
|
@ -19,6 +19,17 @@ enum {
|
||||
IDAC_IO_GAMEBTN_VIEW_CHANGE = 0x20,
|
||||
};
|
||||
|
||||
enum {
|
||||
/* These are the bitmasks to use when checking which
|
||||
lights are triggered on incoming IO4 GPIO writes. */
|
||||
IDAC_IO_LED_START = 1 << 31,
|
||||
IDAC_IO_LED_VIEW_CHANGE = 1 << 30,
|
||||
IDAC_IO_LED_UP = 1 << 25,
|
||||
IDAC_IO_LED_DOWN = 1 << 24,
|
||||
IDAC_IO_LED_LEFT = 1 << 23,
|
||||
IDAC_IO_LED_RIGHT = 1 << 22,
|
||||
};
|
||||
|
||||
struct idac_io_analog_state {
|
||||
/* Current steering wheel position, where zero is the centered position.
|
||||
|
||||
@ -93,3 +104,59 @@ void idac_io_get_analogs(struct idac_io_analog_state *out);
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
void idac_io_get_shifter(uint8_t *gear);
|
||||
|
||||
/* Initialize LED emulation. This function will be called before any
|
||||
other idac_io_led_*() function calls.
|
||||
|
||||
All subsequent calls may originate from arbitrary threads and some may
|
||||
overlap with each other. Ensuring synchronization inside your IO DLL is
|
||||
your responsibility.
|
||||
|
||||
Minimum API version: 0x0101 */
|
||||
|
||||
HRESULT idac_io_led_init(void);
|
||||
|
||||
/* Update the FET outputs. rgb is a pointer to an array up to 3 bytes.
|
||||
|
||||
The following bits are used to control the FET outputs:
|
||||
[0]: LEFT SEAT LED
|
||||
[1]: RIGHT SEAT LED
|
||||
|
||||
The LED is truned on when the byte is 255 and turned off when the byte is 0.
|
||||
|
||||
Minimum API version: 0x0101 */
|
||||
|
||||
void idac_io_led_set_fet_output(const uint8_t *rgb);
|
||||
|
||||
/* Update the RGB LEDs. rgb is a pointer to an array up to 32 * 4 = 128 bytes.
|
||||
|
||||
The LEDs are laid out as follows:
|
||||
[0]: LEFT UP LED
|
||||
[1-2]: LEFT CENTER LED
|
||||
[3]: LEFT DOWN LED
|
||||
[5]: RIGHT UP LED
|
||||
[6-7]: RIGHT CENTER LED
|
||||
[8]: RIGHT DOWN LED
|
||||
|
||||
Each rgb value is comprised for 4 bytes in the order of R, G, B, Speed.
|
||||
Speed is a value from 0 to 255, where 0 is the fastest speed and 255 is the slowest.
|
||||
|
||||
Minimum API version: 0x0101 */
|
||||
|
||||
void idac_io_led_gs_update(const uint8_t *rgb);
|
||||
|
||||
/* Update the cabinet button LEDs. rgb is a pointer to an array up to 6 bytes.
|
||||
|
||||
The LEDs are laid out as follows:
|
||||
[0]: START LED
|
||||
[1]: VIEW CHANGE LED
|
||||
[2]: UP LED
|
||||
[3]: DOWN LED
|
||||
[4]: RIGHT LED
|
||||
[5]: LEFT LED
|
||||
|
||||
The LED is turned on when the byte is 255 and turned off when the byte is 0.
|
||||
|
||||
Minimum API version: 0x0101 */
|
||||
|
||||
void idac_io_led_set_leds(const uint8_t *rgb);
|
||||
|
@ -1,3 +1,14 @@
|
||||
/*
|
||||
"Initial D ARCADE STAGE Zero" (idz) hook
|
||||
|
||||
Devices
|
||||
|
||||
JVS: 837-15257 "Type 4" I/O Board
|
||||
COM1: 838-15069 MOTOR DRIVE BD RS232/422 Board
|
||||
COM10: 837-15286 "Gen 2" Aime Reader
|
||||
COM11: 837-15070-02 IC BD LED Controller Board
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
@ -1,3 +1,22 @@
|
||||
/*
|
||||
"maimai DX" (mai2) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257-01 "Type 4" I/O Board
|
||||
USB: 2 * 601-13216 USB "QR Code" Camera (SDEZ2, SDEZ3)
|
||||
USB: 601-13249 USB "Player" Camera (SDEZ1)
|
||||
USB: 837-15067-02 IC BD USB to Serial 232
|
||||
connected to
|
||||
837-15070-04 LED Board Controller (COM21)
|
||||
837-15070-04 LED Board Controller (COM23)
|
||||
|
||||
COM1: 837-15396 "Gen 3" Aime Reader
|
||||
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||
COM3: 509-6483 Touch Panel Controller
|
||||
COM4: 509-6483 Touch Panel Controller
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
@ -5,6 +24,8 @@
|
||||
#include "board/vfd.h"
|
||||
|
||||
#include "hook/process.h"
|
||||
#include "hook/table.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "hooklib/serial.h"
|
||||
#include "hooklib/spike.h"
|
||||
|
@ -1,3 +1,16 @@
|
||||
/*
|
||||
"WACCA" (mercury) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257-01 "Type 4" I/O Board
|
||||
USB: 14-1497-R "Elisabeth" LED Board Controller
|
||||
COM1: 837-15396 "Gen 3" Aime Reader
|
||||
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||
COM3: PSS-7135-L02-01 "Left Side" Touch Board
|
||||
COM4: PSS-7135-L02-01 "Right Sdde" Touch Board
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
@ -1,3 +1,15 @@
|
||||
/*
|
||||
"O.N.G.E.K.I." (mu3) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257-01 "Type 4" I/O Board
|
||||
USB: 3 * 601-13216 USB "QR Code" Camera (SDDT1-SDDT3)
|
||||
COM1: 837-15396 "Gen 3" Aime Reader
|
||||
COM2: 200-6275 VFD GP1232A02A FUTABA Board
|
||||
COM3: 837-15093-06 LED Controller Board
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
@ -151,7 +151,7 @@ HRESULT mu3_io_led_init(void);
|
||||
that the board 0 is called from mu3 and the board 1 is called from amdaemon.
|
||||
So the library must be able to handle both calls, using shared memory f.e.
|
||||
This is up to the developer to decide how to handle this, recommended way is
|
||||
to use the amdaemon process as the main one and the mu3 call as a sub one.
|
||||
to use the amdaemon process as the main one and the mu3 process as a sub one.
|
||||
|
||||
Minimum API version: 0x0101 */
|
||||
|
||||
|
@ -109,6 +109,21 @@ HRESULT dns_platform_hook_init(const struct dns_config *cfg)
|
||||
return hr;
|
||||
}
|
||||
|
||||
// CHN
|
||||
// PowerOn
|
||||
hr = dns_hook_push(L"at.sys-all.cn", cfg->startup);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// WeChat AimeDB Server
|
||||
hr = dns_hook_push(L"ai.sys-all.cn", cfg->aimedb);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
// if your ISP resolves bad domains, it will kill the network. These 2
|
||||
// *cannot* resolve
|
||||
|
||||
|
@ -76,7 +76,7 @@ HRESULT platform_hook_init(
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = vfs_hook_init(&cfg->vfs);
|
||||
hr = vfs_hook_init(&cfg->vfs, game_id);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
@ -9,6 +9,9 @@
|
||||
#include "hooklib/path.h"
|
||||
#include "hooklib/reg.h"
|
||||
|
||||
#include "hook/procaddr.h"
|
||||
#include "hook/table.h"
|
||||
|
||||
#include "platform/vfs.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
@ -31,6 +34,26 @@ static HRESULT vfs_path_hook_option(
|
||||
static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes);
|
||||
|
||||
static wchar_t* hook_System_getAppRootPath();
|
||||
static wchar_t* (*next_System_getAppRootPath)();
|
||||
|
||||
static wchar_t* hook_AppImage_getOptionMountRootPath();
|
||||
static wchar_t* (*next_AppImage_getOptionMountRootPath)();
|
||||
|
||||
static const struct hook_symbol amdaemon_syms[] = {
|
||||
{
|
||||
.name = "System_getAppRootPath",
|
||||
.patch = hook_System_getAppRootPath,
|
||||
.link = (void **) &next_System_getAppRootPath,
|
||||
},
|
||||
{
|
||||
.name = "AppImage_getOptionMountRootPath",
|
||||
.patch = hook_AppImage_getOptionMountRootPath,
|
||||
.link = (void **) &next_AppImage_getOptionMountRootPath,
|
||||
},
|
||||
};
|
||||
|
||||
static wchar_t game[5] = {0};
|
||||
static wchar_t vfs_nthome_real[MAX_PATH];
|
||||
static const wchar_t vfs_nthome[] = L"C:\\Documents and Settings\\AppUser";
|
||||
static const size_t vfs_nthome_len = _countof(vfs_nthome) - 1;
|
||||
@ -55,7 +78,7 @@ static const struct reg_hook_val vfs_reg_vals[] = {
|
||||
|
||||
static struct vfs_config vfs_config;
|
||||
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config)
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id)
|
||||
{
|
||||
wchar_t temp[MAX_PATH];
|
||||
size_t nthome_len;
|
||||
@ -68,6 +91,8 @@ HRESULT vfs_hook_init(const struct vfs_config *config)
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
mbstowcs(game, game_id, 4);
|
||||
|
||||
if (config->amfs[0] == L'\0') {
|
||||
dprintf("Vfs: FATAL: AMFS path not specified in INI file\n");
|
||||
|
||||
@ -175,6 +200,13 @@ HRESULT vfs_hook_init(const struct vfs_config *config)
|
||||
return hr;
|
||||
}
|
||||
|
||||
proc_addr_table_push(
|
||||
NULL,
|
||||
"amdaemon_api.dll",
|
||||
amdaemon_syms,
|
||||
_countof(amdaemon_syms)
|
||||
);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -287,8 +319,6 @@ static HRESULT vfs_path_hook(const wchar_t *src, wchar_t *dest, size_t *count)
|
||||
}
|
||||
|
||||
switch (src[0]) {
|
||||
// case L'D': // later AMDaemon versions default to D: for AMFS if it can't find it
|
||||
// case L'd':
|
||||
case L'e':
|
||||
case L'E':
|
||||
redir = vfs_config.amfs;
|
||||
@ -479,3 +509,21 @@ static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"Y:\\");
|
||||
}
|
||||
|
||||
static wchar_t* hook_System_getAppRootPath()
|
||||
{
|
||||
wchar_t *path = malloc(sizeof(wchar_t) * MAX_PATH);
|
||||
wcscpy_s(path, MAX_PATH, vfs_config.appdata);
|
||||
wcscat_s(path, MAX_PATH, game);
|
||||
wcscat_s(path, MAX_PATH, L"\\");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static wchar_t* hook_AppImage_getOptionMountRootPath()
|
||||
{
|
||||
wchar_t *path = malloc(sizeof(wchar_t) * MAX_PATH);
|
||||
wcscpy_s(path, MAX_PATH, vfs_config.option);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
@ -12,4 +12,4 @@ struct vfs_config {
|
||||
wchar_t option[MAX_PATH];
|
||||
};
|
||||
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config);
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id);
|
||||
|
@ -1,3 +1,18 @@
|
||||
/*
|
||||
"SEGA World Drivers Championship" (swdc) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257 "Type 4" I/O Board
|
||||
USB: 838-15415 Indicator BD Main Board (COM21)
|
||||
WITH
|
||||
838-15416 Indicator BD LED Board
|
||||
COM1: 838-15069 MOTOR DRIVE BD RS232/422 board
|
||||
COM2: 837-15396 "Gen 3" Aime reader
|
||||
COM3: 837-15070-04 IC BD LED controller board
|
||||
COM4: 200-6275 VFD GP1232A02A FUTABA board
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <shlwapi.h>
|
||||
|
||||
|
@ -24,11 +24,13 @@ static const wchar_t *target_modules[] = {
|
||||
L"mono.dll",
|
||||
L"mono-2.0-bdwgc.dll",
|
||||
L"cri_ware_unity.dll",
|
||||
L"amdaemon_api.dll",
|
||||
L"SerialPortAPI.dll",
|
||||
L"C300usb.dll",
|
||||
L"C300FWDLusb.dll",
|
||||
L"apmled.dll",
|
||||
L"apmmount.dll",
|
||||
L"HKBSys_api.dll",
|
||||
L"amptw.dll"
|
||||
};
|
||||
|
||||
static const size_t target_modules_len = _countof(target_modules);
|
||||
@ -138,9 +140,7 @@ static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name)
|
||||
path_hook_insert_hooks(result);
|
||||
|
||||
// printer_hook_insert_hooks(result);
|
||||
|
||||
reg_hook_insert_hooks(result);
|
||||
|
||||
proc_addr_insert_hooks(result);
|
||||
serial_hook_apply_hooks(result);
|
||||
iohook_apply_hooks(result);
|
||||
|
Reference in New Issue
Block a user