Compare commits

...

45 Commits

Author SHA1 Message Date
965126c68a idac: improved compatibility with newer versions 2024-06-30 14:23:20 +02:00
050951e56f idac: removed unused include 2024-06-24 17:15:29 +02:00
7e5e0f132e idac: 837-15070 board implementation 2024-06-23 21:21:57 +02:00
4e58d3b9a2 added game specific devices documentation 2024-06-23 21:04:08 +02:00
b0f307f427 Fixed option loading, thanks @Hay1tsme, close #16 2024-06-09 00:50:54 +02:00
7aa996193c Merge pull request 'dns: added CHN DNS block' (#17) from zaphkito/segatools:develop into develop
Reviewed-on: Dniel97/segatools#17
2024-05-20 19:59:37 +00:00
9353c9872f dns: added CHN DNS block 2024-05-19 09:37:57 +00:00
d8b3d41809 mu3: hotfix for calling mu3_io_led_set_colors 2024-05-16 08:10:05 +02:00
3bfb046afc mu3, chusan: improved library doc 2024-05-15 21:42:15 +02:00
9fe98b227b mu3: added lights hook 2024-05-12 22:06:37 +02:00
b77ce7b457 io3: added basic rotary input support 2024-05-12 19:39:56 +02:00
517469a60c switched to new capnhook, updated unityhook, added LED 15093 to MU3 2024-05-12 19:37:30 +02:00
1069cfee26 Merge pull request 'dns: amlog hook & subdomain wildcard parse' (#14) from Yusen0727/segatools:fix/amlog-dns-hook into develop
Reviewed-on: Dniel97/segatools#14
2024-05-10 04:09:34 +00:00
d3a0faa530 Merge pull request 'unityhook: check for new entrypoint' (#15) from Yusen0727/segatools:fix/new-doorstop-entrypoint into develop
Reviewed-on: Dniel97/segatools#15
2024-05-10 04:04:01 +00:00
00b3d5b7bb unityhook: check for new entrypoint
The new entrypoint has been introduced in UnityDoorstop 4.1.0,
which is used by BepInEx 5.4.23.

This commit check for new entrypoint to support new version
of BepInEx.
2024-05-10 08:24:53 +08:00
04fcd0d09a dns: amlog hook & subdomain wildcard parse 2024-05-09 15:02:22 +08:00
25e954fb55 Merge pull request 'print vfd message instead of dump hex' (#13) from Sucareto/segatools:develop into develop
Reviewed-on: Dniel97/segatools#13
2024-04-29 19:48:35 +00:00
a8c6ac70e4 Merge pull request '[unity] Fix Unity config path' (#12) from beerpsi/segatools:fix/unity/wrong-config-path into develop
Reviewed-on: Dniel97/segatools#12
2024-04-29 19:41:53 +00:00
eb1ec0e261 idac: updated start.bat script 2024-04-29 21:34:30 +02:00
482a6e530a print vfd message 2024-04-30 02:19:10 +08:00
65173e1fa6 [unity] Fix Unity config path 2024-04-29 23:12:10 +07:00
4041844ea9 mai2/mu3/cm: Integrate UnityDoorstop with segatools (#11)
[UnityDoorstop](https://github.com/NeighTools/UnityDoorstop) is a tool to execute managed code (.NET DLLs) before Unity does, useful for modding frameworks such as BepInEx.

This PR integrates parts of its code into segatools, so loading BepInEx is as simple as adding 2 lines to `segatools.ini`:
```ini
[unity]
targetAssembly=BepInEx\core\BepInEx.Preloader.dll
```

This PR also factors out the Unity path redirection hooks to its own module.

Reviewed-on: Dniel97/segatools#11
Co-authored-by: beerpsi <beerpsi@duck.com>
Co-committed-by: beerpsi <beerpsi@duck.com>
2024-04-15 19:30:28 +00:00
47a65e5e51 fixed aime LED firmware 2024-03-17 14:20:13 +01:00
774a639bb7 cxb: fixed configs 2024-03-14 00:14:51 +01:00
097b74d849 cxb: server support added, bugfixes, thanks @Midorica 2024-03-13 21:40:25 +01:00
2590e749ca config bugfixes 2024-03-07 15:46:43 +01:00
9c66488906 added Move/Replace/Delete hooks
- fixes FGO not correctly switching `START UP MODE`
- fixes SWDC not correctly switching `CABINET SETTING`
2024-02-27 16:54:12 +01:00
f570869946 fixed AMFS path redirect with no E:/ drive present 2024-02-27 16:49:27 +01:00
629ded4018 added AimePay, E-MONEY DNS redirects 2024-02-25 19:03:05 +01:00
ca36a879cb updated README and added "AM Daemon" window name 2024-02-22 19:12:18 +01:00
ae199502e8 fixed amfs/appdata redirects 2024-02-22 12:02:32 +01:00
e40e1dffe3 improved all segatools.ini configs 2024-02-21 21:58:44 +01:00
56e971c6a4 changed default operator buttons to F1, F2 and F3 and fixed subnets 2024-02-06 13:01:26 +01:00
3e9303e043 fgo: ups forgot to add it to Package.mk 2024-02-06 12:34:39 +01:00
451a7ec49d added VFD toggle to config 2024-02-06 12:34:11 +01:00
dae3018411 doc: added develop dongle hint 2024-01-27 23:10:59 +01:00
cadf20040c swdc: fixed dinput buttons 2024-01-17 15:52:41 +01:00
cc0b6b0953 swdc: fixed steering wheel buttons, improved start.bat 2024-01-16 17:56:24 +01:00
0affc96e3e small optimizations 2024-01-16 17:54:06 +01:00
a8bd98706f Merge pull request 'fix(netenv): Print IP addresses properly' (#4) from beerpsi/segatools:fix/print-ip-addresses-properly into develop
Reviewed-on: Dniel97/segatools#4
2024-01-08 18:26:51 +00:00
aa2184f947 Merge branch 'develop' into fix/print-ip-addresses-properly 2024-01-07 18:36:04 +00:00
d0165b1eb0 fix(netenv): Print IP addresses properly 2024-01-08 01:34:55 +07:00
477dad2667 Merge branch 'chuniio' into develop 2023-12-27 19:29:55 +01:00
63320f8456 Merge pull request 'fix chunihook' (#2) from CrazyRedMachine/segatools:chuniio into chuniio
Reviewed-on: Dniel97/segatools#2
2023-12-27 15:14:07 +00:00
926493290b fix chunihook 2023-12-26 06:47:19 -05:00
175 changed files with 6010 additions and 1083 deletions

View File

@ -111,6 +111,7 @@ $(BUILD_DIR_ZIP)/swdc.zip:
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \ $(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
$(BUILD_DIR_64)/swdchook/swdchook.dll \ $(BUILD_DIR_64)/swdchook/swdchook.dll \
$(DIST_DIR)/swdc/segatools.ini \ $(DIST_DIR)/swdc/segatools.ini \
$(DIST_DIR)/swdc/config_hook.json \
$(DIST_DIR)/swdc/start.bat \ $(DIST_DIR)/swdc/start.bat \
$(BUILD_DIR_ZIP)/swdc $(BUILD_DIR_ZIP)/swdc
$(V)cp pki/billing.pub \ $(V)cp pki/billing.pub \
@ -224,6 +225,7 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
$(BUILD_DIR_ZIP)/mu3.zip \ $(BUILD_DIR_ZIP)/mu3.zip \
$(BUILD_DIR_ZIP)/mai2.zip \ $(BUILD_DIR_ZIP)/mai2.zip \
$(BUILD_DIR_ZIP)/cm.zip \ $(BUILD_DIR_ZIP)/cm.zip \
$(BUILD_DIR_ZIP)/fgo.zip \
CHANGELOG.md \ CHANGELOG.md \
README.md \ README.md \

View File

@ -1,33 +1,33 @@
# Segatools # Segatools
Version: `2023-11-22` Version: `2024-03-13`
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms. Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.
## List of supported games ## List of supported games
* Chunithm * CHUNITHM
* [Chunithm (Plus)](doc/chunihook.md) * up to [CHUNITHM PARADISE LOST](doc/chunihook.md)
* [Chunithm Air (Plus)](doc/chunihook.md) * starting from CHUNITHM NEW!!
* [Chunithm Star (Plus)](doc/chunihook.md) * crossbeats REV.
* [Chunithm Amazon (Plus)](doc/chunihook.md) * up to crossbeats REV. SUNRISE
* [Chunithm Crystal (Plus)](doc/chunihook.md)
* Chunithm SUN
* Initial D * Initial D
* [Initial D Arcade Stage Zero](doc/idzhook.md) * [Initial D Arcade Stage Zero](doc/idzhook.md)
* Initial D THE ARCADE * Initial D THE ARCADE
* Hatsune Miku: Project DIVA Arcade
* up to Future Tone
* SEGA World Drivers Championship * SEGA World Drivers Championship
* up to SEGA World Drivers Championship 2019 * SEGA World Drivers Championship 2019
* Fate/Grand Order * Fate/Grand Order
* Fate/Grand Order Arcade * Fate/Grand Order Arcade
* ONGEKI * O.N.G.E.K.I.
* up to bright MEMORY * starting from O.N.G.E.K.I.
* maimai DX * maimai DX
* up to maimai DX FESTiVAL PLUS * starting from maimai DX
* Card Maker * Card Maker
* up to Card Maker 1.35 * starting from Card Maker
* Wacca * WACCA
* up to WACCA Reverse * starting from WACCA
## End-users ## End-users

View File

@ -68,7 +68,6 @@ static void aime_io_config_read(
cfg->felica_path, cfg->felica_path,
_countof(cfg->felica_path), _countof(cfg->felica_path),
filename); filename);
dprintf("NFC: felicaPath GetLastError %lx\n", GetLastError());
cfg->felica_gen = GetPrivateProfileIntW( cfg->felica_gen = GetPrivateProfileIntW(
L"aime", L"aime",

View File

@ -8,6 +8,7 @@
#include "board/aime-dll.h" #include "board/aime-dll.h"
#include "board/config.h" #include "board/config.h"
#include "board/sg-reader.h" #include "board/sg-reader.h"
#include "board/vfd.h"
#include "util/dprintf.h" #include "util/dprintf.h"
@ -71,7 +72,7 @@ void aime_config_load(struct aime_config *cfg, const wchar_t *filename)
aime_dll_config_load(&cfg->dll, filename); aime_dll_config_load(&cfg->dll, filename);
cfg->enable = GetPrivateProfileIntW(L"aime", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"aime", L"enable", 1, filename);
cfg->high_baudrate = GetPrivateProfileIntW(L"aime", L"highbaud", 1, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"aime", L"highBaud", 1, filename);
cfg->gen = GetPrivateProfileIntW(L"aime", L"gen", 0, filename); cfg->gen = GetPrivateProfileIntW(L"aime", L"gen", 0, filename);
} }
@ -82,3 +83,11 @@ void io4_config_load(struct io4_config *cfg, const wchar_t *filename)
cfg->enable = GetPrivateProfileIntW(L"io4", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"io4", L"enable", 1, filename);
} }
void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename);
}

View File

@ -5,6 +5,8 @@
#include "board/io4.h" #include "board/io4.h"
#include "board/sg-reader.h" #include "board/sg-reader.h"
#include "board/vfd.h"
void aime_config_load(struct aime_config *cfg, const wchar_t *filename); void aime_config_load(struct aime_config *cfg, const wchar_t *filename);
void io4_config_load(struct io4_config *cfg, const wchar_t *filename); void io4_config_load(struct io4_config *cfg, const wchar_t *filename);
void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename);

View File

@ -79,6 +79,11 @@ static HRESULT io3_cmd_read_analogs(
struct const_iobuf *req_buf, struct const_iobuf *req_buf,
struct iobuf *resp_buf); struct iobuf *resp_buf);
static HRESULT io3_cmd_read_rotarys(
struct io3 *io3,
struct const_iobuf *req_buf,
struct iobuf *resp_buf);
static HRESULT io3_cmd_write_gpio( static HRESULT io3_cmd_write_gpio(
struct io3 *io3, struct io3 *io3,
struct const_iobuf *req_buf, struct const_iobuf *req_buf,
@ -116,6 +121,13 @@ static uint8_t io3_features[] = {
0x03, 8, 10, 0, 0x03, 8, 10, 0,
/* Feature : 0x04 : Rotary inputs
Param1 : 4 : Number of rotary channels
Param2 : 0 : N/A
Param3 : 0 : N/A */
0x04, 4, 0, 0,
/* Feature : 0x12 : GPIO outputs /* Feature : 0x12 : GPIO outputs
Param1 : 3 : Number of ports (8 bits per port) Param1 : 3 : Number of ports (8 bits per port)
Param2 : 0 : N/A Param2 : 0 : N/A
@ -218,6 +230,9 @@ static HRESULT io3_cmd(
case JVS_CMD_READ_ANALOGS: case JVS_CMD_READ_ANALOGS:
return io3_cmd_read_analogs(io3, req, resp); return io3_cmd_read_analogs(io3, req, resp);
case JVS_CMD_READ_ROTARYS:
return io3_cmd_read_rotarys(io3, req, resp);
case JVS_CMD_WRITE_GPIO: case JVS_CMD_WRITE_GPIO:
return io3_cmd_write_gpio(io3, req, resp); return io3_cmd_write_gpio(io3, req, resp);
@ -536,6 +551,60 @@ static HRESULT io3_cmd_read_analogs(
} }
static HRESULT io3_cmd_read_rotarys(
struct io3 *io3,
struct const_iobuf *req_buf,
struct iobuf *resp_buf)
{
struct jvs_req_read_rotarys req;
uint16_t rotarys[4];
uint8_t i;
HRESULT hr;
/* Read req */
hr = iobuf_read(req_buf, &req, sizeof(req));
if (FAILED(hr)) {
return hr;
}
if (req.nrotarys > _countof(rotarys)) {
dprintf("JVS I/O: Invalid analog count %i\n", req.nrotarys);
return E_FAIL;
}
//dprintf("JVS I/O: Read rotarys, nrotarys=%i\n", req.nrotarys);
/* Write report byte */
hr = iobuf_write_8(resp_buf, 0x01);
if (FAILED(hr)) {
return hr;
}
/* Write analogs */
memset(rotarys, 0, sizeof(rotarys));
if (io3->ops->read_rotarys != NULL) {
io3->ops->read_rotarys(io3->ops_ctx, rotarys, req.nrotarys);
}
for (i = 0 ; i < req.nrotarys ; i++) {
hr = iobuf_write_be16(resp_buf, rotarys[i]);
if (FAILED(hr)) {
return hr;
}
}
return hr;
}
static HRESULT io3_cmd_write_gpio( static HRESULT io3_cmd_write_gpio(
struct io3 *io3, struct io3 *io3,
struct const_iobuf *req_buf, struct const_iobuf *req_buf,

View File

@ -18,6 +18,7 @@ struct io3_ops {
void (*write_gpio)(void *ctx, uint32_t state); void (*write_gpio)(void *ctx, uint32_t state);
void (*read_switches)(void *ctx, struct io3_switch_state *out); void (*read_switches)(void *ctx, struct io3_switch_state *out);
void (*read_analogs)(void *ctx, uint16_t *analogs, uint8_t nanalogs); void (*read_analogs)(void *ctx, uint16_t *analogs, uint8_t nanalogs);
void (*read_rotarys)(void *ctx, uint16_t *rotaries, uint8_t nrotaries);
void (*read_coin_counter)(void *ctx, uint8_t slot_no, uint16_t *out); void (*read_coin_counter)(void *ctx, uint8_t slot_no, uint16_t *out);
}; };

View File

@ -48,7 +48,7 @@ static_assert(sizeof(struct io4_report_in) == 0x40, "IO4 IN report size");
struct io4_report_out { struct io4_report_out {
uint8_t report_id; uint8_t report_id;
uint8_t cmd; uint8_t cmd;
uint8_t payload[62]; uint8_t payload[IO4_REPORT_OUT_PAYLOAD_LEN];
}; };
static_assert(sizeof(struct io4_report_out) == 0x40, "IO4 OUT report size"); static_assert(sizeof(struct io4_report_out) == 0x40, "IO4 OUT report size");
@ -223,7 +223,11 @@ static HRESULT io4_handle_write(struct irp *irp)
return S_OK; return S_OK;
case IO4_CMD_SET_GENERAL_OUTPUT: case IO4_CMD_SET_GENERAL_OUTPUT:
dprintf("USB I/O: GPIO Out\n"); // dprintf("USB I/O: GPIO Out\n");
if (io4_ops->write_gpio != NULL) {
return io4_ops->write_gpio(out.payload, IO4_REPORT_OUT_PAYLOAD_LEN);
}
return S_OK; return S_OK;

View File

@ -4,6 +4,8 @@
#include <stdint.h> #include <stdint.h>
#define IO4_REPORT_OUT_PAYLOAD_LEN 62
enum { enum {
/* System buttons in button[0] */ /* System buttons in button[0] */
@ -24,6 +26,7 @@ struct io4_state {
struct io4_ops { struct io4_ops {
HRESULT (*poll)(void *ctx, struct io4_state *state); HRESULT (*poll)(void *ctx, struct io4_state *state);
HRESULT (*write_gpio)(uint8_t* payload, size_t len);
}; };
HRESULT io4_hook_init( HRESULT io4_hook_init(

81
board/led15070-cmd.h Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

29
board/led15070.h Normal file
View 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);

View File

@ -25,6 +25,11 @@ board_lib = static_library(
'led15093-frame.h', 'led15093-frame.h',
'led15093.c', 'led15093.c',
'led15093.h', 'led15093.h',
'led15070-cmd.h',
'led15070-frame.c',
'led15070-frame.h',
'led15070.c',
'led15070.h',
'sg-cmd.c', 'sg-cmd.c',
'sg-cmd.h', 'sg-cmd.h',
'sg-frame.c', 'sg-frame.c',

View File

@ -25,6 +25,13 @@ struct sg_res_header {
uint8_t payload_len; uint8_t payload_len;
}; };
/* struct to save the version string with its length
to fix NUL terminator issues */
struct version_info {
const char *version;
uint8_t length;
};
typedef HRESULT (*sg_dispatch_fn_t)( typedef HRESULT (*sg_dispatch_fn_t)(
void *ctx, void *ctx,
const void *req, const void *req,

View File

@ -27,11 +27,11 @@ static HRESULT sg_led_cmd_set_color(
const struct sg_led *led, const struct sg_led *led,
const struct sg_led_req_set_color *req); const struct sg_led_req_set_color *req);
const char *sg_led_info[] = { static const struct version_info led_version[] = {
"15084\xFF\x10\x00\x12", {"15084\xFF\x10\x00\x12", 9},
"000-00000\xFF\x11\x40", {"000-00000\xFF\x11\x40", 12},
// maybe the same? // maybe the same?
"000-00000\xFF\x11\x40" {"000-00000\xFF\x11\x40", 12}
}; };
void sg_led_init( void sg_led_init(
@ -156,10 +156,10 @@ static HRESULT sg_led_cmd_get_info(
{ {
sg_led_dprintf(led, "Get info\n"); sg_led_dprintf(led, "Get info\n");
unsigned int len = strlen(sg_led_info[led->gen - 1]); const struct version_info *fw = &led_version[led->gen - 1];
sg_res_init(&res->res, req, len); sg_res_init(&res->res, req, fw->length);
memcpy(res->payload, sg_led_info[led->gen - 1], len); memcpy(res->payload, fw->version, fw->length);
return S_OK; return S_OK;
} }

View File

@ -65,16 +65,16 @@ static HRESULT sg_nfc_cmd_dummy(
const struct sg_req_header *req, const struct sg_req_header *req,
struct sg_res_header *res); struct sg_res_header *res);
static const char *hw_version[] = { static const struct version_info hw_version[] = {
"TN32MSEC003S H/W Ver3.0", {"TN32MSEC003S H/W Ver3.0", 23},
"837-15286", {"837-15286", 9},
"837-15396" {"837-15396", 9}
}; };
static const char *fw_version[] = { static const struct version_info fw_version[] = {
"TN32MSEC003S F/W Ver1.2", {"TN32MSEC003S F/W Ver1.2", 23},
"\x94", {"\x94", 1},
"\x94" {"\x94", 1}
}; };
void sg_nfc_init( void sg_nfc_init(
@ -217,11 +217,11 @@ static HRESULT sg_nfc_cmd_get_fw_version(
const struct sg_req_header *req, const struct sg_req_header *req,
struct sg_nfc_res_get_fw_version *res) struct sg_nfc_res_get_fw_version *res)
{ {
unsigned int len = strlen(fw_version[nfc->gen - 1]); const struct version_info *fw = &fw_version[nfc->gen - 1];
/* Dest version is not NUL terminated, this is intentional */ /* Dest version is not NUL terminated, this is intentional */
sg_res_init(&res->res, req, len); sg_res_init(&res->res, req, fw->length);
memcpy(res->version, fw_version[nfc->gen - 1], len); memcpy(res->version, fw->version, fw->length);
return S_OK; return S_OK;
} }
@ -231,11 +231,11 @@ static HRESULT sg_nfc_cmd_get_hw_version(
const struct sg_req_header *req, const struct sg_req_header *req,
struct sg_nfc_res_get_hw_version *res) struct sg_nfc_res_get_hw_version *res)
{ {
unsigned int len = strlen(hw_version[nfc->gen - 1]); const struct version_info *hw = &hw_version[nfc->gen - 1];
/* Dest version is not NUL terminated, this is intentional */ /* Dest version is not NUL terminated, this is intentional */
sg_res_init(&res->res, req, len); sg_res_init(&res->res, req, hw->length);
memcpy(res->version, hw_version[nfc->gen - 1], len); memcpy(res->version, hw->version, hw->length);
return S_OK; return S_OK;
} }

View File

@ -26,15 +26,25 @@ static HRESULT vfd_handle_irp(struct irp *irp);
static struct uart vfd_uart; static struct uart vfd_uart;
static uint8_t vfd_written[512]; static uint8_t vfd_written[512];
static uint8_t vfd_readable[512]; static uint8_t vfd_readable[512];
UINT codepage;
HRESULT vfd_hook_init(unsigned int port_no) HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
{ {
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
uart_init(&vfd_uart, port_no); uart_init(&vfd_uart, port_no);
vfd_uart.written.bytes = vfd_written; vfd_uart.written.bytes = vfd_written;
vfd_uart.written.nbytes = sizeof(vfd_written); vfd_uart.written.nbytes = sizeof(vfd_written);
vfd_uart.readable.bytes = vfd_readable; vfd_uart.readable.bytes = vfd_readable;
vfd_uart.readable.nbytes = sizeof(vfd_readable); vfd_uart.readable.nbytes = sizeof(vfd_readable);
codepage = GetACP();
dprintf("VFD: hook enabled.\n");
return iohook_push_handler(vfd_handle_irp); return iohook_push_handler(vfd_handle_irp);
} }
@ -54,8 +64,60 @@ static HRESULT vfd_handle_irp(struct irp *irp)
return hr; return hr;
} }
dprintf("VFD TX:\n"); uint8_t cmd = 0;
dump_iobuf(&vfd_uart.written); uint8_t str_1[512];
uint8_t str_2[512];
uint8_t str_1_len = 0;
uint8_t str_2_len = 0;
for (size_t i = 0; i < vfd_uart.written.pos; i++) {
if (vfd_uart.written.bytes[i] == 0x1B) {
i++;
cmd = vfd_uart.written.bytes[i];
if (cmd == 0x30) {
i += 3;
}
else if (cmd == 0x50) {
i++;
}
continue;
}
if (cmd == 0x30) {
str_1[str_1_len++] = vfd_uart.written.bytes[i];
}
else if (cmd == 0x50) {
str_2[str_2_len++] = vfd_uart.written.bytes[i];
}
}
if (str_1_len) {
str_1[str_1_len++] = '\0';
if (codepage != 932) {
WCHAR buffer[512];
MultiByteToWideChar(932, 0, (LPCSTR)str_1, str_1_len, buffer, str_1_len);
char str_recode[str_1_len * 3];
WideCharToMultiByte(codepage, 0, buffer, str_1_len, str_recode, str_1_len * 3, NULL, NULL);
dprintf("VFD: %s\n", str_recode);
}
else {
dprintf("VFD: %s\n", str_1);
}
}
if (str_2_len) {
str_2[str_2_len++] = '\0';
if (codepage != 932) {
WCHAR buffer[512];
MultiByteToWideChar(932, 0, (LPCSTR)str_2, str_2_len, buffer, str_2_len);
char str_recode[str_2_len * 3];
WideCharToMultiByte(codepage, 0, buffer, str_2_len, str_recode, str_2_len * 3, NULL, NULL);
dprintf("VFD: %s\n", str_recode);
} else {
dprintf("VFD: %s\n", str_2);
}
}
// dprintf("VFD TX:\n");
// dump_iobuf(&vfd_uart.written);
vfd_uart.written.pos = 0; vfd_uart.written.pos = 0;
return hr; return hr;

View File

@ -2,4 +2,9 @@
#include <windows.h> #include <windows.h>
HRESULT vfd_hook_init(unsigned int port_no); struct vfd_config {
bool enable;
};
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no);

View File

@ -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 <windows.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -14,7 +14,7 @@ void carol_io_config_load(
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", '1', filename); cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", VK_F1, filename);
cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", '2', filename); cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", VK_F2, filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", '3', filename); cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", VK_F3, filename);
} }

View File

@ -39,6 +39,19 @@ const struct dll_bind_sym chuni_dll_syms[] = {
} }
}; };
/* 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; struct chuni_dll chuni_dll;
// Copypasta DLL binding and diagnostic message boilerplate. // Copypasta DLL binding and diagnostic message boilerplate.
@ -98,16 +111,24 @@ HRESULT chuni_dll_init(const struct chuni_dll_config *cfg, HINSTANCE self)
} }
sym = chuni_dll_syms; sym = chuni_dll_syms;
const struct dll_bind_sym *init_sym = &sym[0];
hr = dll_bind(&chuni_dll, src, &sym, _countof(chuni_dll_syms)); hr = dll_bind(&chuni_dll, src, &sym, _countof(chuni_dll_syms));
if (FAILED(hr)) { if (FAILED(hr)) {
if (src != self) { if (src != self) {
dprintf("Chunithm IO: Custom IO DLL does not provide function " // Might still be ok depending on external dll API version
"\"%s\". Please contact your IO DLL's developer for " int bind_count = sym - init_sym;
"further assistance.\n", if ( has_enough_symbols(chuni_dll.api_version, bind_count) == S_OK )
sym->sym); {
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);
goto end; goto end;
}
} else { } else {
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym); dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
} }

View File

@ -56,7 +56,7 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->port_no = 0; cfg->port_no = 0;
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaudrate", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);

View File

@ -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 <windows.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -163,9 +163,17 @@ HRESULT chuni_io_led_init(void);
Chunithm uses two chains/boards with WS2811 protocol (each logical led corresponds to 3 physical leds). 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 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 Board 0 has 53 LEDs:
right side has 6*10 rgb values for the billboard, followed by 3 rgb values for the air tower [0]-[49]: snakes through left half of billboard (first column starts at top)
[50]-[52]: left side partition LEDs
Board 1 has 63 LEDs:
[0]-[59]: right half of billboard (first column starts at bottom)
[60]-[62]: right side partition LEDs
Board 2 is the slider and has 31 LEDs:
[0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
Each rgb value is comprised of 3 bytes in R,G,B order 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, ...) NOTE: billboard strips have alternating direction (bottom to top, top to bottom, ...)

View File

@ -34,9 +34,9 @@ void chuni_io_config_load(
assert(filename != NULL); assert(filename != NULL);
// Technically it's io4 but leave this for compatibility with old configs. // Technically it's io4 but leave this for compatibility with old configs.
cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", '1', filename); cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", VK_F1, filename);
cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", '2', filename); cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", VK_F2, filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", '3', filename); cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", VK_F3, filename);
cfg->vk_ir_emu = GetPrivateProfileIntW(L"io3", L"ir", VK_SPACE, filename); cfg->vk_ir_emu = GetPrivateProfileIntW(L"io3", L"ir", VK_SPACE, filename);
for (i = 0 ; i < 6 ; i++) { for (i = 0 ; i < 6 ; i++) {
@ -57,11 +57,11 @@ void chuni_io_config_load(
filename); filename);
} }
cfg->led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename); cfg->cab_led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
cfg->led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename); cfg->cab_led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
cfg->slider_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename); cfg->controller_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
cfg->slider_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename); cfg->controller_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
cfg->led_serial_baud = GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename); cfg->led_serial_baud = GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename);
@ -70,7 +70,7 @@ void chuni_io_config_load(
L"serialPort", L"serialPort",
L"COM5", L"COM5",
port_input, port_input,
6, _countof(port_input),
filename); filename);
// Sanitize the output path. If it's a serial COM port, it needs to be prefixed // Sanitize the output path. If it's a serial COM port, it needs to be prefixed

View File

@ -12,16 +12,15 @@ struct chuni_io_config {
uint8_t vk_cell[32]; uint8_t vk_cell[32];
// Which ways to output LED information are enabled // Which ways to output LED information are enabled
bool led_output_pipe; bool cab_led_output_pipe;
bool led_output_serial; bool cab_led_output_serial;
bool slider_led_output_pipe; bool controller_led_output_pipe;
bool slider_led_output_serial; bool controller_led_output_serial;
// The name of a COM port to output LED data on, in serial mode // The name of a COM port to output LED data on, in serial mode
wchar_t led_serial_port[12]; wchar_t led_serial_port[12];
int32_t led_serial_baud; int32_t led_serial_baud;
}; };
void chuni_io_config_load( void chuni_io_config_load(

View File

@ -48,15 +48,15 @@ HRESULT led_output_init(struct chuni_io_config* const cfg)
led_escaped_buf[i].data_len = chuni_led_board_data_lens[i]; led_escaped_buf[i].data_len = chuni_led_board_data_lens[i];
} }
any_outputs_enabled = config->led_output_pipe || config->slider_led_output_pipe any_outputs_enabled = config->cab_led_output_pipe || config->controller_led_output_pipe
|| config->led_output_serial || config->slider_led_output_serial; || config->cab_led_output_serial || config->controller_led_output_serial;
if (config->led_output_pipe || config->slider_led_output_pipe) if (config->cab_led_output_pipe || config->controller_led_output_pipe)
{ {
led_pipe_init(); // don't really care about errors here tbh led_pipe_init(); // don't really care about errors here tbh
} }
if (config->led_output_serial || config->slider_led_output_serial) if (config->cab_led_output_serial || config->controller_led_output_serial)
{ {
led_serial_init(config->led_serial_port, config->led_serial_baud); led_serial_init(config->led_serial_port, config->led_serial_baud);
} }
@ -106,13 +106,13 @@ void led_output_update(uint8_t board, const byte* rgb)
if (board < 2) if (board < 2)
{ {
// billboard // billboard (cab)
if (config->led_output_pipe) if (config->cab_led_output_pipe)
{ {
led_pipe_update(escaped_data); led_pipe_update(escaped_data);
} }
if (config->led_output_serial) if (config->cab_led_output_serial)
{ {
led_serial_update(escaped_data); led_serial_update(escaped_data);
} }
@ -120,12 +120,12 @@ void led_output_update(uint8_t board, const byte* rgb)
else else
{ {
// slider // slider
if (config->slider_led_output_pipe) if (config->controller_led_output_pipe)
{ {
led_pipe_update(escaped_data); led_pipe_update(escaped_data);
} }
if (config->slider_led_output_serial) if (config->controller_led_output_serial)
{ {
led_serial_update(escaped_data); led_serial_update(escaped_data);
} }

View File

@ -4,6 +4,7 @@
Credits: Credits:
somewhatlurker, skogaby somewhatlurker, skogaby
*/ */
#pragma once #pragma once
#include <windows.h> #include <windows.h>

View File

@ -170,7 +170,7 @@ HRESULT chuni_dll_init(const struct chuni_dll_config *cfg, HINSTANCE self)
"\"%s\". Please contact your IO DLL's developer for " "\"%s\". Please contact your IO DLL's developer for "
"further assistance.\n", "further assistance.\n",
sym->sym); sym->sym);
dprintf("imported %d symbols\n",bind_count); dprintf("imported %d symbols\n", bind_count);
goto end; goto end;
} }
} else { } else {

View File

@ -96,7 +96,7 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->port_no = 0; cfg->port_no = 0;
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaudrate", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
@ -160,6 +160,7 @@ void chusan_hook_config_load(
dvd_config_load(&cfg->dvd, filename); dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, filename); io4_config_load(&cfg->io4, filename);
gfx_config_load(&cfg->gfx, filename); gfx_config_load(&cfg->gfx, filename);
vfd_config_load(&cfg->vfd, filename);
chuni_dll_config_load(&cfg->dll, filename); chuni_dll_config_load(&cfg->dll, filename);
slider_config_load(&cfg->slider, filename); slider_config_load(&cfg->slider, filename);
led15093_config_load(&cfg->led15093, filename); led15093_config_load(&cfg->led15093, filename);

View File

@ -20,6 +20,7 @@ struct chusan_hook_config {
struct dvd_config dvd; struct dvd_config dvd;
struct io4_config io4; struct io4_config io4;
struct gfx_config gfx; struct gfx_config gfx;
struct vfd_config vfd;
struct chuni_dll_config dll; struct chuni_dll_config dll;
struct slider_config slider; struct slider_config slider;
struct led15093_config led15093; struct led15093_config led15093;

View File

@ -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 <windows.h>
#include <stddef.h> #include <stddef.h>
@ -122,7 +146,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
unsigned int first_port = is_cvt ? 2 : 20; unsigned int first_port = is_cvt ? 2 : 20;
if (!is_cvt) { if (!is_cvt) {
hr = vfd_hook_init(2); hr = vfd_hook_init(&chusan_hook_cfg.vfd, 2);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;

View File

@ -37,6 +37,8 @@ void cm_hook_config_load(
aime_config_load(&cfg->aime, filename); aime_config_load(&cfg->aime, filename);
dvd_config_load(&cfg->dvd, filename); dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, filename); io4_config_load(&cfg->io4, filename);
vfd_config_load(&cfg->vfd, filename);
touch_screen_config_load(&cfg->touch, filename); touch_screen_config_load(&cfg->touch, filename);
cm_dll_config_load(&cfg->dll, filename); cm_dll_config_load(&cfg->dll, filename);
unity_config_load(&cfg->unity, filename);
} }

View File

@ -11,13 +11,17 @@
#include "platform/config.h" #include "platform/config.h"
#include "unityhook/config.h"
struct cm_hook_config { struct cm_hook_config {
struct platform_config platform; struct platform_config platform;
struct aime_config aime; struct aime_config aime;
struct dvd_config dvd; struct dvd_config dvd;
struct io4_config io4; struct io4_config io4;
struct vfd_config vfd;
struct cm_dll_config dll; struct cm_dll_config dll;
struct touch_screen_config touch; struct touch_screen_config touch;
struct unity_config unity;
}; };
void cm_dll_config_load( void cm_dll_config_load(

View File

@ -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 <windows.h>
#include <stdlib.h> #include <stdlib.h>
@ -16,10 +29,11 @@
#include "cmhook/config.h" #include "cmhook/config.h"
#include "cmhook/io4.h" #include "cmhook/io4.h"
#include "cmhook/cm-dll.h" #include "cmhook/cm-dll.h"
#include "cmhook/unity.h"
#include "platform/platform.h" #include "platform/platform.h"
#include "unityhook/hook.h"
#include "util/dprintf.h" #include "util/dprintf.h"
static HMODULE cm_hook_mod; static HMODULE cm_hook_mod;
@ -54,19 +68,19 @@ static DWORD CALLBACK cm_pre_startup(void)
goto fail; 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); hr = sg_reader_hook_init(&cm_hook_cfg.aime, 1, 1, cm_hook_mod);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;
} }
hr = vfd_hook_init(2); hr = vfd_hook_init(&cm_hook_cfg.vfd, 2);
if (FAILED(hr)) {
goto fail;
}
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;
@ -83,7 +97,7 @@ static DWORD CALLBACK cm_pre_startup(void)
There seems to be an issue with other DLL hooks if `LoadLibraryW` is There seems to be an issue with other DLL hooks if `LoadLibraryW` is
hooked earlier in the `cmhook` initialization. */ hooked earlier in the `cmhook` initialization. */
unity_hook_init(); unity_hook_init(&cm_hook_cfg.unity, cm_hook_mod);
/* Initialize debug helpers */ /* Initialize debug helpers */

View File

@ -16,6 +16,7 @@ shared_library(
hooklib_lib, hooklib_lib,
cmio_lib, cmio_lib,
platform_lib, platform_lib,
unityhook_lib,
util_lib, util_lib,
], ],
sources : [ sources : [
@ -26,7 +27,5 @@ shared_library(
'io4.h', 'io4.h',
'cm-dll.c', 'cm-dll.c',
'cm-dll.h', 'cm-dll.h',
'unity.h',
'unity.c',
], ],
) )

View File

@ -1,95 +0,0 @@
#include <stdbool.h>
#include <windows.h>
#include "hook/table.h"
#include "hooklib/dll.h"
#include "hooklib/path.h"
#include "util/dprintf.h"
static void dll_hook_insert_hooks(HMODULE target);
static HMODULE WINAPI my_LoadLibraryW(const wchar_t *name);
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
static const struct hook_symbol unity_kernel32_syms[] = {
{
.name = "LoadLibraryW",
.patch = my_LoadLibraryW,
.link = (void **) &next_LoadLibraryW,
},
};
static const wchar_t *target_modules[] = {
L"mono.dll",
L"cri_ware_unity.dll",
};
static const size_t target_modules_len = _countof(target_modules);
void unity_hook_init(void)
{
dll_hook_insert_hooks(NULL);
}
static void dll_hook_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"kernel32.dll",
unity_kernel32_syms,
_countof(unity_kernel32_syms));
}
static HMODULE WINAPI my_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("Unity: Loaded %S\n", target_module);
dll_hook_insert_hooks(result);
path_hook_insert_hooks(result);
}
}
return result;
}

View File

@ -1,3 +0,0 @@
#pragma once
void unity_hook_init(void);

View File

@ -16,7 +16,7 @@ void cm_io_config_load(
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename); cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", VK_F1, filename);
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename); cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", VK_F2, filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename); cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", VK_F3, filename);
} }

View File

@ -23,22 +23,32 @@ void cxb_dll_config_load(
struct cxb_dll_config *cfg, struct cxb_dll_config *cfg,
const wchar_t *filename) const wchar_t *filename)
{ {
assert(cfg != NULL);
assert(filename != NULL);
GetPrivateProfileStringW(
L"cxbio",
L"path",
L"",
cfg->path,
_countof(cfg->path),
filename);
} }
void revio_config_load(struct revio_config *cfg, const wchar_t *filename) void revio_config_load(struct revio_config *cfg, const wchar_t *filename)
{ {
assert(cfg != NULL);
assert(filename != NULL);
} cfg->enable = GetPrivateProfileIntW(L"revio", L"enable", 1, filename);
void network_config_load(struct network_config *cfg, const wchar_t *filename)
{
} }
void led_config_load(struct led_config *cfg, const wchar_t *filename) void led_config_load(struct led_config *cfg, const wchar_t *filename)
{ {
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"led", L"enable", 1, filename);
} }
void cxb_hook_config_load( void cxb_hook_config_load(
@ -56,6 +66,5 @@ void cxb_hook_config_load(
gfx_config_load(&cfg->gfx, filename); gfx_config_load(&cfg->gfx, filename);
cxb_dll_config_load(&cfg->dll, filename); cxb_dll_config_load(&cfg->dll, filename);
revio_config_load(&cfg->revio, filename); revio_config_load(&cfg->revio, filename);
network_config_load(&cfg->network, filename);
led_config_load(&cfg->led, filename); led_config_load(&cfg->led, filename);
} }

View File

@ -10,7 +10,6 @@
#include "cxbhook/cxb-dll.h" #include "cxbhook/cxb-dll.h"
#include "cxbhook/revio.h" #include "cxbhook/revio.h"
#include "cxbhook/led.h" #include "cxbhook/led.h"
#include "cxbhook/network.h"
#include "gfxhook/gfx.h" #include "gfxhook/gfx.h"
@ -23,7 +22,6 @@ struct cxb_hook_config {
struct gfx_config gfx; struct gfx_config gfx;
struct cxb_dll_config dll; struct cxb_dll_config dll;
struct revio_config revio; struct revio_config revio;
struct network_config network;
struct led_config led; struct led_config led;
}; };
@ -32,7 +30,6 @@ void cxb_dll_config_load(
const wchar_t *filename); const wchar_t *filename);
void revio_config_load(struct revio_config *cfg, const wchar_t *filename); void revio_config_load(struct revio_config *cfg, const wchar_t *filename);
void network_config_load(struct network_config *cfg, const wchar_t *filename);
void led_config_load(struct led_config *cfg, const wchar_t *filename); void led_config_load(struct led_config *cfg, const wchar_t *filename);
void cxb_hook_config_load( void cxb_hook_config_load(

View File

@ -9,7 +9,6 @@
#include "cxbhook/config.h" #include "cxbhook/config.h"
#include "cxbhook/revio.h" #include "cxbhook/revio.h"
#include "cxbhook/led.h" #include "cxbhook/led.h"
#include "cxbhook/network.h"
#include "cxbio/cxbio.h" #include "cxbio/cxbio.h"
@ -103,12 +102,6 @@ static DWORD CALLBACK cxb_pre_startup(void)
goto fail; goto fail;
} }
hr = network_hook_init(&cxb_hook_cfg.network);
if (FAILED(hr)) {
goto fail;
}
hr = led_hook_init(&cxb_hook_cfg.led); hr = led_hook_init(&cxb_hook_cfg.led);
if (FAILED(hr)) { if (FAILED(hr)) {

View File

@ -5,7 +5,7 @@
#include "cxbhook/led.h" #include "cxbhook/led.h"
#include "cxbhook/cxb-dll.h" #include "cxbhook/cxb-dll.h"
#include "hooklib/procaddr.h" #include "hook/procaddr.h"
#include "hook/table.h" #include "hook/table.h"
@ -49,8 +49,14 @@ static struct hook_symbol lamp_syms[] = {
HRESULT led_hook_init(struct led_config *cfg) HRESULT led_hook_init(struct led_config *cfg)
{ {
dprintf("LED: Init\n"); assert(cfg != NULL);
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
if (!cfg->enable) {
return S_FALSE;
}
dprintf("LED: Hook enabled.\n");
return proc_addr_table_push(NULL, "CommLamp.dll", lamp_syms, _countof(lamp_syms));
} }
static int my_cCommLamp_Open(char *port) static int my_cCommLamp_Open(char *port)

View File

@ -30,7 +30,5 @@ shared_library(
'revio.h', 'revio.h',
'led.c', 'led.c',
'led.h', 'led.h',
'network.c',
'network.h',
], ],
) )

View File

@ -1,13 +0,0 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "cxbhook/network.h"
#include "util/dprintf.h"
HRESULT network_hook_init(struct network_config *cfg)
{
dprintf("Network: Init\n");
return S_OK;
}

View File

@ -1,13 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct network_config {
bool enable;
bool disable_ssl;
char title_server[PATH_MAX];
};
HRESULT network_hook_init(struct network_config *cfg);

View File

@ -6,7 +6,7 @@
#include "cxbhook/revio.h" #include "cxbhook/revio.h"
#include "cxbhook/cxb-dll.h" #include "cxbhook/cxb-dll.h"
#include "hooklib/procaddr.h" #include "hook/procaddr.h"
#include "hook/table.h" #include "hook/table.h"
@ -82,8 +82,14 @@ static struct hook_symbol revio_syms[] = {
HRESULT revio_hook_init(struct revio_config *cfg) HRESULT revio_hook_init(struct revio_config *cfg)
{ {
dprintf("Revio: Init\n"); assert(cfg != NULL);
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
if (!cfg->enable) {
return S_FALSE;
}
dprintf("Revio: Hook enabled.\n");
return proc_addr_table_push(NULL, "CommIo.dll", revio_syms, _countof(revio_syms));
} }
static int my_cCommIo_Open(char *port) static int my_cCommIo_Open(char *port)
@ -154,7 +160,7 @@ static int my_cCommIo_GetTrigger()
out &= ~last_triggers; out &= ~last_triggers;
dprintf("Revio: GetTrigger %X\n", out); // dprintf("Revio: GetTrigger %X\n", out);
last_triggers = out; last_triggers = out;
return out; return out;
} }
@ -188,7 +194,7 @@ static int my_cCommIo_GetRelease()
out &= ~btns; out &= ~btns;
dprintf("Revio: GetRelease %X\n", out); // dprintf("Revio: GetRelease %X\n", out);
last_triggers = btns; last_triggers = btns;
return out; return out;
} }

View File

@ -1,23 +1,56 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
; Insert the path to the game Option directory here (contains Axxx directories) ; Insert the path to the game Option directory here (contains MOV1, PAR0,
; PAR1, RES0 and RES1 directories)
option= option=
; Create an empty directory somewhere and insert the path here. ; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games. ; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime]
; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1
aimePath=DEVICE\aime.txt
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
default=127.0.0.1 default=127.0.0.1
[netenv] [netenv]
; Simulate an ideal LAN environment. ; Simulate an ideal LAN environment. This may interfere with head-to-head play.
; Chunithm is extremely picky about its LAN environment, so leaving this
; setting enabled is strongly recommended.
enable=1 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[gpio] [gpio]
; Emulated Nu DIP switch for Distribution Server setting.
;
; If multiple machines are present on the same LAN then set this to 1 on
; exactly one machine and set this to 0 on all others.
dipsw1=1 dipsw1=1
[keychip] [keychip]
@ -26,6 +59,10 @@ dipsw1=1
; that subnet must start with 192.168. ; that subnet must start with 192.168.
subnet=192.168.126.0 subnet=192.168.126.0
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
[gfx] [gfx]
; Force the game to run windowed. ; Force the game to run windowed.
windowed=1 windowed=1
@ -34,15 +71,31 @@ framed=1
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) ; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0 monitor=0
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio] [aimeio]
; To use a custom card reader IO DLL enter its path here. ; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input. ; Leave empty if you want to use Segatools built-in keyboard input.
path= path=
; -----------------------------------------------------------------------------
; Input settings
; -----------------------------------------------------------------------------
; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal
; (not prefixed with 0x) virtual-key codes, a list of which can be found here:
;
; https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
;
; This is, admittedly, not the most user-friendly configuration method in the
; world. An improved solution will be provided later.
[io3] [io3]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72

View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,6 +12,20 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime]
; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1
aimePath=DEVICE\aime.txt
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -18,6 +36,14 @@ default=127.0.0.1
; Chunithm is extremely picky about its LAN environment, so leaving this ; Chunithm is extremely picky about its LAN environment, so leaving this
; setting enabled is strongly recommended. ; setting enabled is strongly recommended.
enable=1 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
@ -25,6 +51,10 @@ enable=1
; that subnet must start with 192.168. ; that subnet must start with 192.168.
subnet=192.168.139.0 subnet=192.168.139.0
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
[gfx] [gfx]
; Force the game to run windowed. ; Force the game to run windowed.
windowed=1 windowed=1
@ -33,15 +63,9 @@ framed=1
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) ; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0 monitor=0
[aimeio] ; -----------------------------------------------------------------------------
; To use a custom card reader IO DLL enter its path here. ; LED settings
; Leave empty if you want to use Segatools built-in keyboard input. ; -----------------------------------------------------------------------------
path=
[chuniio]
; To use a custom Chunithm IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[led15093] [led15093]
; Enable emulation of the 15093-06 controlled lights, which handle the air tower ; Enable emulation of the 15093-06 controlled lights, which handle the air tower
@ -84,6 +108,20 @@ controllerLedOutputSerial=0
; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers ; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[chuniio]
; To use a custom Chunithm IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -97,12 +135,12 @@ controllerLedOutputSerial=0
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io3] [io3]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Set to 0 for enable separate ir control. Deafult is space key. ; Set to 0 for enable separate ir control. Deafult is space key.
ir=0x20 ir=0x20

View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,17 +12,26 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Enable aime reader emulation. ; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
; Enable high baud rate. ; Enable high baud rate.
;highbaud=1 ;highBaud=1
[aimeio] [vfd]
; Uncomment this if you have custom (x64) aime implementation. ; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; Leave empty if you want to use Segatools built-in keyboard input. ; GP1232A02A FUTABA assembly.
;path= enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
@ -31,6 +44,15 @@ default=127.0.0.1
; setting enabled is strongly recommended. ; setting enabled is strongly recommended.
enable=1 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
@ -55,6 +77,10 @@ dipsw2=1
; the LED 837-15093-06 COM port and the AiMe reder hardware generation as well. ; the LED 837-15093-06 COM port and the AiMe reder hardware generation as well.
dipsw3=1 dipsw3=1
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
[gfx] [gfx]
; Force the game to run windowed. ; Force the game to run windowed.
windowed=1 windowed=1
@ -63,15 +89,9 @@ framed=0
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) ; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0 monitor=0
[chuniio] ; -----------------------------------------------------------------------------
; Uncomment this if you have custom chuniio implementation comprised of a single 32bit DLL. ; LED settings
; (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=
[led15093] [led15093]
; Enable emulation of the 15093-06 controlled lights, which handle the air tower ; Enable emulation of the 15093-06 controlled lights, which handle the air tower
@ -114,6 +134,25 @@ controllerLedOutputSerial=0
; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers ; [0]-[31]: slider LEDs right to left BRG, alternating between keys and dividers
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL (x64) enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[chuniio]
; 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=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -127,12 +166,12 @@ controllerLedOutputSerial=0
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io3] [io3]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Set to 0 for enable separate ir control. Deafult is space key. ; Set to 0 for enable separate ir control. Deafult is space key.
ir=0x20 ir=0x20

View File

@ -2,8 +2,9 @@
pushd %~dp0 pushd %~dp0
start /min inject_x64 -d -k chusanhook_x64.dll amdaemon.exe -c config_common.json config_server.json config_client.json config_cvt.json config_sp.json config_hook.json start "AM Daemon" /min inject_x64 -d -k chusanhook_x64.dll amdaemon.exe -c config_common.json config_server.json config_client.json config_cvt.json config_sp.json config_hook.json
inject_x86 -d -k chusanhook_x86.dll chusanApp.exe inject_x86 -d -k chusanhook_x86.dll chusanApp.exe
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1
echo. echo.

54
dist/cm/segatools.ini vendored
View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,11 +12,25 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Enable aime reader emulation. ; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -24,6 +42,10 @@ default=127.0.0.1
; setting enabled is recommended. ; setting enabled is recommended.
enable=1 enable=1
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
@ -38,10 +60,28 @@ enable=1
; this to 0 on exactly one machine and set this to 1 on all others. ; this to 0 on exactly one machine and set this to 1 on all others.
dipsw1=0 dipsw1=0
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
[touch] [touch]
; Enable/Disable WinTouch emulation ; Enable/Disable WinTouch emulation
enable=0 enable=0
[unity]
; Path to a .NET DLL that should run before the game. Useful for loading
; modding frameworks such as BepInEx.
targetAssembly=
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -55,9 +95,9 @@ enable=0
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72

2
dist/cm/start.bat vendored
View File

@ -2,7 +2,7 @@
pushd %~dp0 pushd %~dp0
start /min inject -d -k cmhook.dll amdaemon.exe -c config_common.json config_server.json config_client.json config_hook.json start "AM Daemon" /min inject -d -k cmhook.dll amdaemon.exe -c config_common.json config_server.json config_client.json config_hook.json
inject -d -k cmhook.dll CardMaker.exe -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920 inject -d -k cmhook.dll CardMaker.exe -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1

107
dist/cxb/segatools.ini vendored
View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Make sure theses are full paths and not relative or you will have a bad time ; Make sure theses are full paths and not relative or you will have a bad time
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
@ -9,41 +13,55 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime]
; Aime reader emulation
enable=1
; CXB is stupid, so we have to make the paths go back two directories. This
; will load the file from "resource\DEVICE\aime.txt".
aimePath=../DEVICE/aime.txt
[led]
; Emulation for the LED board. Currently it's just dummy responses,
; but if somebody wants to make their keyboard or whatever light
; up with the game they can
enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
default=127.0.0.1 default=127.0.0.1
; Set the title server hostname or IP address here, as the title server
; is hardcoded in the game.
title=https://127.0.0.1:9002
[netenv] [netenv]
; Simulate an ideal LAN environment. This may interfere with head-to-head play. ; Simulate an ideal LAN environment. This may interfere with head-to-head play.
; Crossbeats is extremely picky about its LAN environment, so leaving this ; Crossbeats is extremely picky about its LAN environment, so leaving this
; setting enabled is strongly recommended. ; setting enabled is strongly recommended.
enable=1 enable=1
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168. ; that subnet must start with 192.168.
subnet=192.168.100.0 subnet=192.168.150.0
billingCa=../DEVICE/ca.crt billingCa=../DEVICE/ca.crt
billingPub=../DEVICE/billing.pub billingPub=../DEVICE/billing.pub
billingType=2 billingType=2
[gfx]
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.
framed=1
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0
[aime]
; Aime reader emulation
; CXB is stupid, so we have to make the paths go back one
enable=1
aimePath=../DEVICE/aime.txt
felicaPath=../DEVICE/felica.txt
[eeprom] [eeprom]
; See above ; See above
path=../DEVICE/eeprom.bin path=../DEVICE/eeprom.bin
@ -52,21 +70,54 @@ path=../DEVICE/eeprom.bin
; See above ; See above
path=../DEVICE/sram.bin path=../DEVICE/sram.bin
[led] ; -----------------------------------------------------------------------------
; Emulation for the LED board. Currently it's just dummy responses, ; Misc. hooks settings
; but if somebody wants to make their keyboard or whatever light ; -----------------------------------------------------------------------------
; up with the game they can
enable=1 [gfx]
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.
framed=1
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[cxbio]
; To use a custom crossbeats REV. DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; -----------------------------------------------------------------------------
; Input settings
; -----------------------------------------------------------------------------
; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal
; (not prefixed with 0x) virtual-key codes, a list of which can be found here:
;
; https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
;
; This is, admittedly, not the most user-friendly configuration method in the
; world. An improved solution will be provided later.
[revio] [revio]
; Enable emulation of the rev IO board ; Enable emulation of the rev IO board
enabe=1 enable=1
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Menu up key. Default is up arrow. ; Menu up key. Default is up arrow.
up=0x26 up=0x26
; Menu down key. Default is down arrow. ; Menu down key. Default is down arrow.

View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,6 +12,20 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime]
; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1
aimePath=DEVICE\aime.txt
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -19,14 +37,56 @@ default=127.0.0.1
; setting enabled is strongly recommended. ; setting enabled is strongly recommended.
enable=1 enable=1
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[gpio] [gpio]
; Emulated Nu DIP switch for Distribution Server setting.
;
; If multiple machines are present on the same LAN then set this to 1 on
; exactly one machine and set this to 0 on all others.
dipsw1=1 dipsw1=1
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168. ; that subnet must start with 192.168.
subnet=192.168.150.0 subnet=192.168.78.0
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[divaio]
; To use a custom Project DIVA Arcade IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in gamepad/wheel input.
path=
; -----------------------------------------------------------------------------
; Input settings
; -----------------------------------------------------------------------------
; Keyboard bindings are specified as hexadecimal (prefixed with 0x) or decimal
; (not prefixed with 0x) virtual-key codes, a list of which can be found here:
;
; https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
;
; This is, admittedly, not the most user-friendly configuration method in the
; world. An improved solution will be provided later.
[io3]
; Test button virtual-key code. Default is the F1 key.
test=0x70
; Service button virtual-key code. Default is the F2 key.
service=0x71
; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x72
[slider] [slider]
cell1=0x51 cell1=0x51

159
dist/fgo/segatools.ini vendored
View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,49 +12,21 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Controls emulation of the Aime card reader assembly. ; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
[dns] [vfd]
; Insert the hostname or IP address of the server you wish to use here. ; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; Note that 127.0.0.1, localhost etc are specifically rejected. ; GP1232A02A FUTABA assembly.
default=127.0.0.1
[netenv]
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
; SEGA games are somewhat picky about their LAN environment, so leaving this
; setting enabled is recommended.
enable=1 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`).
addrSuffix=11
[keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168.
subnet=192.168.172.0
[touch]
; WinTouch emulation setting.
enable=1
remap=1
cursor=1
[printer]
; Sinfonia CHC-C330 printer emulation setting.
enable=1
; Change the printer serial number here.
serial_no="5A-A123"
; Insert the path to the image output directory here.
printerOutPath="DEVICE\print"
; Rotate all printed images by 180 degrees.
rotate180=1
[deckReader] [deckReader]
; 837-15345 RFID deck reader emulation setting. ; 837-15345 RFID deck reader emulation setting.
enable=1 enable=1
@ -67,6 +43,78 @@ enable=1
; COM port number for the LED board. Has to be the same as the FTDI port. ; COM port number for the LED board. Has to be the same as the FTDI port.
portNo=17 portNo=17
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns]
; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected.
default=127.0.0.1
[netenv]
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
; SEGA games are somewhat picky about their LAN environment, so leaving this
; setting enabled is 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168.
subnet=192.168.167.0
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
; allow you to start a game in freeplay mode.
freeplay=0
; -----------------------------------------------------------------------------
; Misc. hook settings
; -----------------------------------------------------------------------------
[touch]
; WinTouch emulation setting.
enable=1
remap=1
cursor=1
[printer]
; Sinfonia CHC-C330 printer emulation setting.
enable=1
; Change the printer serial number here.
serial_no="5A-A123"
; Insert the path to the image output directory here.
printerOutPath="DEVICE\print"
; Rotate all printed images by 180 degrees.
rotate180=1
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[fgoio]
; To use a custom Fate/Grand Order Arcade IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in gamepad input.
path=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -80,10 +128,33 @@ portNo=17
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Input API selection for JVS input emulator. ; Test button virtual-key code. Default is the F1 key.
; Test button virtual-key code. Default is the 1 key. test=0x70
test=0x31 ; Service button virtual-key code. Default is the F2 key.
; Service button virtual-key code. Default is the 2 key. service=0x71
service=0x32 ; Keyboard button to increment coin counter. Default is the F3 key.
; Keyboard button to increment coin counter. Default is the 3 key. coin=0x72
coin=0x33
; .·:'''''''''''''''''''''''''''''''''''''''''''''':·.
; : : ______ / \ [] : :
; : : | | _____ \ / Coin : :
; : : |______| { (0) } /--\ Attack. : :
; : : DECK \ / / \ : :
; : : | | > < : :
; : : | | \ / ___ : :
; : : | | \--/ | | : :
; : : JOY Noble. | | : :
; : : |___| : :
; : : AIME. : :
; '·:..............................................:·'
;
; Only XInput is currently supported.
; XInput bindings
;
; Left Stick Joystick
; Left Stick Click Reset Camera
; Left Trigger Dash
; Left Shoulder Switch Target
; A/B Attack
; X/Y Noble Phantasm

View File

@ -1,18 +1,30 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
; Insert the path to the game Option directory here (contains OPxx directories) ; Insert the path to the game Option directory here (contains MVxx directories)
option= option=
; Create an empty directory somewhere and insert the path here. ; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games. ; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Controls emulation of the Aime card reader assembly. ; Controls emulation of the Aime card reader assembly.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -24,6 +36,10 @@ default=127.0.0.1
; setting enabled is recommended. ; setting enabled is recommended.
enable=1 enable=1
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
@ -59,13 +75,36 @@ dipsw3=0
dipsw4=0 dipsw4=0
dipsw5=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
; -----------------------------------------------------------------------------
[aimeio] [aimeio]
; To use a custom card reader IO DLL enter its path here. ; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input. ; Leave empty if you want to use Segatools built-in keyboard input.
path= path=
[idacio] [idacio]
; To use a custom Initial D The Arcade IO DLL enter its path here. ; To use a custom Initial D THE ARCADE IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in gamepad/wheel input. ; Leave empty if you want to use Segatools built-in gamepad/wheel input.
path= path=
@ -82,12 +121,12 @@ path=
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Input API selection for IO4 input emulator. ; Input API selection for IO4 input emulator.
; Set "xinput" to use a gamepad and "dinput" to use a steering wheel. ; Set "xinput" to use a gamepad and "dinput" to use a steering wheel.
@ -106,6 +145,22 @@ mode=xinput
restrict=128 restrict=128
[xinput] [xinput]
; XInput bindings
;
; Left Stick Steering
; Right Stick (Steering) when "singleStickSteering" is disabled
; Left Trigger Brake
; Right Trigger Accelerator
; Left Stick Click Left (used for Time Up)
; Right Stick Click Right (used for Time Up)
; Left Shoulder Shift Down
; Right Shoulder Shift Up
; Start/A Start
; Back/B View Change
; X Shift Up
; Y Shift Down
; D-Pad D-Pad
; Left and right thumbsticks are mapped to left and right dpad buttons. ; Left and right thumbsticks are mapped to left and right dpad buttons.
; Press both thumbsticks to trigger "Time Up" and exit the course. ; Press both thumbsticks to trigger "Time Up" and exit the course.
; Automatically reset the simulated shifter to Neutral when XInput Start is ; Automatically reset the simulated shifter to Neutral when XInput Start is

27
dist/idac/start.bat vendored
View File

@ -2,20 +2,6 @@
pushd %~dp0 pushd %~dp0
REM set the APP_DIR to the Y drive
set APP_DIR=Y:\SDGT
REM create the APP_DIR if it doesn't exist and redirect it to the TEMP folder
if not exist "%APP_DIR%" (
subst Y: %TEMP%
REM timeout /t 1
if not exist "%APP_DIR%" (
mkdir "%APP_DIR%"
)
)
echo Mounted the Y:\ drive to the %TEMP%\SDGT folder
set AMDAEMON_CFG=config_common.json ^ set AMDAEMON_CFG=config_common.json ^
config_ex.json ^ config_ex.json ^
config_jp.json ^ config_jp.json ^
@ -39,12 +25,15 @@ config_seat_single_ex.json ^
config_seat_single_jp.json ^ config_seat_single_jp.json ^
config_hook.json config_hook.json
start /min inject -d -k idachook.dll amdaemon.exe -c %AMDAEMON_CFG% start "AM Daemon" /min inject -d -k idachook.dll amdaemon.exe -c %AMDAEMON_CFG%
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject.exe -culture=en launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
taskkill /f /im amdaemon.exe > nul 2>&1
REM unmount the APP_DIR rem JP
subst Y: /d > nul 2>&1 rem inject -d -k idachook.dll ..\WindowsNoEditor\GameProject\Binaries\Win64\GameProject-Win64-Shipping.exe -culture=ja launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
rem EXP
inject -d -k idachook.dll ..\WindowsNoEditor\GameProject\Binaries\Win64\GameProject-Win64-Shipping.exe -culture=en launch=Cabinet ABSLOG="..\..\..\..\..\Userdata\GameProject.log" -Master -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED
taskkill /f /im amdaemon.exe > nul 2>&1
echo. echo.
echo Game processes have terminated echo Game processes have terminated

View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,6 +12,10 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Controls emulation of the Aime card reader assembly. ; Controls emulation of the Aime card reader assembly.
enable=1 enable=1
@ -16,11 +24,36 @@ aimePath=DEVICE\aime.txt
felicaGen=0 felicaGen=0
aimeGen=1 aimeGen=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
default=127.0.0.1 default=127.0.0.1
[netenv]
; Simulate an ideal LAN environment. This may interfere with head-to-head play.
; SEGA games are somewhat picky about their LAN environment, so leaving this
; setting enabled is 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).
; Needed for in store battle, one needs to set it to 12.
;addrSuffix=12
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168.
subnet=192.168.158.0
[ds] [ds]
; Region code on the emulated AMEX board DS EEPROM. ; Region code on the emulated AMEX board DS EEPROM.
; 1: Japan ; 1: Japan
@ -29,23 +62,16 @@ default=127.0.0.1
; NOTE: Changing this setting causes a factory reset. ; NOTE: Changing this setting causes a factory reset.
region=4 region=4
[netenv] [gpio]
; Simulate an ideal LAN environment. This may interfere with head-to-head play. ; Emulated Nu DIP switch for Distribution Server setting.
; SEGA games are somewhat picky about their LAN environment, so leaving this ;
; setting enabled is recommended. ; If multiple machines are present on the same LAN then set this to 1 on
enable=1 ; exactly one machine and set this to 0 on all others.
dipsw1=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, ; Misc. hooks settings
; then the local host's virtualized LAN IP is 192.168.32.11). ; -----------------------------------------------------------------------------
; Needed for in store battle, one needs to set it to 12.
;addrSuffix=12
[keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168.
subnet=192.168.158.0
[gfx] [gfx]
; Enables the graphics hook. This is required for some Initial D Zero versions ; Enables the graphics hook. This is required for some Initial D Zero versions
@ -58,12 +84,9 @@ framed=1
; Select the monitor to run the game on. (Fullscreen only, 0=primary screen) ; Select the monitor to run the game on. (Fullscreen only, 0=primary screen)
monitor=0 monitor=0
[gpio] ; -----------------------------------------------------------------------------
; Emulated Nu DIP switch for Distribution Server setting. ; Custom IO settings
; ; -----------------------------------------------------------------------------
; If multiple machines are present on the same LAN then set this to 1 on
; exactly one machine and set this to 0 on all others.
dipsw1=1
[aimeio] [aimeio]
; To use a custom card reader IO DLL enter its path here. ; To use a custom card reader IO DLL enter its path here.
@ -88,12 +111,12 @@ path=
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io3] [io3]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Input API selection for JVS input emulator. ; Input API selection for JVS input emulator.
; Set "xinput" to use a gamepad and "dinput" to use a steering wheel. ; Set "xinput" to use a gamepad and "dinput" to use a steering wheel.
@ -112,6 +135,20 @@ mode=xinput
restrict=97 restrict=97
[xinput] [xinput]
; XInput bindings
;
; Left Stick Steering
; Right Stick (Steering) when "singleStickSteering" is disabled
; Left Trigger Brake
; Right Trigger Accelerator
; Left Shoulder Shift Down
; Right Shoulder Shift Up
; Start/A Start
; Back/B View Change
; X Shift Up
; Y Shift Down
; D-Pad D-Pad
; Automatically reset the simulated shifter to Neutral when XInput Start is ; Automatically reset the simulated shifter to Neutral when XInput Start is
; pressed (e.g. when navigating menus between races). ; pressed (e.g. when navigating menus between races).
autoNeutral=1 autoNeutral=1

View File

@ -1,18 +1,36 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
; Insert the path to the game Option directory here (contains Axxx, Bxxx directories) ; Insert the path to the game Option directory here (contains Axxx directories)
option= option=
; Create an empty directory somewhere and insert the path here. ; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games. ; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Enable aime reader emulation. ; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -23,12 +41,20 @@ default=127.0.0.1
; SEGA games are somewhat picky about its LAN environment, so leaving this ; SEGA games are somewhat picky about its LAN environment, so leaving this
; setting enabled is recommended. ; setting enabled is recommended.
enable=1 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
; that subnet must start with 192.168. ; that subnet must start with 192.168.
subnet=192.168.100.0 subnet=192.168.172.0
[gpio] [gpio]
; ALLS DIP switches. ; ALLS DIP switches.
@ -43,6 +69,32 @@ freeplay=0
; this to 1 on exactly one machine and set this to 0 on all others. ; this to 1 on exactly one machine and set this to 0 on all others.
dipsw1=1 dipsw1=1
; -----------------------------------------------------------------------------
; Misc. hook settings
; -----------------------------------------------------------------------------
[unity]
; Enable Unity hook. This will allow you to run custom .NET code before the game
enable=1
; Path to a .NET DLL that should run before the game. Useful for loading
; modding frameworks such as BepInEx.
targetAssembly=
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[mai2io]
; To use a custom maimai DX IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -56,12 +108,12 @@ dipsw1=1
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Key bindings for buttons around screen. The default key map, depicted ; Key bindings for buttons around screen. The default key map, depicted
; in clockwise order, is as follows: ; in clockwise order, is as follows:

5
dist/mai2/start.bat vendored
View File

@ -2,8 +2,9 @@
pushd %~dp0 pushd %~dp0
start /min inject -d -k mai2hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json start "AM Daemon" /min inject -d -k mai2hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json
inject -d -k mai2hook.dll sinmai -screen-fullscreen 0 inject -d -k mai2hook.dll sinmai -screen-fullscreen 0 -popupwindow -screen-width 2160 -screen-height 1920 -silent-crashes
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1
echo. echo.

View File

@ -1,11 +1,35 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs=amfs amfs=
; Insert the path to the game Option directory here (contains Axxx directories)
option=
; Create an empty directory somewhere and insert the path here. ; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games. ; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata=appdata appdata=
option=option
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime]
; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
@ -17,6 +41,14 @@ default=127.0.0.1
; SEGA games are somewhat picky about their LAN environment, so leaving this ; SEGA games are somewhat picky about their LAN environment, so leaving this
; setting enabled is recommended. ; setting enabled is recommended.
enable=1 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
@ -24,9 +56,6 @@ enable=1
; that subnet must start with 192.168. ; that subnet must start with 192.168.
subnet=192.168.174.0 subnet=192.168.174.0
[gfx]
enable=1
[gpio] [gpio]
; ALLS DIP switches. ; ALLS DIP switches.
enable=1 enable=1
@ -40,6 +69,35 @@ freeplay=0
; this to 1 on exactly one machine and set this to 0 on all others. ; this to 1 on exactly one machine and set this to 0 on all others.
dipsw1=1 dipsw1=1
; -----------------------------------------------------------------------------
; Misc. hook settings
; -----------------------------------------------------------------------------
[gfx]
enable=1
; Hooks related to the touch boards
[touch]
enable=1
; Hooks related to the LED board (codenamed Elisabeth)
[elisabeth]
enable=1
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[mercuryio]
; To use a custom WACCA IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -53,26 +111,14 @@ dipsw1=1
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Volume up virtual-key code. Default is the "UP" key. ; Volume up virtual-key code. Default is the "UP" key.
volup=0x26 volup=0x26
; Volume down virtual-key code. Default is the "DOWN" key. ; Volume down virtual-key code. Default is the "DOWN" key.
voldown=0x28 voldown=0x28
; Hooks related to the touch boards
[touch]
enable=1
; Hooks related to the LED board (codenamed Elisabeth)
[elisabeth]
enable=1
;[mercuryio]
; Use mercuryio.dll
;path=mercuryio.dll

View File

@ -4,10 +4,10 @@ pushd %~dp0
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1
REM USA REM USA
REM start inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_usa.json
REM JP REM JP
start inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_jpn.json start "AM Daemon" /min inject -d -k mercuryhook.dll amdaemon.exe -f -c config.json config_lan_install_client.json config_lan_install_server.json config_video_clone.json config_video_dual.json config_video_clone_flip.json config_video_dual_flip.json config_region_exp.json config_region_chn.json config_region_jpn.json
inject -d -k mercuryhook.dll ../WindowsNoEditor/Mercury/Binaries/Win64/Mercury-Win64-Shipping.exe inject -d -k mercuryhook.dll ../WindowsNoEditor/Mercury/Binaries/Win64/Mercury-Win64-Shipping.exe
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1

141
dist/mu3/segatools.ini vendored
View File

@ -1,3 +1,7 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
@ -8,11 +12,25 @@ option=
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Controls emulation of the Aime card reader assembly. ; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -24,6 +42,10 @@ default=127.0.0.1
; setting enabled is recommended. ; setting enabled is recommended.
enable=1 enable=1
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; If you disable netenv then you must set this to your LAN's IP subnet, and ; If you disable netenv then you must set this to your LAN's IP subnet, and
@ -43,13 +65,83 @@ freeplay=0
; this to 1 on exactly one machine and set this to 0 on all others. ; this to 1 on exactly one machine and set this to 0 on all others.
dipsw1=1 dipsw1=1
; -----------------------------------------------------------------------------
; Misc. hook settings
; -----------------------------------------------------------------------------
[gfx] [gfx]
enable=1 enable=1
[led15093] [unity]
; 837-15093-06 LED board emulation setting. ; Enable Unity hook. This will allow you to run custom .NET code before the game
enable=1 enable=1
; Path to a .NET DLL that should run before the game. Useful for loading
; modding frameworks such as BepInEx.
targetAssembly=
; -----------------------------------------------------------------------------
; LED settings
; -----------------------------------------------------------------------------
[led15093]
; Enable emulation of the 15093-06 controlled lights, which handle the air tower
; RGBs and the rear LED panel (billboard) on the cabinet.
enable=1
[led]
; Output billboard LED strip data to a named pipe called "\\.\pipe\ongeki_led"
cabLedOutputPipe=1
; Output billboard LED strip data to serial
cabLedOutputSerial=0
; Output slider LED data to the named pipe
controllerLedOutputPipe=1
; Output slider LED data to the serial port
controllerLedOutputSerial=0
; Serial port to send data to if using serial output. Default is COM5.
;serialPort=COM5
; Baud rate for serial data
;serialBaud=921600
; Data output a sequence of bytes, with JVS-like framing.
; Each "packet" starts with 0xE0 as a sync. To avoid E0 appearing elsewhere,
; 0xD0 is used as an escape character -- if you receive D0 in the output, ignore
; it and use the next sent byte plus one instead.
;
; After the sync is one byte for the board number that was updated, followed by
; the red, green and blue values for each LED.
;
; Board 0 has 61 LEDs:
; [0]-[1]: left side button
; [2]-[8]: left pillar lower LEDs
; [9]-[17]: left pillar center LEDs
; [18]-[24]: left pillar upper LEDs
; [25]-[35]: billboard LEDs
; [36]-[42]: right pillar upper LEDs
; [43]-[51]: right pillar center LEDs
; [52]-[58]: right pillar lower LEDs
; [59]-[60]: right side button
;
; Board 1 has 6 LEDs:
; [0]-[5]: 3 left and 3 right controller buttons
;
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
[mu3io]
; To use a custom O.N.G.E.K.I. IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard/gamepad input.
path=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -63,28 +155,43 @@ enable=1
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Input API selection for JVS input emulator. ; Test button virtual-key code. Default is the F1 key.
; Test button virtual-key code. Default is the 1 key. test=0x70
test=0x31 ; Service button virtual-key code. Default is the F2 key.
; Service button virtual-key code. Default is the 2 key. service=0x71
service=0x32 ; Keyboard button to increment coin counter. Default is the F3 key.
; Keyboard button to increment coin counter. Default is the 3 key. coin=0x72
coin=0x33
; Set "1" to enable mouse lever emulation, "0" to use XInput ; Set "1" to enable mouse lever emulation, "0" to use XInput
mouse=1 mouse=1
; XInput input bindings
;
; Left Stick Lever
; Left Trigger Lever (move to the left)
; Right Trigger Lever (move to the right)
; Left Left red button
; Up Left green button
; Right Left blue button
; Left Shoulder Left side button
; Right Shoulder Right side button
; X Right red button
; Y Right green button
; A Right blue button
; Back Left menu button
; Start Right menu button
; Keyboard input bindings ; Keyboard input bindings
left1=0x41 ; A left1=0x41 ; A
left2=0x53 ; S left2=0x53 ; S
left3=0x44 ; D left3=0x44 ; D
leftSide=0x01 ; Mouse Left leftSide=0x01 ; Mouse Left
rightSide=0x02 ; Mouse Right rightSide=0x02 ; Mouse Right
right1=0x4A ; J right1=0x4A ; J
right1=0x4B ; K right1=0x4B ; K
right3=0x4C ; L right3=0x4C ; L
leftMenu=0x55 ; U leftMenu=0x55 ; U
rightMenu=0x4F ; O rightMenu=0x4F ; O

2
dist/mu3/start.bat vendored
View File

@ -2,7 +2,7 @@
pushd %~dp0 pushd %~dp0
start /min inject -d -k mu3hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json start "AM Daemon" /min inject -d -k mu3hook.dll amdaemon.exe -f -c config_common.json config_server.json config_client.json
inject -d -k mu3hook.dll mu3 -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920 inject -d -k mu3hook.dll mu3 -screen-fullscreen 0 -popupwindow -screen-width 1080 -screen-height 1920
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1

6
dist/swdc/config_hook.json vendored Normal file
View File

@ -0,0 +1,6 @@
{
"emoney" :
{
"enable" : false
}
}

View File

@ -1,18 +1,36 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs] [vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2) ; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs= amfs=
; Insert the path to the game Option directory here (contains OPxx directories) ; Insert the path to the game Option directory here (contains Axxx directories)
option= option=
; Create an empty directory somewhere and insert the path here. ; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games. ; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%. ; NOTE: This has nothing to do with Windows %APPDATA%.
appdata= appdata=appdata
; -----------------------------------------------------------------------------
; Device settings
; -----------------------------------------------------------------------------
[aime] [aime]
; Controls emulation of the Aime card reader assembly. ; Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
; reader.
enable=1 enable=1
aimePath=DEVICE\aime.txt aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
; -----------------------------------------------------------------------------
; Network settings
; -----------------------------------------------------------------------------
[dns] [dns]
; Insert the hostname or IP address of the server you wish to use here. ; Insert the hostname or IP address of the server you wish to use here.
; Note that 127.0.0.1, localhost etc are specifically rejected. ; Note that 127.0.0.1, localhost etc are specifically rejected.
@ -23,12 +41,33 @@ default=127.0.0.1
; SEGA games are somewhat picky about their LAN environment, so leaving this ; SEGA games are somewhat picky about their LAN environment, so leaving this
; setting enabled is recommended. ; setting enabled is recommended.
enable=1 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`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
; -----------------------------------------------------------------------------
[keychip] [keychip]
; The /24 LAN subnet that the emulated keychip will tell the game to expect. ; The /24 LAN subnet that the emulated keychip will tell the game to expect.
; You must set this to your LAN's IP subnet, and that subnet must start with 192.168, ; You must set this to your LAN's IP subnet, and that subnet must start with 192.168,
; in order to find the MAIN cabinet. ; in order to find the MAIN cabinet.
subnet=192.168.100.0 subnet=192.168.160.0
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
; allow you to start a game in freeplay mode.
freeplay=0
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio] [aimeio]
; To use a custom card reader IO DLL enter its path here. ; To use a custom card reader IO DLL enter its path here.
@ -40,15 +79,6 @@ path=
; Leave empty if you want to use Segatools built-in gamepad/wheel input. ; Leave empty if you want to use Segatools built-in gamepad/wheel input.
path= path=
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
; freeplay. Keep in mind that some game modes (e.g. Freedom/Time Modes) will not
; allow you to start a game in freeplay mode.
freeplay=0
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -62,12 +92,12 @@ freeplay=0
; world. An improved solution will be provided later. ; world. An improved solution will be provided later.
[io4] [io4]
; Test button virtual-key code. Default is the 1 key. ; Test button virtual-key code. Default is the F1 key.
test=0x31 test=0x70
; Service button virtual-key code. Default is the 2 key. ; Service button virtual-key code. Default is the F2 key.
service=0x32 service=0x71
; Keyboard button to increment coin counter. Default is the 3 key. ; Keyboard button to increment coin counter. Default is the F3 key.
coin=0x33 coin=0x72
; Input API selection for IO4 input emulator. ; Input API selection for IO4 input emulator.
; Set "xinput" to use a gamepad and "dinput" to use a steering wheel. ; Set "xinput" to use a gamepad and "dinput" to use a steering wheel.
@ -86,6 +116,22 @@ mode=xinput
restrict=128 restrict=128
[xinput] [xinput]
; XInput bindings
;
; Left Stick Steering
; Right Stick (Steering) when "singleStickSteering" is disabled
; Left Trigger Brake
; Right Trigger Accelerator
; Left Shoulder Left Paddle
; Right Shoulder Right Paddle
; Start Start
; Back View Change
; A Green (Wheel)
; B Red (Wheel)
; X Blue (Wheel)
; Y Yellow (Wheel)
; D-Pad D-Pad
; Use the left thumbstick for steering instead of both on XInput Controllers. ; Use the left thumbstick for steering instead of both on XInput Controllers.
; Not recommended as it will not give you the precision needed for this game. ; Not recommended as it will not give you the precision needed for this game.
singleStickSteering=1 singleStickSteering=1

36
dist/swdc/start.bat vendored
View File

@ -2,12 +2,36 @@
pushd %~dp0 pushd %~dp0
rem Matching Server REM Root directory
start /min ..\..\..\Tools\tdrserver.exe set ROOT_DIR=WindowsNoEditor
REM start /min inject -d -k swdchook.dll amdaemon.exe -c config.json config_LanClient.json config_MiniCabinet.json config_hook.json
start /min inject -d -k swdchook.dll amdaemon.exe -c config.json config_LanServer.json config_MiniCabinet.json rem Matching Server paths
REM Valid -launch parameters are "PC", "Cabinet" and "MiniCabinet set MATCHING_SERVER_FILE_NAME=tdrserver.exe
inject -d -k swdchook.dll ..\Todoroki\Binaries\Win64\Todoroki-Win64-Shipping.exe -launch=MiniCabinet -ABSLOG="..\..\..\..\..\Userdata\Todoroki.log" -UserDir="..\..\..\Userdata" -NotInstalled -UNATTENDED set MATCHING_SERVER_PATH=..\Tools\%MATCHING_SERVER_FILE_NAME%
rem AM Daemon paths
set DAEMON_DIR=%ROOT_DIR%\AMDaemon
set DAEMON_CONFIG_PATH=%DAEMON_DIR%\config.json
rem Make sure to use appdata=appdata in segatools.ini
set DAEMON_CHECK_LAN_SERVER_PATH=appdata\SDDS\LanServer.dat
rem Check if LanServer.dat is present
if exist "%DAEMON_CHECK_LAN_SERVER_PATH%" (
set DAEMON_LAN_CONFIG_PATH=%DAEMON_DIR%\config_LanServer.json
start "matching_server" /min %MATCHING_SERVER_PATH%
) else (
set DAEMON_LAN_CONFIG_PATH=%DAEMON_DIR%\config_LanClient.json
)
start "AM Daemon" /min inject -d -k swdchook.dll "%DAEMON_DIR%\amdaemon.exe" -c %DAEMON_CONFIG_PATH% -c %DAEMON_LAN_CONFIG_PATH% config_hook.json
REM Launch Todoroki
set APP_EXE_DIR=WindowsNoEditor\Todoroki\Binaries\Win64
set APP_EXE_PATH=%APP_EXE_DIR%\Todoroki-Win64-Shipping.exe
REM Valid -launch parameters are "Cabinet" or "MiniCabinet"
inject -d -k swdchook.dll "%APP_EXE_PATH%" -launch="MiniCabinet" -ABSLOG="..\Userdata\Todoroki.log" -UserDir="..\Userdata" -NotInstalled -UNATTENDED
taskkill /f /im amdaemon.exe > nul 2>&1 taskkill /f /im amdaemon.exe > nul 2>&1
taskkill /f /im tdrserver.exe > nul 2>&1 taskkill /f /im tdrserver.exe > nul 2>&1

View File

@ -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 <windows.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -27,9 +27,9 @@ void diva_io_config_load(
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", '1', filename); cfg->vk_test = GetPrivateProfileIntW(L"io3", L"test", VK_F1, filename);
cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", '2', filename); cfg->vk_service = GetPrivateProfileIntW(L"io3", L"service", VK_F2, filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", '3', filename); cfg->vk_coin = GetPrivateProfileIntW(L"io3", L"coin", VK_F3, filename);
for (i = 0 ; i < _countof(cfg->vk_buttons) ; i++) { for (i = 0 ; i < _countof(cfg->vk_buttons) ; i++) {
swprintf_s(key, _countof(key), L"key%i", i + 1); swprintf_s(key, _countof(key), L"key%i", i + 1);

View File

@ -31,7 +31,7 @@ Default: `1`
Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime Enable Aime card reader assembly emulation. Disable to use a real SEGA Aime
reader (COM port number varies by game). reader (COM port number varies by game).
### `highbaud` ### `highBaud`
Default: `1` Default: `1`
@ -84,6 +84,17 @@ emulates an IC card in its proximity. A variety of different IC cards can be
emulated; the exact choice of card that is emulated depends on the presence or emulated; the exact choice of card that is emulated depends on the presence or
absence of the configured card ID files. absence of the configured card ID files.
## `[vfd]`
Controls emulation of the VFD GP1232A02A FUTABA assembly.
### `enable`
Default: `1`
Enable VFD emulation (currently just stubbed). Disable to use a real VFD
GP1232A02A FUTABA assembly (COM port number varies by game).
## `[amvideo]` ## `[amvideo]`
Controls the `amvideo.dll` stub built into Segatools. This is a DLL that is Controls the `amvideo.dll` stub built into Segatools. This is a DLL that is
@ -142,6 +153,13 @@ setting. Also, loopback addresses are specifically checked for and rejected by
the games themselves; this needs to be a LAN or WAN IP (or a hostname that the games themselves; this needs to be a LAN or WAN IP (or a hostname that
resolves to one). resolves to one).
### `title`
Default: `title`
Leave it as `title` to use the title server returned by ALL.Net. Rewrites
the title server hostname for certain games, such as crossbeats REV.
### `router` ### `router`
Default: Empty string (i.e. use value from `default` setting) Default: Empty string (i.e. use value from `default` setting)
@ -377,13 +395,29 @@ Bit values are:
- 3: EXP: Export (for Asian markets) - 3: EXP: Export (for Asian markets)
- 4: CHS: China (Simplified Chinese?) - 4: CHS: China (Simplified Chinese?)
### `billingCa`
Default: `DEVICE\\ca.crt`
Set the billing certificate path. This has to match the one used for the
SSL billing server. The DER certificate must fit in 1024 bytes so it must be
small.
### `billingPub`
Default: `DEVICE\\billing.pub`
Set the actual keychip RSA public key path. This public key has to match the
private key `billing.key` of the billing server in order to decrypt/encrypt
the billing transactions.
### `billingType` ### `billingType`
Default: `1` Default: `1`
Set the billing "type" for the keychip. The type determins what kind of revenue share, Set the billing "type" for the keychip. The type determins what kind of revenue share,
if any, the game maker has with SEGA. Some games may be picky and require types other if any, the game maker has with SEGA. Some games may be picky and require types other
then 1 (ex. Crossbeats requires billing type 2), so this option is provided if this then 1 (ex. crossbeats REV. requires billing type 2), so this option is provided if this
is an issue. Billing types are: is an issue. Billing types are:
- 0: No billing? - 0: No billing?
@ -396,8 +430,8 @@ is an issue. Billing types are:
Default: `0x64` Default: `0x64`
An 8-bit bitfield of unclear meaning. The least significant bit indicates a An 8-bit bitfield of unclear meaning. The least significant bit indicates a
developer dongle, I think? Changing this doesn't seem to have any effect on developer dongle. Changing this doesn't seem to have any effect on
anything other than Project DIVA. anything other than SEGA AM2 games.
Other values observed in the wild: Other values observed in the wild:

View File

@ -48,7 +48,7 @@ void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename); cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename);
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaudrate", 0, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename); cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename); cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename);
@ -116,6 +116,7 @@ void fgo_hook_config_load(
aime_config_load(&cfg->aime, filename); aime_config_load(&cfg->aime, filename);
dvd_config_load(&cfg->dvd, filename); dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, filename); io4_config_load(&cfg->io4, filename);
vfd_config_load(&cfg->vfd, filename);
touch_screen_config_load(&cfg->touch, filename); touch_screen_config_load(&cfg->touch, filename);
printer_config_load(&cfg->printer, filename); printer_config_load(&cfg->printer, filename);
fgo_deck_config_load(&cfg->deck, filename); fgo_deck_config_load(&cfg->deck, filename);

View File

@ -20,6 +20,7 @@ struct fgo_hook_config {
struct aime_config aime; struct aime_config aime;
struct dvd_config dvd; struct dvd_config dvd;
struct io4_config io4; struct io4_config io4;
struct vfd_config vfd;
struct touch_screen_config touch; struct touch_screen_config touch;
struct printer_config printer; struct printer_config printer;
struct deck_config deck; struct deck_config deck;

View File

@ -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 <windows.h>
#include <stdlib.h> #include <stdlib.h>
@ -67,7 +84,7 @@ static DWORD CALLBACK fgo_pre_startup(void)
goto fail; goto fail;
} }
hr = vfd_hook_init(1); hr = vfd_hook_init(&fgo_hook_cfg.vfd, 1);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;

View File

@ -28,7 +28,7 @@ const struct dll_bind_sym fgo_dll_syms[] = {
.sym = "fgo_io_led_init", .sym = "fgo_io_led_init",
.off = offsetof(struct fgo_dll, led_init), .off = offsetof(struct fgo_dll, led_init),
}, { }, {
.sym = "fgo_io_led_set_leds", .sym = "fgo_io_led_set_colors",
.off = offsetof(struct fgo_dll, led_set_leds), .off = offsetof(struct fgo_dll, led_set_leds),
} }
}; };

View File

@ -11,7 +11,7 @@ struct fgo_dll {
void (*get_opbtns)(uint8_t *opbtn); void (*get_opbtns)(uint8_t *opbtn);
void (*get_gamebtns)(uint8_t *gamebtn); void (*get_gamebtns)(uint8_t *gamebtn);
void (*get_analogs)(int16_t *stick_x, int16_t *stick_y); void (*get_analogs)(int16_t *stick_x, int16_t *stick_y);
HRESULT (*led_init)(); HRESULT (*led_init)(void);
void (*led_set_leds)(uint8_t board, uint8_t *rgb); void (*led_set_leds)(uint8_t board, uint8_t *rgb);
}; };

View File

@ -18,7 +18,7 @@ EXPORTS
fgo_io_init fgo_io_init
fgo_io_poll fgo_io_poll
fgo_io_led_init fgo_io_led_init
fgo_io_led_set_leds fgo_io_led_set_colors
fwdlusb_open fwdlusb_open
fwdlusb_close fwdlusb_close
fwdlusb_listupPrinter fwdlusb_listupPrinter

View File

@ -14,7 +14,7 @@ void fgo_io_config_load(
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename); cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", VK_F1, filename);
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename); cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", VK_F2, filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename); cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", VK_F3, filename);
} }

View File

@ -67,11 +67,11 @@ HRESULT fgo_io_poll(void)
fgo_gamebtn |= FGO_IO_GAMEBTN_TARGET; fgo_gamebtn |= FGO_IO_GAMEBTN_TARGET;
} }
if (xb & XINPUT_GAMEPAD_A) { if (xb & XINPUT_GAMEPAD_A || xb & XINPUT_GAMEPAD_B) {
fgo_gamebtn |= FGO_IO_GAMEBTN_ATTACK; fgo_gamebtn |= FGO_IO_GAMEBTN_ATTACK;
} }
if (xb & XINPUT_GAMEPAD_Y) { if (xb & XINPUT_GAMEPAD_Y || xb & XINPUT_GAMEPAD_X) {
fgo_gamebtn |= FGO_IO_GAMEBTN_NOBLE_PHANTASHM; fgo_gamebtn |= FGO_IO_GAMEBTN_NOBLE_PHANTASHM;
} }
@ -142,11 +142,10 @@ void fgo_io_get_analogs(int16_t *stick_x, int16_t *stick_y)
HRESULT fgo_io_led_init(void) HRESULT fgo_io_led_init(void)
{ {
// return 0;
return S_OK; return S_OK;
} }
void fgo_io_led_set_leds(uint8_t board, uint8_t *rgb) void fgo_io_led_set_colors(uint8_t board, uint8_t *rgb)
{ {
return; return;
} }

View File

@ -83,4 +83,4 @@ HRESULT fgo_io_led_init(void);
Exact layout is TBD. */ Exact layout is TBD. */
void fgo_io_led_set_leds(uint8_t board, uint8_t *rgb); void fgo_io_led_set_colors(uint8_t board, uint8_t *rgb);

View File

@ -3,6 +3,7 @@
#include <windows.h> #include <windows.h>
#include <windns.h> #include <windns.h>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include <winhttp.h>
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
@ -12,6 +13,8 @@
#include "hook/hr.h" #include "hook/hr.h"
#include "hook/table.h" #include "hook/table.h"
#include "util/dprintf.h"
#include "hooklib/dns.h" #include "hooklib/dns.h"
/* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill" /* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill"
@ -66,6 +69,18 @@ static int WSAAPI hook_getaddrinfo(
const ADDRINFOA *pHints, const ADDRINFOA *pHints,
ADDRINFOA **ppResult); ADDRINFOA **ppResult);
static HINTERNET WINAPI hook_WinHttpConnect(
HINTERNET hSession,
const wchar_t *pwszServerName,
INTERNET_PORT nServerPort,
DWORD dwReserved);
static bool WINAPI hook_WinHttpCrackUrl(
const wchar_t *pwszUrl,
DWORD dwUrlLength,
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents);
/* Link pointers */ /* Link pointers */
static DNS_STATUS (WINAPI *next_DnsQuery_A)( static DNS_STATUS (WINAPI *next_DnsQuery_A)(
@ -95,6 +110,18 @@ static int (WSAAPI *next_getaddrinfo)(
const ADDRINFOA *pHints, const ADDRINFOA *pHints,
ADDRINFOA **ppResult); ADDRINFOA **ppResult);
static HINTERNET (WINAPI *next_WinHttpConnect)(
HINTERNET hSession,
const wchar_t *pwszServerName,
INTERNET_PORT nServerPort,
DWORD dwReserved);
static bool (WINAPI *next_WinHttpCrackUrl)(
const wchar_t *pwszUrl,
DWORD dwUrlLength,
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents);
static const struct hook_symbol dns_hook_syms_dnsapi[] = { static const struct hook_symbol dns_hook_syms_dnsapi[] = {
{ {
.name = "DnsQuery_A", .name = "DnsQuery_A",
@ -120,10 +147,24 @@ static const struct hook_symbol dns_hook_syms_ws2[] = {
} }
}; };
static const struct hook_symbol dns_hook_syms_winhttp[] = {
{
.name = "WinHttpConnect",
.patch = hook_WinHttpConnect,
.link = (void **) &next_WinHttpConnect,
}, {
.name = "WinHttpCrackUrl",
.patch = hook_WinHttpCrackUrl,
.link = (void **) &next_WinHttpCrackUrl,
}
};
static bool dns_hook_initted; static bool dns_hook_initted;
static CRITICAL_SECTION dns_hook_lock; static CRITICAL_SECTION dns_hook_lock;
static struct dns_hook_entry *dns_hook_entries; static struct dns_hook_entry *dns_hook_entries;
static size_t dns_hook_nentries; static size_t dns_hook_nentries;
static char received_title_url[255];
static void dns_hook_init(void) static void dns_hook_init(void)
{ {
@ -145,6 +186,43 @@ static void dns_hook_init(void)
"ws2_32.dll", "ws2_32.dll",
dns_hook_syms_ws2, dns_hook_syms_ws2,
_countof(dns_hook_syms_ws2)); _countof(dns_hook_syms_ws2));
hook_table_apply(
NULL,
"winhttp.dll",
dns_hook_syms_winhttp,
_countof(dns_hook_syms_winhttp));
}
// This function match domain and subdomains like *.naominet.jp.
bool match_domain(const wchar_t* target, const wchar_t* pattern) {
if (_wcsicmp(pattern, target) == 0) {
return true;
}
int pattern_ptr_index = 0;
int target_ptr_index = 0;
while (pattern[pattern_ptr_index] != '\0' && target[target_ptr_index] != '\0') {
if (pattern[pattern_ptr_index] == '*') {
pattern_ptr_index++; // Check next character for wildcard match.
while (pattern[pattern_ptr_index] != target[target_ptr_index]) {
target_ptr_index++;
if (target[target_ptr_index] == '\0') return false;
}
}
else if (pattern[pattern_ptr_index] != target[target_ptr_index]) {
return false;
}
else {
pattern_ptr_index++;
target_ptr_index++;
}
}
return pattern[pattern_ptr_index] == '\0' && target[target_ptr_index] == '\0';
} }
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src) HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src)
@ -250,7 +328,7 @@ static DNS_STATUS WINAPI hook_DnsQuery_A(
for (i = 0 ; i < dns_hook_nentries ; i++) { for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i]; pos = &dns_hook_entries[i];
if (_wcsicmp(wstr, pos->from) == 0) { if (match_domain(wstr, pos->from)) {
if(pos->to == NULL) { if(pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock); LeaveCriticalSection(&dns_hook_lock);
hr = HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR); hr = HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR);
@ -314,7 +392,7 @@ static DNS_STATUS WINAPI hook_DnsQuery_W(
for (i = 0 ; i < dns_hook_nentries ; i++) { for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i]; pos = &dns_hook_entries[i];
if (_wcsicmp(pszName, pos->from) == 0) { if (match_domain(pszName, pos->from)) {
if(pos->to == NULL) { if(pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock); LeaveCriticalSection(&dns_hook_lock);
return HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR); return HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR);
@ -358,7 +436,7 @@ static DNS_STATUS WINAPI hook_DnsQueryEx(
for (i = 0 ; i < dns_hook_nentries ; i++) { for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i]; pos = &dns_hook_entries[i];
if (_wcsicmp(pRequest->QueryName, pos->from) == 0) { if (match_domain(pRequest->QueryName, pos->from)) {
if(pos->to == NULL) { if(pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock); LeaveCriticalSection(&dns_hook_lock);
return HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR); return HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR);
@ -425,7 +503,7 @@ static int WSAAPI hook_getaddrinfo(
for (i = 0 ; i < dns_hook_nentries ; i++) { for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i]; pos = &dns_hook_entries[i];
if (_wcsicmp(wstr, pos->from) == 0) { if (match_domain(wstr, pos->from)) {
if(pos->to == NULL) { if(pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock); LeaveCriticalSection(&dns_hook_lock);
result = EAI_NONAME; result = EAI_NONAME;
@ -460,3 +538,83 @@ end:
return result; return result;
} }
static HINTERNET WINAPI hook_WinHttpConnect(
HINTERNET hSession,
const wchar_t *pwszServerName,
INTERNET_PORT nServerPort,
DWORD dwReserved)
{
const struct dns_hook_entry *pos;
size_t i;
if (pwszServerName == NULL) {
return NULL;
}
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(pwszServerName, pos->from)) {
if(pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock);
return NULL;
}
pwszServerName = pos->to;
break;
}
}
LeaveCriticalSection(&dns_hook_lock);
return next_WinHttpConnect(hSession, pwszServerName, nServerPort, dwReserved);
}
// Hook to replace CXB title url
static bool WINAPI hook_WinHttpCrackUrl(
const wchar_t *pwszUrl,
DWORD dwUrlLength,
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents)
{
const struct dns_hook_entry *pos;
size_t i;
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(pwszUrl, pos->from)) {
wchar_t* toAddr = pos->to;
wchar_t titleBuffer[255];
if(wcscmp(toAddr, L"title") == 0) {
size_t wstr_c;
mbstowcs_s(&wstr_c, titleBuffer, 255, received_title_url, strlen(received_title_url));
toAddr = titleBuffer;
}
bool result = next_WinHttpCrackUrl(
toAddr,
wcslen(toAddr),
dwFlags,
lpUrlComponents
);
LeaveCriticalSection(&dns_hook_lock);
return result;
}
}
LeaveCriticalSection(&dns_hook_lock);
return next_WinHttpCrackUrl(
pwszUrl,
dwUrlLength,
dwFlags,
lpUrlComponents
);
}

View File

@ -23,8 +23,6 @@ hooklib_lib = static_library(
'fdshark.h', 'fdshark.h',
'path.c', 'path.c',
'path.h', 'path.h',
'procaddr.c',
'procaddr.h',
'reg.c', 'reg.c',
'reg.h', 'reg.h',
'setupapi.c', 'setupapi.c',

View File

@ -101,6 +101,40 @@ static BOOL WINAPI hook_PathFileExistsA(LPCSTR pszPath);
static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath); static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath);
static BOOL WINAPI hook_MoveFileA(
const char *lpExistingFileName,
const char *lpNewFileName);
static BOOL WINAPI hook_MoveFileW(
const wchar_t *lpExistingFileName,
const wchar_t *lpNewFileName);
static BOOL WINAPI hook_MoveFileExA(
const char *lpExistingFileName,
const char *lpNewFileName,
uint32_t dwFlags);
static BOOL WINAPI hook_ReplaceFileA(
const char *lpReplacedFileName,
const char *lpReplacementFileName,
const char *lpBackupFileName,
uint32_t dwReplaceFlags,
void *lpExclude,
void *lpReserved);
static BOOL WINAPI hook_ReplaceFileW(
const wchar_t *lpReplacedFileName,
const wchar_t *lpReplacementFileName,
const wchar_t *lpBackupFileName,
uint32_t dwReplaceFlags,
void *lpExclude,
void *lpReserved);
static BOOL WINAPI hook_DeleteFileA(const char *lpFileName);
static BOOL WINAPI hook_DeleteFileW(const wchar_t *lpFileName);
/* Link pointers */ /* Link pointers */
static BOOL (WINAPI *next_CreateDirectoryA)( static BOOL (WINAPI *next_CreateDirectoryA)(
@ -185,6 +219,39 @@ static BOOL (WINAPI *next_PathFileExistsA)(LPCSTR pszPath);
static BOOL (WINAPI *next_PathFileExistsW)(LPCWSTR pszPath); static BOOL (WINAPI *next_PathFileExistsW)(LPCWSTR pszPath);
static BOOL (WINAPI *next_MoveFileA)(
const char *lpExistingFileName,
const char *lpNewFileName);
static BOOL (WINAPI *next_MoveFileW)(
const wchar_t *lpExistingFileName,
const wchar_t *lpNewFileName);
static BOOL (WINAPI *next_MoveFileExA)(
const char *lpExistingFileName,
const char *lpNewFileName,
uint32_t dwFlags);
static BOOL (WINAPI *next_ReplaceFileA)(
const char *lpReplacedFileName,
const char *lpReplacementFileName,
const char *lpBackupFileName,
uint32_t dwReplaceFlags,
void *lpExclude,
void *lpReserved);
static BOOL (WINAPI *next_ReplaceFileW)(
const wchar_t *lpReplacedFileName,
const wchar_t *lpReplacementFileName,
const wchar_t *lpBackupFileName,
uint32_t dwReplaceFlags,
void *lpExclude,
void *lpReserved);
static BOOL (WINAPI *next_DeleteFileA)(const char *lpFileName);
static BOOL (WINAPI *next_DeleteFileW)(const wchar_t *lpFileName);
/* Hook table */ /* Hook table */
static const struct hook_symbol path_hook_syms[] = { static const struct hook_symbol path_hook_syms[] = {
@ -260,6 +327,34 @@ static const struct hook_symbol path_hook_syms[] = {
.name = "PathFileExistsW", .name = "PathFileExistsW",
.patch = hook_PathFileExistsW, .patch = hook_PathFileExistsW,
.link = (void **) &next_PathFileExistsW, .link = (void **) &next_PathFileExistsW,
}, {
.name = "MoveFileA",
.patch = hook_MoveFileA,
.link = (void **) &next_MoveFileA,
}, {
.name = "MoveFileW",
.patch = hook_MoveFileW,
.link = (void **) &next_MoveFileW,
}, {
.name = "MoveFileExA",
.patch = hook_MoveFileExA,
.link = (void **) &next_MoveFileExA,
}, {
.name = "ReplaceFileA",
.patch = hook_ReplaceFileA,
.link = (void **) &next_ReplaceFileA,
}, {
.name = "ReplaceFileW",
.patch = hook_ReplaceFileW,
.link = (void **) &next_ReplaceFileW,
}, {
.name = "DeleteFileA",
.patch = hook_DeleteFileA,
.link = (void **) &next_DeleteFileA,
}, {
.name = "DeleteFileW",
.patch = hook_DeleteFileW,
.link = (void **) &next_DeleteFileW,
} }
}; };
@ -906,3 +1001,213 @@ static BOOL WINAPI hook_PathFileExistsW(LPCWSTR pszPath)
return ok; return ok;
} }
static BOOL WINAPI hook_MoveFileA(
const char *lpExistingFileName,
const char *lpNewFileName)
{
char *oldTrans;
char *newTrans;
BOOL ok;
ok = path_transform_a(&oldTrans, lpExistingFileName);
if (!ok) {
return FALSE;
}
ok = path_transform_a(&newTrans, lpNewFileName);
if (!ok) {
free(oldTrans);
return FALSE;
}
ok = next_MoveFileA(
oldTrans ? oldTrans : lpExistingFileName,
newTrans ? newTrans : lpNewFileName);
free(oldTrans);
free(newTrans);
return ok;
}
static BOOL WINAPI hook_MoveFileW(
const wchar_t *lpExistingFileName,
const wchar_t *lpNewFileName)
{
wchar_t *oldTrans;
wchar_t *newTrans;
BOOL ok;
ok = path_transform_w(&oldTrans, lpExistingFileName);
if (!ok) {
return FALSE;
}
ok = path_transform_w(&newTrans, lpNewFileName);
if (!ok) {
free(oldTrans);
return FALSE;
}
ok = next_MoveFileW(
oldTrans ? oldTrans : lpExistingFileName,
newTrans ? newTrans : lpNewFileName);
free(oldTrans);
free(newTrans);
return ok;
}
static BOOL WINAPI hook_MoveFileExA(
const char *lpExistingFileName,
const char *lpNewFileName,
uint32_t dwFlags)
{
char *oldTrans;
char *newTrans;
BOOL ok;
ok = path_transform_a(&oldTrans, lpExistingFileName);
if (!ok) {
return FALSE;
}
ok = path_transform_a(&newTrans, lpNewFileName);
if (!ok) {
free(oldTrans);
return FALSE;
}
ok = next_MoveFileExA(
oldTrans ? oldTrans : lpExistingFileName,
newTrans ? newTrans : lpNewFileName,
dwFlags);
free(oldTrans);
free(newTrans);
return ok;
}
static BOOL WINAPI hook_ReplaceFileA(
const char *lpReplacedFileName,
const char *lpReplacementFileName,
const char *lpBackupFileName,
uint32_t dwReplaceFlags,
void *lpExclude,
void *lpReserved)
{
char *oldTrans;
char *newTrans;
BOOL ok;
ok = path_transform_a(&oldTrans, lpReplacedFileName);
if (!ok) {
return FALSE;
}
ok = path_transform_a(&newTrans, lpReplacementFileName);
if (!ok) {
free(oldTrans);
return FALSE;
}
ok = next_ReplaceFileA(
oldTrans ? oldTrans : lpReplacedFileName,
newTrans ? newTrans : lpReplacementFileName,
lpBackupFileName,
dwReplaceFlags,
lpExclude,
lpReserved);
free(oldTrans);
free(newTrans);
return ok;
}
static BOOL WINAPI hook_ReplaceFileW(
const wchar_t *lpReplacedFileName,
const wchar_t *lpReplacementFileName,
const wchar_t *lpBackupFileName,
uint32_t dwReplaceFlags,
void *lpExclude,
void *lpReserved)
{
wchar_t *oldTrans;
wchar_t *newTrans;
BOOL ok;
ok = path_transform_w(&oldTrans, lpReplacedFileName);
if (!ok) {
return FALSE;
}
ok = path_transform_w(&newTrans, lpReplacementFileName);
if (!ok) {
free(oldTrans);
return FALSE;
}
ok = next_ReplaceFileW(
oldTrans ? oldTrans : lpReplacedFileName,
newTrans ? newTrans : lpReplacementFileName,
lpBackupFileName,
dwReplaceFlags,
lpExclude,
lpReserved);
free(oldTrans);
free(newTrans);
return ok;
}
static BOOL WINAPI hook_DeleteFileA(const char *lpFileName)
{
char *trans;
BOOL ok;
ok = path_transform_a(&trans, lpFileName);
if (!ok) {
return FALSE;
}
ok = next_DeleteFileA(trans ? trans: lpFileName);
return ok;
}
static BOOL WINAPI hook_DeleteFileW(const wchar_t *lpFileName)
{
wchar_t *trans;
BOOL ok;
ok = path_transform_w(&trans, lpFileName);
if (!ok) {
return FALSE;
}
ok = next_DeleteFileW(trans ? trans: lpFileName);
return ok;
}

View File

@ -1,125 +0,0 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <libgen.h>
#include "hooklib/procaddr.h"
#include "hook/table.h"
#include "util/dprintf.h"
static struct proc_addr_table *proc_addr_hook_list;
static size_t proc_addr_hook_count;
static CRITICAL_SECTION proc_addr_hook_lock;
static bool proc_addr_hook_initted;
static FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name);
static FARPROC (WINAPI *next_GetProcAddress)(HMODULE hModule, const char *name);
static void proc_addr_hook_init(void);
static const struct hook_symbol win32_hooks[] = {
{
.name = "GetProcAddress",
.patch = my_GetProcAddress,
.link = (void **) &next_GetProcAddress
}
};
HRESULT proc_addr_table_push(
const char *target,
struct hook_symbol *syms,
size_t nsyms
)
{
HRESULT hr;
struct proc_addr_table *new_item;
struct proc_addr_table *new_mem;
proc_addr_hook_init();
EnterCriticalSection(&proc_addr_hook_lock);
new_mem = realloc(
proc_addr_hook_list,
(proc_addr_hook_count + 1) * sizeof(struct proc_addr_table));
if (new_mem == NULL) {
hr = E_OUTOFMEMORY;
LeaveCriticalSection(&proc_addr_hook_lock);
return hr;
}
new_item = &new_mem[proc_addr_hook_count];
new_item->name = target;
new_item->nsyms = nsyms;
new_item->syms = syms;
proc_addr_hook_list = new_mem;
proc_addr_hook_count++;
hr = S_OK;
LeaveCriticalSection(&proc_addr_hook_lock);
return hr;
}
static void proc_addr_hook_init(void)
{
if (proc_addr_hook_initted) {
return;
}
dprintf("ProcAddr: Hook init\n");
proc_addr_hook_initted = true;
InitializeCriticalSection(&proc_addr_hook_lock);
hook_table_apply(
NULL,
"kernel32.dll",
win32_hooks,
_countof(win32_hooks));
}
FARPROC WINAPI my_GetProcAddress(HMODULE hModule, const char *name)
{
uintptr_t ordinal = (uintptr_t) name;
char mod_path[PATH_MAX];
char *mod_name;
const struct hook_symbol *sym;
FARPROC result = next_GetProcAddress(hModule, name);
GetModuleFileNameA(hModule, mod_path, PATH_MAX);
mod_name = basename(mod_path);
for (int i = 0; i < proc_addr_hook_count; i++) {
if (strcmp(proc_addr_hook_list[i].name, mod_name) == 0) {
for (int j = 0; j < proc_addr_hook_list[i].nsyms; j++) {
sym = &proc_addr_hook_list[i].syms[j];
if (ordinal > 0xFFFF) {
if (strcmp(sym->name, name) == 0) {
dprintf("ProcAddr: Hooking %s from %s\n", name, mod_name);
result = (FARPROC) sym->patch;
}
}
else {
if (sym->ordinal == ordinal) {
dprintf("ProcAddr: Hooking Ord %p from %s\n", (void *)ordinal, mod_name);
result = (FARPROC) sym->patch;
}
}
}
}
}
return result;
}

View File

@ -1,18 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include "hook/table.h"
struct proc_addr_table {
const char *name;
size_t nsyms;
struct hook_symbol *syms;
};
HRESULT proc_addr_table_push(
const char *target,
struct hook_symbol *syms,
size_t nsyms
);

View File

@ -7,6 +7,7 @@
#include "hook/table.h" #include "hook/table.h"
#include "hooklib/reg.h" #include "hooklib/reg.h"
#include "hook/procaddr.h"
#include "util/dprintf.h" #include "util/dprintf.h"
#include "util/str.h" #include "util/str.h"
@ -99,6 +100,29 @@ static LSTATUS WINAPI hook_RegGetValueW(
uint32_t *numData uint32_t *numData
); );
static LSTATUS WINAPI hook_RegQueryInfoKeyW(
HKEY hKey,
LPWSTR lpClass,
LPDWORD lpcchClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime);
static LSTATUS WINAPI hook_RegEnumValueW(
HKEY hkey,
DWORD dwIndex,
LPWSTR lpValueName,
LPDWORD lpcchValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData);
/* Link pointers */ /* Link pointers */
static LSTATUS (WINAPI *next_RegOpenKeyExW)( static LSTATUS (WINAPI *next_RegOpenKeyExW)(
@ -155,6 +179,30 @@ static LSTATUS (WINAPI *next_RegGetValueW)(
uint32_t *numData uint32_t *numData
); );
static LSTATUS (WINAPI *next_RegQueryInfoKeyW)(
HKEY hKey,
LPWSTR lpClass,
LPDWORD lpcchClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime);
static LSTATUS (WINAPI *next_RegEnumValueW)(
HKEY hkey,
DWORD dwIndex,
LPWSTR lpValueName,
LPDWORD lpcchValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData);
static const struct hook_symbol reg_hook_syms[] = { static const struct hook_symbol reg_hook_syms[] = {
{ {
.name = "RegOpenKeyExW", .name = "RegOpenKeyExW",
@ -184,6 +232,14 @@ static const struct hook_symbol reg_hook_syms[] = {
.name = "RegGetValueW", .name = "RegGetValueW",
.patch = hook_RegGetValueW, .patch = hook_RegGetValueW,
.link = (void **) &next_RegGetValueW, .link = (void **) &next_RegGetValueW,
}, {
.name = "RegQueryInfoKeyW",
.patch = hook_RegQueryInfoKeyW,
.link = (void **) &next_RegQueryInfoKeyW,
}, {
.name = "RegEnumValueW",
.patch = hook_RegEnumValueW,
.link = (void **) &next_RegEnumValueW,
} }
}; };
@ -254,11 +310,24 @@ static void reg_hook_init(void)
InitializeCriticalSection(&reg_hook_lock); InitializeCriticalSection(&reg_hook_lock);
dprintf("Reg hook init\n"); dprintf("Reg hook init\n");
reg_hook_insert_hooks(NULL);
proc_addr_table_push(
NULL,
"ADVAPI32.dll",
(struct hook_symbol *) reg_hook_syms,
_countof(reg_hook_syms));
}
void reg_hook_insert_hooks(HMODULE target)
{
hook_table_apply( hook_table_apply(
NULL, target,
"advapi32.dll", "advapi32.dll",
reg_hook_syms, reg_hook_syms,
_countof(reg_hook_syms)); _countof(reg_hook_syms));
} }
static LRESULT reg_hook_propagate_hr(HRESULT hr) static LRESULT reg_hook_propagate_hr(HRESULT hr)
@ -331,6 +400,7 @@ static LSTATUS reg_hook_open_locked(
/* Assume reg keys are referenced from a root key and not from some /* Assume reg keys are referenced from a root key and not from some
intermediary key */ intermediary key */
key = &reg_hook_keys[i]; key = &reg_hook_keys[i];
//dprintf("Reg: %ls vs %ls\n", name, key->name);
if (key->root == parent && wstr_ieq(key->name, name)) { if (key->root == parent && wstr_ieq(key->name, name)) {
break; break;
@ -821,6 +891,99 @@ static LSTATUS WINAPI hook_RegGetValueW(
return err; return err;
} }
static LSTATUS WINAPI hook_RegQueryInfoKeyW(
HKEY hKey,
LPWSTR lpClass,
LPDWORD lpcchClass,
LPDWORD lpReserved,
LPDWORD lpcSubKeys,
LPDWORD lpcbMaxSubKeyLen,
LPDWORD lpcbMaxClassLen,
LPDWORD lpcValues,
LPDWORD lpcbMaxValueNameLen,
LPDWORD lpcbMaxValueLen,
LPDWORD lpcbSecurityDescriptor,
PFILETIME lpftLastWriteTime)
{
struct reg_hook_key *key;
LSTATUS err;
EnterCriticalSection(&reg_hook_lock);
key = reg_hook_match_key_locked(hKey);
/* Check if this is a virtualized registry key */
if (key == NULL) {
LeaveCriticalSection(&reg_hook_lock);
return next_RegQueryInfoKeyW(
hKey,
lpClass,
lpcchClass,
lpReserved,
lpcSubKeys,
lpcbMaxSubKeyLen,
lpcbMaxClassLen,
lpcValues,
lpcbMaxValueNameLen,
lpcbMaxValueLen,
lpcbSecurityDescriptor,
lpftLastWriteTime);
}
// This is the only one I've seen even be changed, so it's all I'm doing
// until I see otherwise.
*lpcValues = key->nvals;
LeaveCriticalSection(&reg_hook_lock);
return ERROR_SUCCESS;
}
static LSTATUS WINAPI hook_RegEnumValueW(
HKEY hkey,
DWORD dwIndex,
LPWSTR lpValueName,
LPDWORD lpcchValueName,
LPDWORD lpReserved,
LPDWORD lpType,
LPBYTE lpData,
LPDWORD lpcbData)
{
struct reg_hook_key *key;
HRESULT hr;
LSTATUS err;
EnterCriticalSection(&reg_hook_lock);
key = reg_hook_match_key_locked(hkey);
/* Check if this is a virtualized registry key */
if (key == NULL) {
LeaveCriticalSection(&reg_hook_lock);
return next_RegEnumValueW(
hkey,
dwIndex,
lpValueName,
lpcchValueName,
lpReserved,
lpType,
lpData,
lpcbData);
}
if (dwIndex >= key->nvals) {
LeaveCriticalSection(&reg_hook_lock);
return ERROR_NO_MORE_ITEMS; // Pretty sure this is what it actually returns here?
}
wcscpy_s(lpValueName, *lpcchValueName, key->vals[dwIndex].name);
*lpcchValueName = wcslen(key->vals[dwIndex].name);
LeaveCriticalSection(&reg_hook_lock);
return ERROR_SUCCESS;
}
HRESULT reg_hook_read_bin( HRESULT reg_hook_read_bin(
void *bytes, void *bytes,
uint32_t *nbytes, uint32_t *nbytes,

View File

@ -12,6 +12,8 @@ struct reg_hook_val {
uint32_t type; uint32_t type;
}; };
void reg_hook_insert_hooks(HMODULE target);
HRESULT reg_hook_push_key( HRESULT reg_hook_push_key(
HKEY root, HKEY root,
const wchar_t *name, const wchar_t *name,

View File

@ -119,10 +119,19 @@ void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE sel
defaultCursor = LoadCursorA(NULL, IDC_CROSS); defaultCursor = LoadCursorA(NULL, IDC_CROSS);
memcpy(&touch_config, cfg, sizeof(*cfg)); memcpy(&touch_config, cfg, sizeof(*cfg));
hook_table_apply(NULL, "user32.dll", touch_hooks, _countof(touch_hooks)); touch_hook_insert_hooks(NULL);
dprintf("TOUCH: hook enabled.\n"); dprintf("TOUCH: hook enabled.\n");
} }
void touch_hook_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"user32.dll",
touch_hooks,
_countof(touch_hooks));
}
static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) { static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) {
if (cursor == 0 && touch_config.cursor) if (cursor == 0 && touch_config.cursor)
return next_SetCursor(defaultCursor); return next_SetCursor(defaultCursor);

View File

@ -14,3 +14,4 @@ struct touch_screen_config {
blah blah you know the drill by now. */ blah blah you know the drill by now. */
void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self); void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self);
void touch_hook_insert_hooks(HMODULE target);

View File

@ -13,6 +13,43 @@
#include "platform/config.h" #include "platform/config.h"
#include "platform/platform.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( void idac_dll_config_load(
struct idac_dll_config *cfg, struct idac_dll_config *cfg,
const wchar_t *filename) const wchar_t *filename)
@ -29,6 +66,16 @@ void idac_dll_config_load(
filename); 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( void idac_hook_config_load(
struct idac_hook_config *cfg, struct idac_hook_config *cfg,
const wchar_t *filename) const wchar_t *filename)
@ -42,6 +89,8 @@ void idac_hook_config_load(
zinput_config_load(&cfg->zinput, filename); zinput_config_load(&cfg->zinput, filename);
dvd_config_load(&cfg->dvd, filename); dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, 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) void zinput_config_load(struct zinput_config *cfg, const wchar_t *filename)

View File

@ -4,11 +4,13 @@
#include <stddef.h> #include <stddef.h>
#include "board/config.h" #include "board/config.h"
#include "board/led15070.h"
#include "hooklib/dvd.h" #include "hooklib/dvd.h"
#include "idachook/idac-dll.h" #include "idachook/idac-dll.h"
#include "idachook/zinput.h" #include "idachook/zinput.h"
#include "idachook/indrun.h"
#include "platform/platform.h" #include "platform/platform.h"
@ -19,6 +21,8 @@ struct idac_hook_config {
struct io4_config io4; struct io4_config io4;
struct idac_dll_config dll; struct idac_dll_config dll;
struct zinput_config zinput; struct zinput_config zinput;
struct led15070_config led15070;
struct indrun_config indrun;
}; };
void idac_dll_config_load( void idac_dll_config_load(
@ -29,4 +33,10 @@ void idac_hook_config_load(
struct idac_hook_config *cfg, struct idac_hook_config *cfg,
const wchar_t *filename); 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);

View File

@ -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 <windows.h>
#include <shlwapi.h> #include <shlwapi.h>
@ -53,13 +66,13 @@ static DWORD CALLBACK idac_pre_startup(void)
goto fail; 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)) { if (FAILED(hr)) {
goto fail; 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)) { if (FAILED(hr)) {
goto fail; goto fail;
@ -71,6 +84,20 @@ static DWORD CALLBACK idac_pre_startup(void)
goto fail; 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 */ /* Initialize debug helpers */
spike_hook_init(L".\\segatools.ini"); spike_hook_init(L".\\segatools.ini");

View File

@ -12,9 +12,6 @@ const struct dll_bind_sym idac_dll_syms[] = {
{ {
.sym = "idac_io_init", .sym = "idac_io_init",
.off = offsetof(struct idac_dll, init), .off = offsetof(struct idac_dll, init),
}, {
.sym = "idac_io_poll",
.off = offsetof(struct idac_dll, poll),
}, { }, {
.sym = "idac_io_get_opbtns", .sym = "idac_io_get_opbtns",
.off = offsetof(struct idac_dll, get_opbtns), .off = offsetof(struct idac_dll, get_opbtns),
@ -27,6 +24,18 @@ const struct dll_bind_sym idac_dll_syms[] = {
}, { }, {
.sym = "idac_io_get_analogs", .sym = "idac_io_get_analogs",
.off = offsetof(struct idac_dll, 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),
} }
}; };

View File

@ -7,11 +7,14 @@
struct idac_dll { struct idac_dll {
uint16_t api_version; uint16_t api_version;
HRESULT (*init)(void); HRESULT (*init)(void);
HRESULT (*poll)(void);
void (*get_opbtns)(uint8_t *opbtn); void (*get_opbtns)(uint8_t *opbtn);
void (*get_gamebtns)(uint8_t *gamebtn); void (*get_gamebtns)(uint8_t *gamebtn);
void (*get_shifter)(uint8_t *gear); void (*get_shifter)(uint8_t *gear);
void (*get_analogs)(struct idac_io_analog_state *out); 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 { struct idac_dll_config {

View File

@ -13,8 +13,11 @@ EXPORTS
amDllVideoSetResolution @3 amDllVideoSetResolution @3
idac_io_get_api_version idac_io_get_api_version
idac_io_init idac_io_init
idac_io_poll
idac_io_get_opbtns idac_io_get_opbtns
idac_io_get_gamebtns idac_io_get_gamebtns
idac_io_get_shifter idac_io_get_shifter
idac_io_get_analogs 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
View 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
View File

@ -0,0 +1,9 @@
#pragma once
#include <windows.h>
struct indrun_config {
bool enable;
};
void indrun_hook_init(struct indrun_config *cfg);

View File

@ -11,10 +11,12 @@
#include "util/dprintf.h" #include "util/dprintf.h"
static HRESULT idac_io4_poll(void *ctx, struct io4_state *state); 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 uint16_t coins;
static const struct io4_ops idac_io4_ops = { static const struct io4_ops idac_io4_ops = {
.poll = idac_io4_poll, .poll = idac_io4_poll,
.write_gpio = idac_io4_write_gpio
}; };
static const uint16_t idac_gear_signals[] = { static const uint16_t idac_gear_signals[] = {
@ -57,7 +59,6 @@ static HRESULT idac_io4_poll(void *ctx, struct io4_state *state)
struct idac_io_analog_state analog_state; struct idac_io_analog_state analog_state;
HRESULT hr; HRESULT hr;
assert(idac_dll.poll != NULL);
assert(idac_dll.get_opbtns != NULL); assert(idac_dll.get_opbtns != NULL);
assert(idac_dll.get_gamebtns != NULL); assert(idac_dll.get_gamebtns != NULL);
assert(idac_dll.get_analogs != NULL); assert(idac_dll.get_analogs != NULL);
@ -65,13 +66,6 @@ static HRESULT idac_io4_poll(void *ctx, struct io4_state *state)
memset(state, 0, sizeof(*state)); memset(state, 0, sizeof(*state));
memset(&analog_state, 0, sizeof(analog_state)); memset(&analog_state, 0, sizeof(analog_state));
hr = idac_dll.poll();
if (FAILED(hr)) {
return hr;
}
opbtn = 0; opbtn = 0;
gamebtn = 0; gamebtn = 0;
gear = 0; gear = 0;
@ -136,3 +130,34 @@ static HRESULT idac_io4_poll(void *ctx, struct io4_state *state)
return S_OK; 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;
}

Some files were not shown because too many files have changed in this diff Show More