Compare commits

..

No commits in common. "develop" and "develop" have entirely different histories.

248 changed files with 1965 additions and 12016 deletions

3
.gitignore vendored
View File

@ -18,6 +18,3 @@ build/
# External dependencies
subprojects/capnhook
# For enabling debug logging on local builds
MesonLocalOptions.mk

View File

@ -11,11 +11,6 @@ DOC_DIR := doc
DIST_DIR := dist
# Add "-D[option]=[value]" here as necessary
MESON_OPTIONS :=
# For options that shouldn't be committed
-include MesonLocalOptions.mk
# -----------------------------------------------------------------------------
# Targets
# -----------------------------------------------------------------------------
@ -24,9 +19,9 @@ include Package.mk
.PHONY: build # Build the project
build:
$(V)meson setup $(MESON_OPTIONS) --cross cross-mingw-32.txt $(BUILD_DIR_32)
$(V)meson --cross cross-mingw-32.txt $(BUILD_DIR_32)
$(V)ninja -C $(BUILD_DIR_32)
$(V)meson setup $(MESON_OPTIONS) --cross cross-mingw-64.txt $(BUILD_DIR_64)
$(V)meson --cross cross-mingw-64.txt $(BUILD_DIR_64)
$(V)ninja -C $(BUILD_DIR_64)
.PHONY: dist # Build and create a zip distribution package

View File

@ -203,43 +203,6 @@ $(BUILD_DIR_ZIP)/cm.zip:
$(V)strip $(BUILD_DIR_ZIP)/cm/*.{exe,dll}
$(V)cd $(BUILD_DIR_ZIP)/cm ; zip -r ../cm.zip *
$(BUILD_DIR_ZIP)/tokyo.zip:
$(V)echo ... $@
$(V)mkdir -p $(BUILD_DIR_ZIP)/tokyo
$(V)mkdir -p $(BUILD_DIR_ZIP)/tokyo/DEVICE
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
$(BUILD_DIR_64)/tokyohook/tokyohook.dll \
$(DIST_DIR)/tokyo/config_hook.json \
$(DIST_DIR)/tokyo/segatools.ini \
$(DIST_DIR)/tokyo/start.bat \
$(BUILD_DIR_ZIP)/tokyo
$(V)cp pki/billing.pub \
pki/ca.crt \
$(BUILD_DIR_ZIP)/tokyo/DEVICE
$(V)strip $(BUILD_DIR_ZIP)/tokyo/*.{exe,dll}
$(V)cd $(BUILD_DIR_ZIP)/tokyo ; zip -r ../tokyo.zip *
$(BUILD_DIR_ZIP)/kemono.zip:
$(V)echo ... $@
$(V)mkdir -p $(BUILD_DIR_ZIP)/kemono
$(V)mkdir -p $(BUILD_DIR_ZIP)/kemono/DEVICE
$(V)cp $(DIST_DIR)/kemono/segatools.ini \
$(DIST_DIR)/kemono/start.bat \
$(BUILD_DIR_ZIP)/kemono
$(V)cp $(BUILD_DIR_32)/kemonohook/kemonohook.dll \
$(BUILD_DIR_ZIP)/kemono/kemonohook_x86.dll
$(V)cp $(BUILD_DIR_64)/kemonohook/kemonohook.dll \
$(BUILD_DIR_ZIP)/kemono/kemonohook_x64.dll
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject.exe \
$(BUILD_DIR_ZIP)/kemono/inject_x86.exe
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
$(BUILD_DIR_ZIP)/kemono/inject_x64.exe
$(V)cp pki/billing.pub \
pki/ca.crt \
$(BUILD_DIR_ZIP)/kemono/DEVICE
for x in exe dll; do strip $(BUILD_DIR_ZIP)/kemono/*.$$x; done
$(V)cd $(BUILD_DIR_ZIP)/kemono ; zip -r ../kemono.zip *
$(BUILD_DIR_ZIP)/doc.zip: \
$(DOC_DIR)/config \
$(DOC_DIR)/chunihook.md \
@ -262,9 +225,7 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
$(BUILD_DIR_ZIP)/mu3.zip \
$(BUILD_DIR_ZIP)/mai2.zip \
$(BUILD_DIR_ZIP)/cm.zip \
$(BUILD_DIR_ZIP)/tokyo.zip \
$(BUILD_DIR_ZIP)/fgo.zip \
$(BUILD_DIR_ZIP)/kemono.zip \
CHANGELOG.md \
README.md \

View File

@ -1,37 +1,33 @@
# Segatools
Version: `2024-09-30`
Version: `2024-03-13`
Loaders and hardware emulators for SEGA games that run on the Nu and ALLS platforms.
## List of supported games
* Card Maker
* starting from Card Maker
* CHUNITHM
* up to [CHUNITHM PARADISE LOST](doc/chunihook.md)
* starting from CHUNITHM NEW!!
* crossbeats REV.
* up to crossbeats REV. SUNRISE
* Fate/Grand Order
* Fate/Grand Order Arcade
* Hatsune Miku: Project DIVA Arcade
* up to Future Tone
* Initial D
* [Initial D Arcade Stage Zero](doc/idzhook.md)
* Initial D THE ARCADE
* maimai DX
* starting from maimai DX
* Mario & Sonic
* Mario & Sonic at the Tokyo 2020 Olympics Arcade
* O.N.G.E.K.I.
* starting from O.N.G.E.K.I.
* Hatsune Miku: Project DIVA Arcade
* up to Future Tone
* SEGA World Drivers Championship
* SEGA World Drivers Championship 2019
* Fate/Grand Order
* Fate/Grand Order Arcade
* O.N.G.E.K.I.
* starting from O.N.G.E.K.I.
* maimai DX
* starting from maimai DX
* Card Maker
* starting from Card Maker
* WACCA
* starting from WACCA
* Kemono Friends
* Kemono Friends 3: Planet Tours
## End-users

View File

@ -185,14 +185,14 @@ static HRESULT jvs_ioctl_sense(struct irp *irp)
static HRESULT jvs_ioctl_transact(struct irp *irp)
{
#if defined(LOG_JVS)
#if 0
dprintf("\nJVS Port: Outbound frame:\n");
dump_const_iobuf(&irp->write);
#endif
jvs_bus_transact(jvs_root, irp->write.bytes, irp->write.nbytes, &irp->read);
#if defined(LOG_JVS)
#if 0
dprintf("JVS Port: Inbound frame:\n");
dump_iobuf(&irp->read);
dprintf("\n");

View File

@ -90,14 +90,4 @@ void vfd_config_load(struct vfd_config *cfg, const wchar_t *filename)
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"vfd", L"enable", 1, filename);
cfg->port = GetPrivateProfileIntW(L"vfd", L"portNo", 0, filename);
cfg->utf_conversion = GetPrivateProfileIntW(L"vfd", L"utfConversion", 0, filename);
}
void ffb_config_load(struct ffb_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"ffb", L"enable", 1, filename);
}

View File

@ -6,9 +6,7 @@
#include "board/io4.h"
#include "board/sg-reader.h"
#include "board/vfd.h"
#include "board/ffb.h"
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 vfd_config_load(struct vfd_config *cfg, const wchar_t *filename);
void ffb_config_load(struct ffb_config *cfg, const wchar_t *filename);

View File

@ -1,235 +0,0 @@
/*
Force Feedback Board (FFB)
This board is used by many SEGA games to provide force feedback to the player.
It is driven by the game software over a serial connection and is used by many
games such as SEGA World Drivers Championship, Initial D Arcade, ...
Part number in schematics is "838-15069 MOTOR DRIVE BD RS232/422 Board".
Some observations:
The maximal strength for any effect is 127, except Damper which maxes out at 40.
The period for rumble effects is in the range 0-40.
*/
#include "board/ffb.h"
#include <assert.h>
#include <stdint.h>
#include <windows.h>
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "util/dprintf.h"
#include "util/dump.h"
// request format:
// 0x?? - sync + command
// 0x?? - direction/additional command
// 0x?? - strength
// 0x?? - checksum (sum of everything except the sync byte)
enum {
FFB_CMD_TOGGLE = 0x80,
FFB_CMD_CONSTANT_FORCE = 0x84,
FFB_CMD_RUMBLE = 0x85,
FFB_CMD_DAMPER = 0x86,
};
struct ffb_hdr {
uint8_t cmd;
};
union ffb_req_any {
struct ffb_hdr hdr;
uint8_t bytes[3];
};
static HRESULT ffb_handle_irp(struct irp *irp);
static HRESULT ffb_req_dispatch(const union ffb_req_any *req);
static HRESULT ffb_req_toggle(const uint8_t *bytes);
static HRESULT ffb_req_constant_force(const uint8_t *bytes);
static HRESULT ffb_req_rumble(const uint8_t *bytes);
static HRESULT ffb_req_damper(const uint8_t *bytes);
static const struct ffb_ops *ffb_ops;
static struct uart ffb_uart;
static bool ffb_started;
static HRESULT ffb_start_hr;
static uint8_t ffb_written[4];
static uint8_t ffb_readable[4];
/* Static variables to store maximum strength values */
static uint8_t max_constant_force = 0;
static uint8_t max_rumble = 0;
static uint8_t max_period = 0;
static uint8_t max_damper = 0;
HRESULT ffb_hook_init(
const struct ffb_config *cfg,
const struct ffb_ops *ops,
unsigned int port_no)
{
assert(cfg != NULL);
assert(ops != NULL);
if (!cfg->enable) {
return S_FALSE;
}
ffb_ops = ops;
uart_init(&ffb_uart, port_no);
ffb_uart.written.bytes = ffb_written;
ffb_uart.written.nbytes = sizeof(ffb_written);
ffb_uart.readable.bytes = ffb_readable;
ffb_uart.readable.nbytes = sizeof(ffb_readable);
dprintf("FFB: hook enabled.\n");
return iohook_push_handler(ffb_handle_irp);
}
static HRESULT ffb_handle_irp(struct irp *irp)
{
HRESULT hr;
assert(irp != NULL);
if (!uart_match_irp(&ffb_uart, irp)) {
return iohook_invoke_next(irp);
}
hr = uart_handle_irp(&ffb_uart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
assert(&ffb_uart.written != NULL);
assert(ffb_uart.written.bytes != NULL || ffb_uart.written.nbytes == 0);
assert(ffb_uart.written.pos <= ffb_uart.written.nbytes);
// dprintf("FFB TX:\n");
hr = ffb_req_dispatch((const union ffb_req_any *) ffb_uart.written.bytes);
if (FAILED(hr)) {
dprintf("FFB: Processing error: %x\n", (int)hr);
}
// dump_iobuf(&ffb_uart.written);
ffb_uart.written.pos = 0;
return hr;
}
static HRESULT ffb_req_dispatch(const union ffb_req_any *req)
{
switch (req->hdr.cmd) {
case FFB_CMD_TOGGLE:
return ffb_req_toggle(req->bytes);
case FFB_CMD_CONSTANT_FORCE:
return ffb_req_constant_force(req->bytes);
case FFB_CMD_RUMBLE:
return ffb_req_rumble(req->bytes);
case FFB_CMD_DAMPER:
return ffb_req_damper(req->bytes);
/* There are some test mode specfic commands which doesn't seem to be used in
game at all. The same is true for the initialization phase. */
default:
dprintf("FFB: Unhandled command %02x\n", req->hdr.cmd);
return S_OK;
}
}
static HRESULT ffb_req_toggle(const uint8_t *bytes)
{
uint8_t activate = bytes[2];
if (activate == 0x01) {
dprintf("FFB: Activated\n");
} else {
dprintf("FFB: Deactivated\n");
}
if (ffb_ops->toggle != NULL) {
ffb_ops->toggle(activate == 0x01);
}
return S_OK;
}
static HRESULT ffb_req_constant_force(const uint8_t *bytes)
{
// dprintf("FFB: Constant force\n");
uint8_t direction = bytes[1];
uint8_t force = bytes[2];
if (direction == 0x0) {
// Right
force = 128 - force;
}
// Update max strength if the current force is greater
if (force > max_constant_force) {
max_constant_force = force;
}
// dprintf("FFB: Constant Force Strength: %d (Max: %d)\n", force, max_constant_force);
if (ffb_ops->constant_force != NULL) {
ffb_ops->constant_force(direction, force);
}
return S_OK;
}
static HRESULT ffb_req_rumble(const uint8_t *bytes)
{
// dprintf("FFB: Rumble\n");
uint8_t force = bytes[1];
uint8_t period = bytes[2];
// Update max strength if the current force is greater
if (force > max_rumble) {
max_rumble = force;
}
if (period > max_period) {
max_period = period;
}
// dprintf("FFB: Rumble Period: %d (Max %d), Strength: %d (Max: %d)\n", period, max_period, force, max_rumble);
if (ffb_ops->rumble != NULL) {
ffb_ops->rumble(force, period);
}
return S_OK;
}
static HRESULT ffb_req_damper(const uint8_t *bytes)
{
// dprintf("FFB: Damper\n");
uint8_t force = bytes[2];
// Update max strength if the current force is greater
if (force > max_damper) {
max_damper = force;
}
// dprintf("FFB: Damper Strength: %d (Max: %d)\n", force, max_damper);
if (ffb_ops->damper != NULL) {
ffb_ops->damper(force);
}
return S_OK;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
struct ffb_config {
bool enable;
};
struct ffb_ops {
void (*toggle)(bool active);
void (*constant_force)(uint8_t direction, uint8_t force);
void (*rumble)(uint8_t force, uint8_t period);
void (*damper)(uint8_t force);
};
HRESULT ffb_hook_init(
const struct ffb_config *cfg,
const struct ffb_ops *ops,
unsigned int port_no);

View File

@ -79,11 +79,6 @@ static HRESULT io3_cmd_read_analogs(
struct const_iobuf *req_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(
struct io3 *io3,
struct const_iobuf *req_buf,
@ -121,13 +116,6 @@ static uint8_t io3_features[] = {
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
Param1 : 3 : Number of ports (8 bits per port)
Param2 : 0 : N/A
@ -231,9 +219,6 @@ static HRESULT io3_cmd(
case JVS_CMD_READ_ANALOGS:
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:
return io3_cmd_write_gpio(io3, req, resp);
@ -390,7 +375,7 @@ static HRESULT io3_cmd_read_switches(
return hr;
}
#if defined(LOG_IO3)
#if 0
dprintf("JVS I/O: Read switches, np=%i, bpp=%i\n",
req.num_players,
req.bytes_per_player);
@ -551,60 +536,6 @@ 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(
struct io3 *io3,
struct const_iobuf *req_buf,

View File

@ -18,7 +18,6 @@ struct io3_ops {
void (*write_gpio)(void *ctx, uint32_t state);
void (*read_switches)(void *ctx, struct io3_switch_state *out);
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);
};

View File

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

View File

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

View File

@ -1,81 +0,0 @@
#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;
};

View File

@ -1,194 +0,0 @@
#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;
}

View File

@ -1,26 +0,0 @@
#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);

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
#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

@ -199,7 +199,7 @@ struct led15093_resp_board_info {
char chip_num[5];
uint8_t endcode; // Always 0xFF
uint8_t fw_ver;
uint16_t rx_buf;
uint8_t rx_buf;
};
struct led15093_resp_protocol_ver {

View File

@ -1,6 +1,6 @@
/*
SEGA 837-15093-XX LED Controller Board emulator
Supported variants:
837-15093
@ -106,7 +106,7 @@ static uint8_t led15093_host_adr = 1;
static io_led_init_t led_init;
static io_led_set_leds_t set_leds;
HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init,
HRESULT led15093_hook_init(const struct led15093_config *cfg, io_led_init_t _led_init,
io_led_set_leds_t _set_leds, unsigned int first_port, unsigned int num_boards, uint8_t board_adr, uint8_t host_adr)
{
@ -236,12 +236,12 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
}
}
*/
if (irp->op == IRP_OP_OPEN) {
dprintf("LED 15093: Starting backend DLL\n");
// int res = led_init();
hr = led_init();
/*
if (res != 0) {
dprintf("LED 15093: Backend error, LED board disconnected: "
@ -267,7 +267,7 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
}
for (;;) {
#if defined(LOG_LED15093)
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&boarduart->written);
#endif
@ -294,7 +294,7 @@ static HRESULT led15093_handle_irp_locked(int board, struct irp *irp)
return hr;
}
#if defined(LOG_LED15093)
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif
@ -717,7 +717,7 @@ static HRESULT led15093_req_set_imm_led(int board, const struct led15093_req_set
resp.status = v->status_code;
if (req->cmd == LED_15093_CMD_SET_IMM_LED) {
resp.cmd = LED_15093_CMD_SET_IMM_LED;
}
}
// else {
// resp.cmd = LED_15093_CMD_SET_IMM_LED_LEGACY;
// }

View File

@ -25,11 +25,6 @@ board_lib = static_library(
'led15093-frame.h',
'led15093.c',
'led15093.h',
'led15070-cmd.h',
'led15070-frame.c',
'led15070-frame.h',
'led15070.c',
'led15070.h',
'sg-cmd.c',
'sg-cmd.h',
'sg-frame.c',
@ -47,10 +42,5 @@ board_lib = static_library(
'slider-frame.h',
'vfd.c',
'vfd.h',
'vfd-cmd.h',
'vfd-frame.c',
'vfd-frame.h',
'ffb.c',
'ffb.h'
],
)

View File

@ -5,21 +5,19 @@
#pragma pack(push, 1)
enum {
SG_NFC_CMD_GET_FW_VERSION = 0x30,
SG_NFC_CMD_GET_HW_VERSION = 0x32,
SG_NFC_CMD_RADIO_ON = 0x40,
SG_NFC_CMD_RADIO_OFF = 0x41,
SG_NFC_CMD_POLL = 0x42,
SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43,
SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x50,
SG_NFC_CMD_MIFARE_AUTHENTICATE_A = 0x51,
SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52,
SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x54,
SG_NFC_CMD_MIFARE_AUTHENTICATE_B = 0x55,
SG_NFC_CMD_TO_UPDATE_MODE = 0x60,
SG_NFC_CMD_SEND_HEX_DATA = 0x61,
SG_NFC_CMD_RESET = 0x62,
SG_NFC_CMD_FELICA_ENCAP = 0x71,
SG_NFC_CMD_GET_FW_VERSION = 0x30,
SG_NFC_CMD_GET_HW_VERSION = 0x32,
SG_NFC_CMD_RADIO_ON = 0x40,
SG_NFC_CMD_RADIO_OFF = 0x41,
SG_NFC_CMD_POLL = 0x42,
SG_NFC_CMD_MIFARE_SELECT_TAG = 0x43,
SG_NFC_CMD_MIFARE_SET_KEY_BANA = 0x50,
SG_NFC_CMD_MIFARE_READ_BLOCK = 0x52,
SG_NFC_CMD_MIFARE_SET_KEY_AIME = 0x54,
SG_NFC_CMD_MIFARE_AUTHENTICATE = 0x55, /* guess based on time sent */
SG_NFC_CMD_SEND_HEX_DATA = 0x61,
SG_NFC_CMD_RESET = 0x62,
SG_NFC_CMD_FELICA_ENCAP = 0x71,
};
struct sg_nfc_res_get_fw_version {
@ -34,7 +32,7 @@ struct sg_nfc_res_get_hw_version {
struct sg_nfc_req_mifare_set_key {
struct sg_req_header req;
uint8_t key[6];
uint8_t key_a[6];
};
struct sg_nfc_req_mifare_50 {

View File

@ -60,11 +60,6 @@ static HRESULT sg_nfc_cmd_felica_encap(
const struct sg_nfc_req_felica_encap *req,
struct sg_nfc_res_felica_encap *res);
static HRESULT sg_nfc_cmd_send_hex_data(
struct sg_nfc *nfc,
const struct sg_req_header *req,
struct sg_res_header *res);
static HRESULT sg_nfc_cmd_dummy(
struct sg_nfc *nfc,
const struct sg_req_header *req,
@ -189,17 +184,13 @@ static HRESULT sg_nfc_dispatch(
&req->felica_encap,
&res->felica_encap);
case SG_NFC_CMD_MIFARE_AUTHENTICATE_A:
case SG_NFC_CMD_MIFARE_AUTHENTICATE_B:
case SG_NFC_CMD_SEND_HEX_DATA:
return sg_nfc_cmd_send_hex_data(nfc, &req->simple, &res->simple);
case SG_NFC_CMD_MIFARE_AUTHENTICATE:
case SG_NFC_CMD_MIFARE_SELECT_TAG:
case SG_NFC_CMD_MIFARE_SET_KEY_AIME:
case SG_NFC_CMD_MIFARE_SET_KEY_BANA:
case SG_NFC_CMD_RADIO_ON:
case SG_NFC_CMD_RADIO_OFF:
case SG_NFC_CMD_TO_UPDATE_MODE:
case SG_NFC_CMD_SEND_HEX_DATA: // TODO: implement?
return sg_nfc_cmd_dummy(nfc, &req->simple, &res->simple);
default:
@ -429,7 +420,7 @@ static HRESULT sg_nfc_cmd_felica_encap(
f_res.nbytes = sizeof(res->payload);
f_res.pos = 1;
#if defined(LOG_NFC)
#if 0
dprintf("FELICA OUTBOUND:\n");
dump_const_iobuf(&f_req);
#endif
@ -443,7 +434,7 @@ static HRESULT sg_nfc_cmd_felica_encap(
sg_res_init(&res->res, &req->req, f_res.pos);
res->payload[0] = f_res.pos;
#if defined(LOG_NFC)
#if 0
dprintf("FELICA INBOUND:\n");
dump_iobuf(&f_res);
#endif
@ -451,22 +442,6 @@ static HRESULT sg_nfc_cmd_felica_encap(
return S_OK;
}
static HRESULT sg_nfc_cmd_send_hex_data(
struct sg_nfc *nfc,
const struct sg_req_header *req,
struct sg_res_header *res)
{
sg_res_init(res, req, 0);
/* Firmware checksum length? */
if (req->payload_len == 0x2b) {
/* The firmware is identical flag? */
res->status = 0x20;
}
return S_OK;
}
static HRESULT sg_nfc_cmd_dummy(
struct sg_nfc *nfc,
const struct sg_req_header *req,

View File

@ -115,14 +115,14 @@ static HRESULT sg_reader_handle_irp_locked(struct irp *irp)
{
HRESULT hr;
#if defined(LOG_NFC)
#if 0
if (irp->op == IRP_OP_WRITE) {
dprintf("WRITE:\n");
dump_const_iobuf(&irp->write);
}
#endif
#if defined(LOG_NFC)
#if 0
if (irp->op == IRP_OP_READ) {
dprintf("READ:\n");
dump_iobuf(&sg_reader_uart.readable);

View File

@ -1,123 +0,0 @@
#pragma once
#include "board/vfd-frame.h"
enum {
VFD_CMD_GET_VERSION = 0x5B,
VFD_CMD_RESET = 0x0B,
VFD_CMD_CLEAR_SCREEN = 0x0C,
VFD_CMD_SET_BRIGHTNESS = 0x20,
VFD_CMD_SET_SCREEN_ON = 0x21,
VFD_CMD_SET_H_SCROLL = 0x22,
VFD_CMD_DRAW_IMAGE = 0x2E,
VFD_CMD_SET_CURSOR = 0x30,
VFD_CMD_SET_ENCODING = 0x32,
VFD_CMD_SET_TEXT_WND = 0x40,
VFD_CMD_SET_TEXT_SPEED = 0x41,
VFD_CMD_WRITE_TEXT = 0x50,
VFD_CMD_ENABLE_SCROLL = 0x51,
VFD_CMD_DISABLE_SCROLL = 0x52,
VFD_CMD_ROTATE = 0x5D,
VFD_CMD_CREATE_CHAR = 0xA3,
VFD_CMD_CREATE_CHAR2 = 0xA4,
};
enum {
VFD_ENC_GB2312 = 0,
VFD_ENC_BIG5 = 1,
VFD_ENC_SHIFT_JIS = 2,
VFD_ENC_KSC5601 = 3,
VFD_ENC_MAX = 3,
};
struct vfd_req_hdr {
uint8_t sync;
uint8_t cmd;
};
struct vfd_req_any {
struct vfd_req_hdr hdr;
uint8_t payload[2054];
};
struct vfd_req_board_info {
struct vfd_req_hdr hdr;
uint8_t unk1;
};
struct vfd_resp_board_info { // \x0201.20\x03
uint8_t unk1;
char version[5];
uint8_t unk2;
};
struct vfd_req_reset {
struct vfd_req_hdr hdr;
};
struct vfd_req_cls {
struct vfd_req_hdr hdr;
};
struct vfd_req_brightness {
struct vfd_req_hdr hdr;
uint8_t brightness;
};
struct vfd_req_power {
struct vfd_req_hdr hdr;
uint8_t power_state;
};
struct vfd_req_hscroll {
struct vfd_req_hdr hdr;
uint8_t x_pos;
};
struct vfd_req_draw {
struct vfd_req_hdr hdr;
uint16_t x0;
uint8_t y0;
uint16_t x1;
uint8_t y1;
uint8_t image[2048];
};
struct vfd_req_cursor {
struct vfd_req_hdr hdr;
uint16_t x;
uint8_t y;
};
struct vfd_req_encoding {
struct vfd_req_hdr hdr;
uint8_t encoding;
};
struct vfd_req_wnd {
struct vfd_req_hdr hdr;
uint16_t x0;
uint8_t y0;
uint16_t x1;
uint8_t y1;
};
struct vfd_req_speed {
struct vfd_req_hdr hdr;
uint8_t encoding;
};
struct vfd_req_scroll {
struct vfd_req_hdr hdr;
};
struct vfd_req_rotate {
struct vfd_req_hdr hdr;
uint8_t unk1;
};
struct vfd_req_create_char {
struct vfd_req_hdr hdr;
uint8_t type;
uint8_t pixels[32];
};

View File

@ -1,88 +0,0 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#define SUPER_VERBOSE 1
#include "board/vfd-frame.h"
#include "hook/iobuf.h"
#include "util/dprintf.h"
static HRESULT vfd_frame_encode_byte(struct iobuf *dest, uint8_t byte);
/* Frame structure:
REQUEST:
[0] Sync byte (0x1A or 0x1B)
[1] Packet ID
[2...n-1] Data/payload
--- OR ---
if no sync byte is given, plain static text in the currently configured encoding is expected.
RESPONSE:
This thing never responds, unless it's VFD_CMD_GET_VERSION
*/
bool vfd_frame_sync(struct const_iobuf *src) {
return src->bytes[src->pos] == VFD_SYNC_BYTE || src->bytes[src->pos] == VFD_SYNC_BYTE2;
}
HRESULT vfd_frame_encode(
struct iobuf *dest,
const void *ptr,
size_t nbytes) {
const uint8_t *src;
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;
if (dest->pos >= dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
#if SUPER_VERBOSE
dprintf("VFD: RX Buffer:\n");
#endif
for (i = 1; i < nbytes; i++) {
byte = src[i];
#if SUPER_VERBOSE
dprintf("%02x ", byte);
#endif
hr = vfd_frame_encode_byte(dest, byte);
if (FAILED(hr)) {
return hr;
}
}
#if SUPER_VERBOSE
dprintf("\n");
#endif
return hr;
}
static HRESULT vfd_frame_encode_byte(struct iobuf *dest, uint8_t byte) {
if (dest->pos + 1 > dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
}
dest->bytes[dest->pos++] = byte;
return S_OK;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include <windows.h>
#include <stddef.h>
#include <stdint.h>
#include "hook/iobuf.h"
enum {
VFD_SYNC_BYTE = 0x1B,
VFD_SYNC_BYTE2 = 0x1A,
};
bool vfd_frame_sync(struct const_iobuf *src);
HRESULT vfd_frame_encode(
struct iobuf *dest,
const void *ptr,
size_t nbytes);

View File

@ -2,16 +2,17 @@
directly by amdaemon, and it has something to do with displaying the status
of electronic payments.
Part number in schematics is "VFD GP1232A02A FUTABA". */
Part number in schematics is "VFD GP1232A02A FUTABA".
Little else about this board is known. Black-holing the RS232 comms that it
receives seems to be sufficient for the time being. */
#include <windows.h>
#include <assert.h>
#include <stdint.h>
#include "board/config.h"
#include "board/vfd.h"
#include "board/vfd-cmd.h"
#include "hook/iohook.h"
@ -20,101 +21,33 @@
#include "util/dprintf.h"
#include "util/dump.h"
#define SUPER_VERBOSE 0
static HRESULT vfd_handle_irp(struct irp *irp);
static struct uart vfd_uart;
static uint8_t vfd_written[4096];
static uint8_t vfd_readable[4096];
static uint8_t vfd_written[512];
static uint8_t vfd_readable[512];
UINT codepage;
static int encoding = VFD_ENC_SHIFT_JIS;
HRESULT vfd_handle_get_version(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_reset(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_clear_screen(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_brightness(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_screen_on(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_h_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_draw_image(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_cursor(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_encoding(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_text_wnd(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_set_text_speed(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_write_text(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_enable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_disable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_rotate(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_create_char(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
HRESULT vfd_handle_create_char2(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart);
static bool utf_enabled;
HRESULT vfd_hook_init(struct vfd_config *cfg, int default_port)
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no)
{
if (!cfg->enable){
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
utf_enabled = cfg->utf_conversion;
int port = cfg->port;
if (port == 0){
port = default_port;
}
dprintf("VFD: enabling (port=%d)\n", port);
uart_init(&vfd_uart, port);
uart_init(&vfd_uart, port_no);
vfd_uart.written.bytes = vfd_written;
vfd_uart.written.nbytes = sizeof(vfd_written);
vfd_uart.readable.bytes = vfd_readable;
vfd_uart.readable.nbytes = sizeof(vfd_readable);
codepage = GetACP();
dprintf("VFD: hook enabled.\n");
return iohook_push_handler(vfd_handle_irp);
}
const char* get_encoding_name(int b){
switch (b){
case 0: return "gb2312";
case 1: return "big5";
case 2: return "shift-jis";
case 3: return "ks_c_5601-1987";
default: return "unknown";
}
}
void print_vfd_text(const char* str, int len){
if (utf_enabled){
wchar_t encoded[1024];
memset(encoded, 0, 1024 * sizeof(wchar_t));
int codepage = 0;
if (encoding == VFD_ENC_GB2312){
codepage = 936;
} else if (encoding == VFD_ENC_BIG5){
codepage = 950;
} else if (encoding == VFD_ENC_SHIFT_JIS){
codepage = 932;
} else if (encoding == VFD_ENC_KSC5601) {
codepage = 949;
}
if (!MultiByteToWideChar(codepage, MB_USEGLYPHCHARS, str, len, encoded, 1024)){
dprintf("VFD: Text conversion failed: %ld", GetLastError());
return;
}
dprintf("VFD: Text: %ls\n", encoded);
} else {
dprintf("VFD: Text: %s\n", str);
}
}
static HRESULT vfd_handle_irp(struct irp *irp)
{
HRESULT hr;
@ -125,274 +58,67 @@ static HRESULT vfd_handle_irp(struct irp *irp)
return iohook_invoke_next(irp);
}
if (irp->op == IRP_OP_OPEN){
dprintf("VFD: Open\n");
} else if (irp->op == IRP_OP_CLOSE){
dprintf("VFD: Close\n");
}
hr = uart_handle_irp(&vfd_uart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
#if SUPER_VERBOSE
dprintf("VFD TX:\n");
dump_iobuf(&vfd_uart.written);
#endif
struct const_iobuf reader;
iobuf_flip(&reader, &vfd_uart.written);
struct iobuf* writer = &vfd_uart.readable;
for (; reader.pos < reader.nbytes ; ){
if (vfd_frame_sync(&reader)) {
reader.pos++; // get the sync byte out of the way
uint8_t cmd;
iobuf_read_8(&reader, &cmd);
if (cmd == VFD_CMD_GET_VERSION) {
hr = vfd_handle_get_version(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_RESET) {
hr = vfd_handle_reset(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_CLEAR_SCREEN) {
hr = vfd_handle_clear_screen(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_BRIGHTNESS) {
hr = vfd_handle_set_brightness(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_SCREEN_ON) {
hr = vfd_handle_set_screen_on(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_H_SCROLL) {
hr = vfd_handle_set_h_scroll(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_DRAW_IMAGE) {
hr = vfd_handle_draw_image(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_CURSOR) {
hr = vfd_handle_set_cursor(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_ENCODING) {
hr = vfd_handle_set_encoding(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_TEXT_WND) {
hr = vfd_handle_set_text_wnd(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_SET_TEXT_SPEED) {
hr = vfd_handle_set_text_speed(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_WRITE_TEXT) {
hr = vfd_handle_write_text(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_ENABLE_SCROLL) {
hr = vfd_handle_enable_scroll(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_DISABLE_SCROLL) {
hr = vfd_handle_disable_scroll(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_ROTATE) {
hr = vfd_handle_rotate(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_CREATE_CHAR) {
hr = vfd_handle_create_char(&reader, writer, &vfd_uart);
} else if (cmd == VFD_CMD_CREATE_CHAR2) {
hr = vfd_handle_create_char2(&reader, writer, &vfd_uart);
} else {
dprintf("VFD: Unknown command 0x%x\n", cmd);
dump_const_iobuf(&reader);
hr = S_FALSE;
uint8_t cmd = 0;
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 no sync byte is sent, we are just getting plain text...
if (reader.pos < reader.nbytes){
int len = 0;
// read chars until we hit a new sync byte or the data ends
while (reader.pos + len + 1 < reader.nbytes && reader.bytes[reader.pos + len] != VFD_SYNC_BYTE && reader.bytes[reader.pos + len] != VFD_SYNC_BYTE2){
len++;
}
char* str = malloc(len);
memset(str, 0, len);
iobuf_read(&reader, str, len);
print_vfd_text(str, len);
free(str);
reader.pos += len;
else if (cmd == 0x50) {
i++;
}
continue;
}
if (!SUCCEEDED(hr)){
return hr;
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;
return hr;
}
HRESULT vfd_handle_get_version(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
dprintf("VFD: Get Version\n");
struct vfd_resp_board_info resp;
memset(&resp, 0, sizeof(resp));
resp.unk1 = 2;
strcpy(resp.version, "01.20");
resp.unk2 = 1;
return vfd_frame_encode(writer, &resp, sizeof(resp));
}
HRESULT vfd_handle_reset(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
dprintf("VFD: Reset\n");
encoding = VFD_ENC_SHIFT_JIS;
return S_FALSE;
}
HRESULT vfd_handle_clear_screen(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
dprintf("VFD: Clear Screen\n");
return S_FALSE;
}
HRESULT vfd_handle_set_brightness(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b;
iobuf_read_8(reader, &b);
if (b > 4){
dprintf("VFD: Brightness, invalid argument\n");
return E_FAIL;
}
dprintf("VFD: Brightness, %d\n", b);
return S_FALSE;
}
HRESULT vfd_handle_set_screen_on(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b;
iobuf_read_8(reader, &b);
if (b > 1){
dprintf("VFD: Screen Power, invalid argument\n");
return E_FAIL;
}
dprintf("VFD: Screen Power, %d\n", b);
return S_FALSE;
}
HRESULT vfd_handle_set_h_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t x;
iobuf_read_8(reader, &x);
dprintf("VFD: Horizontal Scroll, X=%d\n", x);
return S_FALSE;
}
HRESULT vfd_handle_draw_image(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
int w, h;
uint16_t x0, x1;
uint8_t y0, y1;
uint8_t image[2048];
iobuf_read_be16(reader, &x0);
iobuf_read_8(reader, &y0);
iobuf_read_be16(reader, &x1);
iobuf_read_8(reader, &y1);
w = x1 - x0;
h = y1 - y0;
iobuf_read(reader, image, w*h);
dprintf("VFD: Draw image, %dx%d\n", w, h);
return S_FALSE;
}
HRESULT vfd_handle_set_cursor(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint16_t x;
uint8_t y;
iobuf_read_be16(reader, &x);
iobuf_read_8(reader, &y);
dprintf("VFD: Set Cursor, x=%d,y=%d\n", x, y);
return S_FALSE;
}
HRESULT vfd_handle_set_encoding(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b;
iobuf_read_8(reader, &b);
dprintf("VFD: Set Encoding, %d (%s)\n", b, get_encoding_name(b));
if (b < 0 || b > VFD_ENC_MAX){
dprintf("Invalid encoding specified\n");
return E_FAIL;
}
encoding = b;
return S_FALSE;
}
HRESULT vfd_handle_set_text_wnd(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint16_t x0, x1;
uint8_t y0, y1;
iobuf_read_be16(reader, &x0);
iobuf_read_8(reader, &y0);
iobuf_read_be16(reader, &x1);
iobuf_read_8(reader, &y1);
dprintf("VFD: Set Text Window, p0:%d,%d, p1:%d,%d\n", x0, y0, x1, y1);
return S_FALSE;
}
HRESULT vfd_handle_set_text_speed(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b;
iobuf_read_8(reader, &b);
dprintf("VFD: Set Text Speed, %d\n", b);
return S_FALSE;
}
HRESULT vfd_handle_write_text(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t len;
iobuf_read_8(reader, &len);
char* str = malloc(len);
iobuf_read(reader, str, len);
print_vfd_text(str, len);
free(str);
return S_FALSE;
}
HRESULT vfd_handle_enable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
dprintf("VFD: Enable Scrolling\n");
return S_FALSE;
}
HRESULT vfd_handle_disable_scroll(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
dprintf("VFD: Disable Scrolling\n");
return S_FALSE;
}
HRESULT vfd_handle_rotate(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b;
iobuf_read_8(reader, &b);
dprintf("VFD: Rotate, %d\n", b);
return S_FALSE;
}
HRESULT vfd_handle_create_char(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b;
iobuf_read_8(reader, &b);
char buf[32];
iobuf_read(reader, buf, 32);
dprintf("VFD: Create character, %d\n", b);
return S_FALSE;
}
HRESULT vfd_handle_create_char2(struct const_iobuf* reader, struct iobuf* writer, struct uart* vfd_uart){
uint8_t b, b2;
iobuf_read_8(reader, &b);
iobuf_read_8(reader, &b2);
char buf[16];
iobuf_read(reader, buf, 16);
dprintf("VFD: Create character, %d, %d\n", b, b2);
return S_FALSE;
}

View File

@ -4,10 +4,7 @@
struct vfd_config {
bool enable;
int port;
bool utf_conversion;
};
HRESULT vfd_hook_init(struct vfd_config *cfg, int default_port);
HRESULT vfd_hook_init(const struct vfd_config *cfg, unsigned int port_no);

View File

@ -78,7 +78,7 @@ static HRESULT controlbd_frame_decode(struct controlbd_req_any *req, struct iobu
uint8_t checksum_pos = src->pos - 1;
uint8_t calculated_checksum = 0;
uint8_t checksum = 0;
if (src->pos < 6) {
dprintf("Control Board: Decode Error, request too short (pos is 0x%08X)\n", (int)src->pos);
return SEC_E_BUFFER_TOO_SMALL;
@ -137,7 +137,7 @@ static HRESULT controlbd_handle_irp_locked(struct irp *irp)
for (;;) {
if (controlbd_uart.written.bytes[0] == 0xE0) {
#if defined(LOG_CAROL_CONTROL_BD)
#if 0
dprintf("Control Board: TX Buffer:\n");
dump_iobuf(&controlbd_uart.written);
#endif
@ -147,12 +147,12 @@ static HRESULT controlbd_handle_irp_locked(struct irp *irp)
return hr;
}
hr = controlbd_req_dispatch(&req);
hr = controlbd_req_dispatch(&req);
if (FAILED(hr)) {
dprintf("Control Board: Dispatch Error: 0X%X\n", (int) hr);
return hr;
}
#if defined(LOG_CAROL_CONTROL_BD)
#if 0
dprintf("Control Board: RX Buffer:\n");
dump_iobuf(&controlbd_uart.readable);
#endif
@ -206,7 +206,7 @@ static HRESULT controlbd_req_dispatch(const struct controlbd_req_any *req)
case CONTROLBD_CMD_FIRM_SUM:
return controlbd_req_firmware_checksum();
case CONTROLBD_CMD_TIMEOUT:
case CONTROLBD_CMD_TIMEOUT:
dprintf("Control Board: Acknowledge Timeout\n");
return controlbd_req_ack_any(req->hdr.cmd);
@ -278,7 +278,7 @@ static HRESULT controlbd_req_get_board_info(void)
resp.rev = 0x90;
resp.bfr_size = 0x0001;
resp.ack = 1;
strcpy_s(resp.bd_no, sizeof(resp.bd_no), "15312 ");
strcpy_s(resp.chip_no, sizeof(resp.chip_no), "6699 ");
resp.chip_no[5] = 0xFF;
@ -317,7 +317,7 @@ static HRESULT controlbd_req_polling(const struct controlbd_req_any *req)
resp.unk7 = 3;
resp.unk8 = 1;
resp.unk9 = 1;
resp.btns_pressed = 0; // bit 1 is pen button, bit 2 is dodge
resp.coord_x = 0x0;
resp.coord_y = 0x0;

View File

@ -1,31 +1,3 @@
/*
"Wonderland Wars" (carol*) hook
Devices:
JVS: 837-14572 "Type 3" I/O Board
[Satellite]
USB: "WinTouch" Controller Board
^ (DIPSW2 ON, Version 5.xx.xx or above)
COM1: 3M Touch Systems 78-0011-2353-4 Touch Controller Board
^ (DIPSW2 OFF)
COM10: TN32MSEC003S "Gen 1" Aime Reader
OR
837-15286 "Gen 2" Aime Reader
^ (Version 1.6x.xx or above)
COM11: 837-15070-02 LED Controller Board
COM12: 837-15312 Pen Controller I/O Board
[Terminal]
COM10: 837-15286 "Gen 2" Aime Reader
*: SEGA's abbreviation for Lewis Carroll, author of Alice's Adventures in
Wonderland.
*/
#include <windows.h>
#include <stdlib.h>

View File

@ -94,7 +94,7 @@ static HRESULT ledbd_handle_irp_locked(struct irp *irp)
}
for (;;) {
#if defined(LOG_CAROL_LED_BD)
#if 0
dprintf("LED Board: TX Buffer:\n");
dump_iobuf(&ledbd_uart.written);
#endif
@ -165,4 +165,4 @@ static HRESULT ledbd_req_unkF0(uint8_t cmd)
iobuf_write(&ledbd_uart.readable, resp, 16);
return S_OK;
}
}

View File

@ -54,7 +54,7 @@ HRESULT touch_hook_init(const struct touch_config *cfg)
if (!cfg->enable) {
return S_OK;
}
InitializeCriticalSection(&touch_lock);
uart_init(&touch_uart, 1);
@ -112,7 +112,7 @@ static HRESULT touch_handle_irp_locked(struct irp *irp)
}
for (;;) {
#if defined(LOG_CAROL_TOUCH)
#if 0
dprintf("Touchscreen: TX Buffer:\n");
dump_iobuf(&touch_uart.written);
#endif
@ -188,7 +188,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
resp.touches[0].touch_id = 1;
tmp_x = mouse_x & 0x7FFF;
tmp_y = mouse_y & 0x7FFF;
resp.touches[0].x1 = tmp_x & 0x7F;
resp.touches[0].x2 = (tmp_x >> 7) & 0x7F;
resp.touches[0].y1 = tmp_y & 0x7F;
@ -201,7 +201,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
dprintf("Touch: Mouse down! x %02X %02X y: %02X %02X\n", resp.touches[0].x1, resp.touches[0].x2, resp.touches[0].y1, resp.touches[0].y2);
#endif
last_x1 = resp.touches[0].x1;
last_x2 = resp.touches[0].x2;
last_y1 = resp.touches[0].y1;
@ -220,7 +220,7 @@ static void touch_scan_auto(const bool is_pressed, const uint16_t mouse_x, const
iobuf_write(&touch_uart.readable, &resp, sizeof(resp));
LeaveCriticalSection(&touch_lock);
#if defined(LOG_CAROL_TOUCH)
#if 0
dprintf("Touch: RX Buffer: (pos %08x)\n", (uint32_t)touch_uart.readable.pos);
dump_iobuf(&touch_uart.readable);
#endif

View File

@ -1,15 +1,3 @@
/*
"CHUNITHM" (chuni) hook
Devices
JVS: 837-14572 "Type 3" I/O Board
COM1: 837-15330 Ground Slider
COM10: 837-15093-06 LED Controller Board
COM11: 837-15093-06 LED Controller Board
COM12: TN32MSEC003S "Gen 1" Aime Reader
*/
#include <windows.h>
#include <stdlib.h>

View File

@ -98,7 +98,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
}
for (;;) {
#if defined(LOG_CHUNI_SLIDER)
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&slider_uart.written);
#endif
@ -117,7 +117,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
return hr;
}
#if defined(LOG_CHUNI_SLIDER)
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif

View File

@ -139,10 +139,9 @@ void chuni_io_slider_start(chuni_io_slider_callback_t callback);
void chuni_io_slider_stop(void);
/* Update the RGB lighting on the slider. A pointer to an array of 32 * 3 = 96
bytes is supplied, organized in BRG format.
The first set of bytes is the right-most slider key, and from there the bytes
alternate between the dividers and the keys until the left-most key.
There are 31 illuminated sections in total.
bytes is supplied. The illuminated areas on the touch slider are some
combination of rectangular regions and dividing lines between these regions
but the exact mapping of this lighting control buffer is still TBD.
Minimum API version: 0x0100 */
@ -164,17 +163,9 @@ HRESULT chuni_io_led_init(void);
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 has 53 LEDs:
[0]-[49]: snakes through left half of billboard (first column starts at top)
[50]-[52]: left side partition LEDs
left side has 5*10 rgb values for the billboard, followed by 3 rgb values for the air tower
right side has 6*10 rgb values for the billboard, followed by 3 rgb values for the air tower
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
NOTE: billboard strips have alternating direction (bottom to top, top to bottom, ...)

View File

@ -57,13 +57,11 @@ void chuni_io_config_load(
filename);
}
cfg->cab_led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
cfg->cab_led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
cfg->led_output_pipe = GetPrivateProfileIntW(L"led", L"cabLedOutputPipe", 1, filename);
cfg->led_output_serial = GetPrivateProfileIntW(L"led", L"cabLedOutputSerial", 0, filename);
cfg->controller_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
cfg->controller_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
cfg->controller_led_output_openithm = GetPrivateProfileIntW(L"led", L"controllerLedOutputOpeNITHM", 0, filename);
cfg->slider_led_output_pipe = GetPrivateProfileIntW(L"led", L"controllerLedOutputPipe", 1, filename);
cfg->slider_led_output_serial = GetPrivateProfileIntW(L"led", L"controllerLedOutputSerial", 0, filename);
cfg->led_serial_baud = GetPrivateProfileIntW(L"led", L"serialBaud", 921600, filename);
@ -72,7 +70,7 @@ void chuni_io_config_load(
L"serialPort",
L"COM5",
port_input,
_countof(port_input),
6,
filename);
// Sanitize the output path. If it's a serial COM port, it needs to be prefixed

View File

@ -12,17 +12,16 @@ struct chuni_io_config {
uint8_t vk_cell[32];
// Which ways to output LED information are enabled
bool cab_led_output_pipe;
bool cab_led_output_serial;
bool led_output_pipe;
bool led_output_serial;
bool controller_led_output_pipe;
bool controller_led_output_serial;
bool controller_led_output_openithm;
bool slider_led_output_pipe;
bool slider_led_output_serial;
// The name of a COM port to output LED data on, in serial mode
wchar_t led_serial_port[12];
int32_t led_serial_baud;
};
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];
}
any_outputs_enabled = config->cab_led_output_pipe || config->controller_led_output_pipe
|| config->cab_led_output_serial || config->controller_led_output_serial;
any_outputs_enabled = config->led_output_pipe || config->slider_led_output_pipe
|| config->led_output_serial || config->slider_led_output_serial;
if (config->cab_led_output_pipe || config->controller_led_output_pipe)
if (config->led_output_pipe || config->slider_led_output_pipe)
{
led_pipe_init(); // don't really care about errors here tbh
}
if (config->cab_led_output_serial || config->controller_led_output_serial)
if (config->led_output_serial || config->slider_led_output_serial)
{
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)
{
// billboard (cab)
if (config->cab_led_output_pipe)
// billboard
if (config->led_output_pipe)
{
led_pipe_update(escaped_data);
}
if (config->cab_led_output_serial)
if (config->led_output_serial)
{
led_serial_update(escaped_data);
}
@ -120,18 +120,14 @@ void led_output_update(uint8_t board, const byte* rgb)
else
{
// slider
if (config->controller_led_output_pipe)
if (config->slider_led_output_pipe)
{
led_pipe_update(escaped_data);
}
if (config->controller_led_output_serial)
if (config->slider_led_output_serial)
{
if (config->controller_led_output_openithm){
led_serial_update_openithm(rgb);
} else {
led_serial_update(escaped_data);
}
led_serial_update(escaped_data);
}
}
}

View File

@ -4,7 +4,6 @@ chuniio_lib = static_library(
include_directories : inc,
implicit_include_directories : false,
c_pch : '../precompiled.h',
sources : [
'chu2to3.c',
'chu2to3.h',

View File

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

View File

@ -97,27 +97,3 @@ void led_serial_update(struct _chuni_led_data_buf_t* data)
ReleaseMutex(serial_write_mutex);
}
void led_serial_update_openithm(const byte* rgb)
{
if (serial_port != INVALID_HANDLE_VALUE)
{
char led_buffer[100];
DWORD bytes_to_write; // No of bytes to write into the port
DWORD bytes_written = 0; // No of bytes written to the port
bytes_to_write = sizeof(led_buffer);
BOOL status;
led_buffer[0] = 0xAA;
led_buffer[1] = 0xAA;
memcpy(led_buffer+2, rgb, sizeof(uint8_t) * 96);
led_buffer[98] = 0xDD;
led_buffer[99] = 0xDD;
status = WriteFile(serial_port, // Handle to the Serial port
led_buffer, // Data to be written to the port
bytes_to_write, // No of bytes to write
&bytes_written, // Bytes written
NULL);
}
}

View File

@ -13,4 +13,3 @@
HRESULT led_serial_init(wchar_t led_com[12], DWORD baud);
void led_serial_update(struct _chuni_led_data_buf_t* data);
void led_serial_update_openithm(const byte* rgb);

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 "
"further assistance.\n",
sym->sym);
dprintf("imported %d symbols\n", bind_count);
dprintf("imported %d symbols\n",bind_count);
goto end;
}
} else {

View File

@ -1,27 +1,3 @@
/*
"CHUNITHM NEW" (chusan) hook
Devices
USB: 837-15257-02 "Type 4" I/O Board
COM1: 837-15330 Ground Slider
[CVT mode (DIPSW2 ON)]
COM2: 837-15093-06 LED Controller Board
COM3: 837-15093-06 LED Controller Board
COM4: 837-15286 "Gen 2" Aime Reader
[SP mode (DIPSW2 OFF)]
USB: 837-15067-02 USB Serial I/F Board
connected to
837-15093-06 LED Controller Board (COM20)
837-15093-06 LED Controller Board (COM21)
COM2: 200-6275 VFD GP1232A02A FUTABA Board
COM4: 837-15396 "Gen 3" Aime Reader
*/
#include <windows.h>
#include <stddef.h>
@ -123,7 +99,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
goto fail;
}
bool *dipsw = &chusan_hook_cfg.platform.system.dipsw[0];
bool *dipsw = &chusan_hook_cfg.platform.dipsw.dipsw[0];
bool is_cvt = dipsw[2];
for (int i = 0; i < 3; i++) {

View File

@ -98,7 +98,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
}
for (;;) {
#if defined(LOG_CHUSAN_SLIDER)
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&slider_uart.written);
#endif
@ -117,7 +117,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
return hr;
}
#if defined(LOG_CHUSAN_SLIDER)
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif

View File

@ -15,59 +15,3 @@ EXPORTS
cm_io_get_opbtns
cm_io_init
cm_io_poll
CFW_init
CFW_term
CFW_open
CFW_close
CFW_listupPrinter
CFW_listupPrinterSN
CFW_selectPrinter
CFW_selectPrinterSN
CFW_getPrinterInfo
CFW_status
CFW_statusAll
CFW_resetPrinter
CFW_updateFirmware
CFW_getFirmwareInfo
CHCUSB_init
CHCUSB_term
CHCUSB_MakeThread
CHCUSB_open
CHCUSB_close
CHCUSB_ReleaseThread
CHCUSB_listupPrinter
CHCUSB_listupPrinterSN
CHCUSB_selectPrinter
CHCUSB_selectPrinterSN
CHCUSB_getPrinterInfo
CHCUSB_imageformat
CHCUSB_setmtf
CHCUSB_makeGamma
CHCUSB_setIcctableProfile
CHCUSB_setIcctable
CHCUSB_copies
CHCUSB_status
CHCUSB_statusAll
CHCUSB_startpage
CHCUSB_endpage
CHCUSB_write
CHCUSB_writeLaminate
CHCUSB_writeHolo
CHCUSB_setPrinterInfo
CHCUSB_setPrinterToneCurve
CHCUSB_getGamma
CHCUSB_getMtf
CHCUSB_cancelCopies
CHCUSB_getPrinterToneCurve
CHCUSB_blinkLED
CHCUSB_resetPrinter
CHCUSB_AttachThreadCount
CHCUSB_getPrintIDStatus
CHCUSB_setPrintStandby
CHCUSB_testCardFeed
CHCUSB_exitCard
CHCUSB_getCardRfidTID
CHCUSB_commCardRfidReader
CHCUSB_updateCardRfidReader
CHCUSB_getErrorLog
CHCUSB_getErrorStatus

View File

@ -39,7 +39,6 @@ void cm_hook_config_load(
io4_config_load(&cfg->io4, filename);
vfd_config_load(&cfg->vfd, filename);
touch_screen_config_load(&cfg->touch, filename);
printer_config_load(&cfg->printer, filename);
cm_dll_config_load(&cfg->dll, filename);
unity_config_load(&cfg->unity, filename);
}

View File

@ -6,7 +6,6 @@
#include "hooklib/dvd.h"
#include "hooklib/touch.h"
#include "hooklib/printer.h"
#include "cmhook/cm-dll.h"
@ -22,7 +21,6 @@ struct cm_hook_config {
struct vfd_config vfd;
struct cm_dll_config dll;
struct touch_screen_config touch;
struct printer_config printer;
struct unity_config unity;
};

View File

@ -1,16 +1,3 @@
/*
"Card Maker" (cm) hook
Devices
USB: 837-15257-01 "Type 4" I/O Board
USB: 838-20006 "WinTouch" Controller Board
USB: 630-00009 Sinfonia CHC-C310 Printer
COM1: 837-15396 "Gen 3" Aime Reader
COM2: 200-6275 VFD GP1232A02A FUTABA Board
COM3: 220-5872 AS-6DB Coin Selector
*/
#include <windows.h>
#include <stdlib.h>
@ -56,10 +43,6 @@ static DWORD CALLBACK cm_pre_startup(void)
touch_screen_hook_init(&cm_hook_cfg.touch, cm_hook_mod);
serial_hook_init();
/* Hook external DLL APIs */
printer_hook_init(&cm_hook_cfg.printer, 0, cm_hook_mod);
/* Initialize emulation hooks */
hr = platform_hook_init(
@ -72,12 +55,6 @@ static DWORD CALLBACK cm_pre_startup(void)
goto fail;
}
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = sg_reader_hook_init(&cm_hook_cfg.aime, 1, 1, cm_hook_mod);
if (FAILED(hr)) {
@ -90,6 +67,12 @@ static DWORD CALLBACK cm_pre_startup(void)
goto fail;
}
hr = cm_dll_init(&cm_hook_cfg.dll, cm_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = cm_io4_hook_init(&cm_hook_cfg.io4);
if (FAILED(hr)) {
@ -101,7 +84,7 @@ static DWORD CALLBACK cm_pre_startup(void)
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
hooked earlier in the `cmhook` initialization. */
unity_hook_init(&cm_hook_cfg.unity, cm_hook_mod, NULL);
unity_hook_init(&cm_hook_cfg.unity, cm_hook_mod);
/* Initialize debug helpers */

View File

@ -36,9 +36,9 @@ HRESULT cm_io_init(void);
HRESULT cm_io_poll(void);
/* Get the state of the cabinet's operator buttons as of the last poll. See
CM_IO_OPBTN enum above: this contains bit mask definitions for button
cm_IO_OPBTN enum above: this contains bit mask definitions for button
states returned in *opbtn. All buttons are active-high.
Minimum API version: 0x0100 */
void cm_io_get_opbtns(uint8_t *opbtn);
void cm_io_get_opbtns(uint8_t *opbtn);

View File

@ -5,7 +5,7 @@
#include "cxbhook/led.h"
#include "cxbhook/cxb-dll.h"
#include "hook/procaddr.h"
#include "hooklib/procaddr.h"
#include "hook/table.h"
@ -56,7 +56,7 @@ HRESULT led_hook_init(struct led_config *cfg)
}
dprintf("LED: Hook enabled.\n");
return proc_addr_table_push(NULL, "CommLamp.dll", lamp_syms, _countof(lamp_syms));
return proc_addr_table_push("CommLamp.dll", lamp_syms, _countof(lamp_syms));
}
static int my_cCommLamp_Open(char *port)

View File

@ -6,7 +6,7 @@
#include "cxbhook/revio.h"
#include "cxbhook/cxb-dll.h"
#include "hook/procaddr.h"
#include "hooklib/procaddr.h"
#include "hook/table.h"
@ -89,7 +89,7 @@ HRESULT revio_hook_init(struct revio_config *cfg)
}
dprintf("Revio: Hook enabled.\n");
return proc_addr_table_push(NULL, "CommIo.dll", revio_syms, _countof(revio_syms));
return proc_addr_table_push("CommIo.dll", revio_syms, _countof(revio_syms));
}
static int my_cCommIo_Open(char *port)

View File

@ -64,8 +64,6 @@ subnet=192.168.126.0
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.

View File

@ -56,8 +56,6 @@ subnet=192.168.139.0
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.
@ -65,6 +63,20 @@ 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=
[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=
; -----------------------------------------------------------------------------
; LED settings
; -----------------------------------------------------------------------------
@ -84,12 +96,10 @@ cabLedOutputSerial=0
controllerLedOutputPipe=1
; Output slider LED data to the serial port
controllerLedOutputSerial=0
; Use the OpeNITHM protocol for serial LED output
controllerLedOutputOpeNITHM=0
; Serial port to send data to if using serial output. Default is COM5.
;serialPort=COM5
; Baud rate for serial data (set to 115200 if using OpeNITHM)
; Baud rate for serial data
;serialBaud=921600
; Data output a sequence of bytes, with JVS-like framing.
@ -112,20 +122,6 @@ controllerLedOutputOpeNITHM=0
; [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
; -----------------------------------------------------------------------------

View File

@ -25,7 +25,7 @@ aimePath=DEVICE\aime.txt
;highBaud=1
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -43,7 +43,6 @@ default=127.0.0.1
; Chunithm is extremely picky about its LAN environment, so leaving this
; setting enabled is strongly recommended.
enable=1
; The final octet of the local host's IP address on the virtualized subnet (so,
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
; local host's virtualized LAN IP is `192.168.32.11`).
@ -59,8 +58,8 @@ addrSuffix=11
; that subnet must start with 192.168.
subnet=192.168.139.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -82,8 +81,6 @@ dipsw3=1
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.
@ -91,6 +88,25 @@ framed=0
; 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 (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=
; -----------------------------------------------------------------------------
; LED settings
; -----------------------------------------------------------------------------
@ -110,12 +126,10 @@ cabLedOutputSerial=0
controllerLedOutputPipe=1
; Output slider LED data to the serial port
controllerLedOutputSerial=0
; Use the OpeNITHM protocol for serial LED output
controllerLedOutputOpeNITHM=0
; Serial port to send data to if using serial output. Default is COM5.
;serialPort=COM5
; Baud rate for serial data (set to 115200 if using OpeNITHM)
; Baud rate for serial data
;serialBaud=921600
; Data output a sequence of bytes, with JVS-like framing.
@ -138,25 +152,6 @@ controllerLedOutputOpeNITHM=0
; [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
; -----------------------------------------------------------------------------
@ -206,3 +201,7 @@ ir=0x20
; ... etc ...
;cell31=0x53
;cell32=0x53
; Enable slider LED serial output. This follows OpeNITHM Serial LED Protocol.
; eg. COM5
;ledport=

16
dist/cm/segatools.ini vendored
View File

@ -23,7 +23,7 @@ enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -50,10 +50,10 @@ enable=1
; 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.165.0
subnet=192.168.100.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; LAN Install: If multiple machines are present on the same LAN then set
@ -73,14 +73,6 @@ enable=0
; modding frameworks such as BepInEx.
targetAssembly=
[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"
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------

View File

@ -75,8 +75,6 @@ path=../DEVICE/sram.bin
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.

View File

@ -5,7 +5,7 @@
[vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs=
; Insert the path to the game Option (mdata) directory here (contains Mxxx directories)
; Insert the path to the game Option directory here (contains Axxx directories)
option=
; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games.
@ -36,10 +36,6 @@ default=127.0.0.1
; Chunithm is extremely picky about its LAN environment, so leaving this
; setting enabled is strongly recommended.
enable=1
; The final octet of the local host's IP address on the virtualized subnet (so,
; if the keychip subnet is `192.168.32.0` and this value is set to `11`, then the
; local host's virtualized LAN IP is `192.168.32.11`).
addrSuffix=11
; -----------------------------------------------------------------------------
; Board settings
@ -58,18 +54,6 @@ dipsw1=1
; that subnet must start with 192.168.
subnet=192.168.78.0
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Force the game to run windowed.
windowed=1
; Add a frame to the game window if running windowed.
framed=0
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------

View File

@ -23,7 +23,7 @@ enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -72,8 +72,8 @@ addrSuffix=11
; that subnet must start with 192.168.
subnet=192.168.167.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -85,14 +85,6 @@ freeplay=0
; Misc. hook settings
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Force the game to run windowed.
windowed=0
; Add a frame to the game window if running windowed.
framed=0
[touch]
; WinTouch emulation setting.
enable=1
@ -136,6 +128,7 @@ path=
; world. An improved solution will be provided later.
[io4]
; Input API selection for JVS input emulator.
; Test button virtual-key code. Default is the F1 key.
test=0x70
; Service button virtual-key code. Default is the F2 key.

View File

@ -54,8 +54,8 @@ subnet=192.168.158.0
; 1: JPN: Japan, 4: EXP: Export (for Asian markets)
region=4
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -75,30 +75,6 @@ dipsw3=0
dipsw4=0
dipsw5=0
[ffb]
; Enable force feedback (838-15069) board emulation. This is required for
; both DirectInput and XInput steering wheel effects.
enable=1
; -----------------------------------------------------------------------------
; 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
; -----------------------------------------------------------------------------
@ -236,20 +212,6 @@ reverseAccelAxis=0
reverseBrakeAxis=0
; Force feedback settings.
; Only works when FFB board emulation is enabled!
;
; It is recommended to change the strength inside the Game Test Mode!
;
; These settings are only used when using DirectInput for the wheel.
; The values are in the range 0%-100%, where 0 disables the effect and
; 100 is the maximum.
; Constant force strength, used for centering spring effect.
constantForceStrength=100
; Damper strength, used for steering wheel damper effect.
damperStrength=100
; Rumble strength, used for road surface effects.
rumbleStrength=100
; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect.
rumbleDuration=1000
; Strength of the force feedback spring effect in percent. Possible values
; are 0-100.
centerSpringStrength=30

View File

@ -69,20 +69,6 @@ region=4
; exactly one machine and set this to 0 on all others.
dipsw1=1
[ffb]
; Enable force feedback (838-15069) board emulation. This is required for
; both DirectInput and XInput steering wheel effects.
enable=1
; -----------------------------------------------------------------------------
; LED settings
; -----------------------------------------------------------------------------
[led15070]
; Enable emulation of the 837-15070-02 controlled lights, which handle the
; cabinet and seat LEDs.
enable=1
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
@ -226,20 +212,6 @@ reverseAccelAxis=0
reverseBrakeAxis=0
; Force feedback settings.
; Only works when FFB board emulation is enabled!
;
; It is recommended to change the strength inside the Game Test Mode!
;
; These settings are only used when using DirectInput for the wheel.
; The values are in the range 0%-100%, where 0 disables the effect and
; 100 is the maximum.
; Constant force strength, used for centering spring effect.
constantForceStrength=100
; Damper strength, used for steering wheel damper effect.
damperStrength=100
; Rumble strength, used for road surface effects.
rumbleStrength=100
; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect.
rumbleDuration=1000
; Strength of the force feedback spring effect in percent. Possible values
; are 0-100.
centerSpringStrength=30

5
dist/idz/start.bat vendored
View File

@ -2,11 +2,10 @@
pushd %~dp0
start /min "AM Daemon" inject -d -k idzhook.dll amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json
inject -k idzhook.dll InitialD0_DX11_Nu.exe
rem Set dipsw1=0 and uncomment the ServerBox for in store battle?
rem inject -k idzhook.dll ServerBoxD8_Nu_x64.exe
inject -d -k idzhook.dll InitialD0_DX11_Nu.exe
inject -d -k idzhook.dll amdaemon.exe -c configDHCP_Final_Common.json configDHCP_Final_JP.json configDHCP_Final_JP_ST1.json configDHCP_Final_JP_ST2.json configDHCP_Final_EX.json configDHCP_Final_EX_ST1.json configDHCP_Final_EX_ST2.json
taskkill /im ServerBoxD8_Nu_x64.exe > nul 2>&1

View File

@ -1,150 +0,0 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs=
; Insert the path to the game Option directory here (contains Axxx directories)
option=
; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %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
[vfd]
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
; -----------------------------------------------------------------------------
; 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 its 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.179.0
[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
; Chassis Test button virtual-key code. Default is the 4 key.
test=0x34
; Chassis Service button virtual-key code. Default is the 5 key.
service=0x35
; -----------------------------------------------------------------------------
; 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.
;
; NOTE: For Kemono Friends, BepInEx (or similar) should be installed to the main folder, not the "UnityApp" folder.
targetAssembly=
[printer]
; Sinfonia CHC-C300 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"
; The length in milliseconds the printer should be busy printing.
; Set to 0 to instantly finish printing.
waitTime=20000
; -----------------------------------------------------------------------------
; LED settings
; -----------------------------------------------------------------------------
[led15093]
; 837-15093-06 LED board emulation setting.
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=
[kemonoio]
; To use a custom Kemono IO 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.
[io3]
; Test button virtual-key code. Default is the 1 key.
test=0x31
; Service button virtual-key code. Default is the 2 key.
service=0x32
; Keyboard button to increment coin counter. Default is the 3 key.
coin=0x33
; Analog lever (which is actually just four buttons, and not real analog input, default: Arrow keys)
left=0x25
right=0x27
up=0x26
down=0x28
; Controller face buttons (default A, S, D)
red=0x41
green=0x53
blue=0x44
; Menu confirmation key (default RETURN)
start=0x0D

12
dist/kemono/start.bat vendored
View File

@ -1,12 +0,0 @@
@echo off
pushd %~dp0
start "AM Daemon" /min inject_x64 -d -k kemonohook_x64.dll amdaemon.exe -c config.json
inject_x86 -d -k kemonohook_x86.dll UnityApp\Parade -screen-fullscreen 0 -popupwindow -screen-width 720 -screen-height 1280 -silent-crashes
taskkill /f /im amdaemon.exe > nul 2>&1
echo.
echo Game processes have terminated
pause

View File

@ -23,7 +23,7 @@ enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -56,8 +56,8 @@ addrSuffix=11
; that subnet must start with 192.168.
subnet=192.168.172.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -69,18 +69,6 @@ freeplay=0
; this to 1 on exactly one machine and set this to 0 on all others.
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
; -----------------------------------------------------------------------------
@ -95,6 +83,15 @@ path=
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; -----------------------------------------------------------------------------
; Misc. hook settings
; -----------------------------------------------------------------------------
[unity]
; Path to a .NET DLL that should run before the game. Useful for loading
; modding frameworks such as BepInEx.
targetAssembly=
; -----------------------------------------------------------------------------
; Input settings
; -----------------------------------------------------------------------------

View File

@ -23,7 +23,7 @@ enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -56,8 +56,8 @@ addrSuffix=11
; that subnet must start with 192.168.
subnet=192.168.174.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -74,7 +74,6 @@ dipsw1=1
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
; Hooks related to the touch boards

View File

@ -23,7 +23,7 @@ enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -52,8 +52,8 @@ enable=1
; that subnet must start with 192.168.
subnet=192.168.162.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -70,65 +70,13 @@ dipsw1=1
; -----------------------------------------------------------------------------
[gfx]
; Enables the graphics hook.
enable=1
[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=
; -----------------------------------------------------------------------------
; 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
; -----------------------------------------------------------------------------
@ -191,7 +139,7 @@ leftSide=0x01 ; Mouse Left
rightSide=0x02 ; Mouse Right
right1=0x4A ; J
right2=0x4B ; K
right1=0x4B ; K
right3=0x4C ; L
leftMenu=0x55 ; U

View File

@ -23,7 +23,7 @@ enable=1
aimePath=DEVICE\aime.txt
[vfd]
; Enable VFD emulation. Disable to use a real VFD
; Enable VFD emulation (currently just stubbed). Disable to use a real VFD
; GP1232A02A FUTABA assembly.
enable=1
@ -56,8 +56,8 @@ addrSuffix=11
; in order to find the MAIN cabinet.
subnet=192.168.160.0
[system]
; Enable ALLS system settings.
[gpio]
; ALLS DIP switches.
enable=1
; Enable freeplay mode. This will disable the coin slot and set the game to
@ -65,11 +65,6 @@ enable=1
; allow you to start a game in freeplay mode.
freeplay=0
[ffb]
; Enable force feedback (838-15069) board emulation. This is required for
; both DirectInput and XInput steering wheel effects.
enable=1
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
@ -186,20 +181,6 @@ reverseAccelAxis=0
reverseBrakeAxis=0
; Force feedback settings.
; Only works when FFB board emulation is enabled!
;
; It is recommended to change the strength inside the Game Test Mode!
;
; These settings are only used when using DirectInput for the wheel.
; The values are in the range 0%-100%, where 0 disables the effect and
; 100 is the maximum.
; Constant force strength, used for centering spring effect.
constantForceStrength=100
; Damper strength, used for steering wheel damper effect.
damperStrength=100
; Rumble strength, used for road surface effects.
rumbleStrength=100
; Rumble duration factor from ms to µs, used to scale the duration of the rumble effect.
rumbleDuration=1000
; Strength of the force feedback spring effect in percent. Possible values
; are 0-100.
centerSpringStrength=30

View File

@ -1,9 +0,0 @@
{
"network" :
{
"property" :
{
"dhcp" : true
}
}
}

View File

@ -1,199 +0,0 @@
; -----------------------------------------------------------------------------
; Path settings
; -----------------------------------------------------------------------------
[vfs]
; Insert the path to the game AMFS directory here (contains ICF1 and ICF2)
amfs=
; Insert the path to the game Option directory here (contains OPxx directories)
option=
; Create an empty directory somewhere and insert the path here.
; This directory may be shared between multiple SEGA games.
; NOTE: This has nothing to do with Windows %APPDATA%.
appdata=
; -----------------------------------------------------------------------------
; 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.149.0` and this value is set to `205`, then the
; local host's virtualized LAN IP is `192.168.149.205`).
addrSuffix=205
; -----------------------------------------------------------------------------
; 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.149.0
; Override the keychip's region code.
; 1: JAPAN (ALL.Net, Japanese language, Option support enabled)
; 4: EXPORT (Local networking only, English language, No option support)
; 8: CHINA
;
; NOTE: Changing this setting causes a factory reset. The language can be
; changed in the game settings, so it's possible to run the JAPAN region
; with English language.
region=1
[system]
; Enable ALLS system settings.
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
; For Mario & Sonic at the Tokyo 2020 Olympics Arcade, DipSw 1/2/3 must be set
; as the following:
; Cabinet ID 1 (Server): 1 0 0
; Cabinet ID 2 (Client): 0 1 0
; Cabinet ID 3 (Client): 0 0 1
; Cabinet ID 4 (Client): 0 1 1
dipsw1=1
dipsw2=0
dipsw3=0
; -----------------------------------------------------------------------------
; LED settings
; -----------------------------------------------------------------------------
[led15093]
; Enable emulation of the 15093-04 controlled lights, which handle the cabinet
; LEDs.
enable=1
; -----------------------------------------------------------------------------
; Misc. hook settings
; -----------------------------------------------------------------------------
[zinput]
; Disables the built-in DirectInput support, which is used to support a
; controller out of the box.
enable=1
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[tokyoio]
; To use a custom Mario & Sonic at the Tokyo 2020 Olympics Arcade IO DLL enter
; its path here. Leave empty if you want to use Segatools built-in keyboard/
; gamepad 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.
[io4]
; 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
; Input API selection for IO4 input emulator.
; Set "xinput" to use a gamepad and "keyboard" to use a keyboard.
mode=xinput
; Mario & Sonic at the Tokyo 2020 Olympics Arcade Control Panel
;
; |--|------------------ Main-Assy ------------------|--|
; | | YELLOW | |
; | | --- | |
; | | ( O ) | |
; |--| BLUE --- RED |--|
; | | --- PUSH CENTER --- | |
; | | ( O ) /---------------\ ( O ) | |
; | | --- / \ --- | |
; | | PUSH LEFT / \ PUSH RIGHT| |
; |--|---------/ Floor Assy \---------|--|
; | | |JUMP SENSE JUMP SENSE| | |
; | | |1|---------------|-|-------------->|1| | |
; | | | | Foot Panel | | Foot Panel | | | |
; | | |2|<- - - - - - - |-| - - - - - - - |2| | |
; | | | | | | | | | |
; | | |3| -FOOT SENSE - |-| - FOOT SENSE->|3| | |
; | | | | L | | R | | | |
; | | |4|<- - - - - - - |-| - - - - - - - |4| | |
; | | | | | | | | | |
; | | |5| - - - - - - - |-| - - - - - - ->|5| | |
; | | | | | | | | | |
; | | |6|<--------------|-|---------------|6| | |
; | | | | | |
; | | | | | |
; |--|----|-------------------------------------|----|--|
;
; XInput bindings
;
; X Push Left Blue
; Y Push Center Yellow
; B Push Right Red
; D-Pad Left Push Left Blue
; D-Pad Right Push Right Red
; Left Trigger Foot Sense L/Jump Sense
; Right Trigger Foot Sense R/Jump Sense
[keyboard]
; Keyboard bindings
; Keyoard: Push button settings
; PUSH LEFT (BLUE) button virtual-key code. Default is the A key.
leftBlue=0x41
; PUSH CENTER (YELLOW) button virtual-key code. Default is the S key.
centerYellow=0x53
; PUSH RIGHT (RED) button virtual-key code. Default is the D key.
rightRed=0x44
; Keyboard: Sensor settings
; FOOT SENSE L (LEFT) button virtual-key code. Default is the Left Arrow key.
footLeft=0x25
; FOOT SENSE R (RIGHT) button virtual-key code. Default is the Right Arrow key.
footRight=0x27
; Keyboard: Jump sensor settings
; All jump sensors will also trigger the FOOT SENSE L and FOOT SENSE R buttons.
; JUMP SENSOR 1 button virtual-key code. Default is the Z key.
jump1=0x5A
; JUMP SENSOR 2 button virtual-key code. Default is the X key.
jump2=0x58
; JUMP SENSOR 3 button virtual-key code. Default is the C key.
jump3=0x43
; JUMP SENSOR 4 button virtual-key code. Default is the B key.
jump4=0x42
; JUMP SENSOR 5 button virtual-key code. Default is the N key.
jump5=0x4E
; JUMP SENSOR 6 button virtual-key code. Default is the M key.
jump6=0x4D
; Virtual-key code for all jump sensors. Default is the Space key.
jumpAll=0x20

57
dist/tokyo/start.bat vendored
View File

@ -1,57 +0,0 @@
@echo off
pushd %~dp0
set DAEMON_WAIT_SECONDS=5
set AMDAEMON_CFG=config_common.json ^
config_ch.json ^
config_ex.json ^
config_jp.json ^
config_st1_ch.json ^
config_st1_ex.json ^
config_st1_jp.json ^
config_st2_ch.json ^
config_st2_ex.json ^
config_st2_jp.json ^
config_st3_ch.json ^
config_st3_ex.json ^
config_st3_jp.json ^
config_st4_ch.json ^
config_st4_ex.json ^
config_st4_jp.json ^
config_laninstall_server_ch.json ^
config_laninstall_client1_ch.json ^
config_laninstall_client2_ch.json ^
config_laninstall_client3_ch.json ^
config_laninstall_server_ex.json ^
config_laninstall_client1_ex.json ^
config_laninstall_client2_ex.json ^
config_laninstall_client3_ex.json ^
config_laninstall_server_jp.json ^
config_laninstall_client1_jp.json ^
config_laninstall_client2_jp.json ^
config_laninstall_client3_jp.json ^
config_hook.json
start /min "AM Daemon" inject -d -k tokyohook.dll amdaemon.exe -c %AMDAEMON_CFG%
timeout %DAEMON_WAIT_SECONDS% > nul 2>&1
REM ---------------------------------------------------------------------------
REM Set configuration
REM ---------------------------------------------------------------------------
REM Configuration values to be passed to the game executable.
REM All known values:
REM -forceapi:11
REM -forcehal
REM -forcevsync:0/1
REM -fullscreen
REM -windowed
REM Note: -windowed is recommended as the game looks sharper in windowed mode.
inject -d -k tokyohook.dll app.exe -windowed
taskkill /f /im amdaemon.exe > nul 2>&1
echo.
echo Game processes have terminated
pause

View File

@ -8,9 +8,6 @@
#include "board/config.h"
#include "board/sg-reader.h"
#include "hooklib/config.h"
#include "hooklib/dvd.h"
#include "divahook/config.h"
#include "platform/config.h"
@ -50,8 +47,6 @@ void diva_hook_config_load(
platform_config_load(&cfg->platform, filename);
amex_config_load(&cfg->amex, filename);
aime_config_load(&cfg->aime, filename);
dvd_config_load(&cfg->dvd, filename);
gfx_config_load(&cfg->gfx, filename);
diva_dll_config_load(&cfg->dll, filename);
slider_config_load(&cfg->slider, filename);
}

View File

@ -6,25 +6,15 @@
#include "board/sg-reader.h"
#include "hooklib/dvd.h"
#include "hooklib/touch.h"
#include "gfxhook/config.h"
#include "platform/config.h"
#include "divahook/3mpxsc.h"
#include "divahook/diva-dll.h"
#include "divahook/slider.h"
#include "platform/platform.h"
struct diva_hook_config {
struct platform_config platform;
struct amex_config amex;
struct aime_config aime;
struct dvd_config dvd;
struct gfx_config gfx;
struct touch3mpxsc_config touch3mpxsc;
struct touch_screen_config touch;
struct diva_dll_config dll;
struct slider_config slider;
};

View File

@ -1,14 +1,3 @@
/*
"Hatsune Miku Project DIVA Arcade " (diva) hook
Devices
JVS: 837-14572 "Type 3" I/O Board
COM1: 3M Touch Systems 78-0011-2353-4 Touch Controller Board
COM10: TN32MSEC003S "Gen 1" Aime Reader
COM11: 837-15275 Touch Slider
*/
#include <windows.h>
#include <stdlib.h>
@ -22,9 +11,6 @@
#include "divahook/jvs.h"
#include "divahook/slider.h"
#include "gfxhook/gfx.h"
#include "gfxhook/gl.h"
#include "hook/process.h"
#include "hooklib/serial.h"
@ -41,30 +27,15 @@ static struct diva_hook_config diva_hook_cfg;
static DWORD CALLBACK diva_pre_startup(void)
{
HRESULT hr;
HMODULE dbghelp;
dprintf("--- Begin diva_pre_startup ---\n");
/* Pin dbghelp so the path hooks apply to it. */
dbghelp = LoadLibraryW(L"dbghelp.dll");
if (dbghelp != NULL) {
dprintf("Pinned debug helper library, hMod=%p\n", dbghelp);
}
else {
dprintf("Failed to load debug helper library!\n");
}
/* Config load */
diva_hook_config_load(&diva_hook_cfg, L".\\segatools.ini");
/* Hook Win32 APIs */
dvd_hook_init(&diva_hook_cfg.dvd, diva_hook_mod);
gfx_hook_init(&diva_hook_cfg.gfx);
gfx_gl_hook_init(&diva_hook_cfg.gfx, diva_hook_mod);
serial_hook_init();
/* Initialize emulation hooks */

View File

@ -63,33 +63,33 @@ static void diva_jvs_read_switches(void *ctx, struct io3_switch_state *out)
diva_dll.jvs_poll(&opbtn, &gamebtn);
if (gamebtn & DIVA_IO_GAMEBTN_CIRCLE) {
if (gamebtn & 0x01) {
out->p1 |= 1 << 6;
}
if (gamebtn & DIVA_IO_GAMEBTN_CROSS) {
if (gamebtn & 0x02) {
out->p1 |= 1 << 7;
}
if (gamebtn & DIVA_IO_GAMEBTN_SQUARE) {
if (gamebtn & 0x04) {
out->p1 |= 1 << 8;
}
if (gamebtn & DIVA_IO_GAMEBTN_TRIANGLE) {
if (gamebtn & 0x08) {
out->p1 |= 1 << 9;
}
if (gamebtn & DIVA_IO_GAMEBTN_START) {
if (gamebtn & 0x10) {
out->p1 |= 1 << 15;
}
if (opbtn & DIVA_IO_OPBTN_TEST) {
if (opbtn & 0x01) {
out->system = 0x80;
} else {
out->system = 0;
}
if (opbtn & DIVA_IO_OPBTN_SERVICE) {
if (opbtn & 0x02) {
out->p1 |= 1 << 14;
}
}

View File

@ -14,7 +14,6 @@ shared_library(
amex_lib,
board_lib,
divaio_lib,
gfxhook_lib,
hooklib_lib,
jvs_lib,
platform_lib,

View File

@ -99,7 +99,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
}
for (;;) {
#if defined(LOG_DIVA_SLIDER)
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&slider_uart.written);
#endif
@ -118,7 +118,7 @@ static HRESULT slider_handle_irp_locked(struct irp *irp)
return hr;
}
#if defined(LOG_DIVA_SLIDER)
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif

View File

@ -37,11 +37,11 @@ void diva_io_jvs_poll(uint8_t *opbtn_out, uint8_t *gamebtn_out)
opbtn = 0;
if (GetAsyncKeyState(diva_io_cfg.vk_test) & 0x8000) {
opbtn |= DIVA_IO_OPBTN_TEST;
opbtn |= 1;
}
if (GetAsyncKeyState(diva_io_cfg.vk_service) & 0x8000) {
opbtn |= DIVA_IO_OPBTN_SERVICE;
opbtn |= 2;
}
for (i = 0 ; i < _countof(diva_io_cfg.vk_buttons) ; i++) {

View File

@ -5,19 +5,6 @@
#include <stdbool.h>
#include <stdint.h>
enum {
DIVA_IO_OPBTN_TEST = 0x01,
DIVA_IO_OPBTN_SERVICE = 0x02
};
enum {
DIVA_IO_GAMEBTN_CIRCLE = 0x01,
DIVA_IO_GAMEBTN_CROSS = 0x02,
DIVA_IO_GAMEBTN_SQUARE = 0x04,
DIVA_IO_GAMEBTN_TRIANGLE = 0x08,
DIVA_IO_GAMEBTN_START = 0x10,
};
/* Get the version of the Project Diva IO API that this DLL supports. This
function should return a positive 16-bit integer, where the high byte is
the major version and the low byte is the minor version (as defined by the

View File

@ -92,21 +92,9 @@ Controls emulation of the VFD GP1232A02A FUTABA assembly.
Default: `1`
Enable VFD emulation. Disable to use a real VFD
Enable VFD emulation (currently just stubbed). Disable to use a real VFD
GP1232A02A FUTABA assembly (COM port number varies by game).
### `portNo`
Default: (game specific)
Sets the COM port to use for the VFD.
### `utfConversion`
Default: `0`
Converts the strings from the VFD from their respective encoding to UTF, so console output will display as it should on non-Japanese locales.
## `[amvideo]`
Controls the `amvideo.dll` stub built into Segatools. This is a DLL that is
@ -364,7 +352,7 @@ Enable keychip emulation. Disable to use a real keychip.
Default: `A69E-01A88888888`
Keychip serial number. Keychip serials observed in the wild follow this
pattern: `A\d{2}(E|X)-(01|20)[ABCDU]\d{8}`.
pattern: `A6xE-01Ayyyyyyyy`.
### `gameId`

View File

@ -122,6 +122,5 @@ void fgo_hook_config_load(
fgo_deck_config_load(&cfg->deck, filename);
ftdi_config_load(&cfg->ftdi, filename);
led15093_config_load(&cfg->led15093, filename);
gfx_config_load(&cfg->gfx, filename);
fgo_dll_config_load(&cfg->dll, filename);
}

View File

@ -9,8 +9,6 @@
#include "hooklib/touch.h"
#include "hooklib/printer.h"
#include "gfxhook/config.h"
#include "fgohook/deck.h"
#include "fgohook/ftdi.h"
#include "fgohook/fgo-dll.h"
@ -28,7 +26,6 @@ struct fgo_hook_config {
struct deck_config deck;
struct ftdi_config ftdi;
struct led15093_config led15093;
struct gfx_config gfx;
struct fgo_dll_config dll;
};

View File

@ -1,20 +1,3 @@
/*
"Fate Grand/Order Arcade" (fgo) hook
Devices
USB: 837-15257 "Type 4" I/O Board
USB: 838-15405 "WinTouch" Controller Board
USB: 630-00008 Sinfonia CHC-C330 Printer
USB: 837-14509-02 USB-SER I/F BD Mini-B FTDI Board
connected to
837-15093-06 LED Controller Board
COM1: 200-6275 VFD GP1232A02A FUTABA Board
COM2: 837-15345 RFID Deck Reader Noard
COM3: 837-15396 "Gen 3" Aime Reader
COM4: 837-15347 RFID Reader/Writer Board (inside the printer)
*/
#include <windows.h>
#include <stdlib.h>
@ -26,7 +9,6 @@
#include "hook/process.h"
#include "hooklib/dll.h"
#include "hooklib/dvd.h"
#include "hooklib/touch.h"
#include "hooklib/printer.h"
@ -34,8 +16,6 @@
#include "hooklib/serial.h"
#include "hooklib/spike.h"
#include "gfxhook/gfx.h"
#include "fgohook/config.h"
#include "fgohook/io4.h"
#include "fgohook/fgo-dll.h"
@ -52,21 +32,9 @@ static struct fgo_hook_config fgo_hook_cfg;
static DWORD CALLBACK fgo_pre_startup(void)
{
HRESULT hr;
HMODULE dbghelp;
dprintf("--- Begin fgo_pre_startup ---\n");
/* Pin dbghelp so the path hooks apply to it. */
dbghelp = LoadLibraryW(L"dbghelp.dll");
if (dbghelp != NULL) {
dprintf("Pinned debug helper library, hMod=%p\n", dbghelp);
}
else {
dprintf("Failed to load debug helper library!\n");
}
/* Load config */
fgo_hook_config_load(&fgo_hook_cfg, L".\\segatools.ini");
@ -74,15 +42,12 @@ static DWORD CALLBACK fgo_pre_startup(void)
/* Hook Win32 APIs */
dvd_hook_init(&fgo_hook_cfg.dvd, fgo_hook_mod);
gfx_hook_init(&fgo_hook_cfg.gfx);
touch_screen_hook_init(&fgo_hook_cfg.touch, fgo_hook_mod);
serial_hook_init();
/* Hook external DLL APIs */
printer_hook_init(&fgo_hook_cfg.printer, 4, fgo_hook_mod);
dll_hook_push(fgo_hook_mod, L"C330Ausb.dll");
dll_hook_push(fgo_hook_mod, L"C330AFWDLusb.dll");
/* Initialize emulation hooks */

View File

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

View File

@ -18,7 +18,7 @@ EXPORTS
fgo_io_init
fgo_io_poll
fgo_io_led_init
fgo_io_led_set_colors
fgo_io_led_set_leds
fwdlusb_open
fwdlusb_close
fwdlusb_listupPrinter
@ -44,7 +44,7 @@ EXPORTS
chcusb_selectPrinter
chcusb_selectPrinterSN
chcusb_getPrinterInfo
chcusb_imageformat=chcusb_imageformat_330
chcusb_imageformat
chcusb_setmtf
chcusb_makeGamma
chcusb_setIcctable

View File

@ -13,7 +13,6 @@ shared_library(
link_with : [
aimeio_lib,
board_lib,
gfxhook_lib,
hooklib_lib,
fgoio_lib,
platform_lib,

View File

@ -145,7 +145,7 @@ HRESULT fgo_io_led_init(void)
return S_OK;
}
void fgo_io_led_set_colors(uint8_t board, uint8_t *rgb)
void fgo_io_led_set_leds(uint8_t board, uint8_t *rgb)
{
return;
}
}

View File

@ -52,12 +52,16 @@ HRESULT fgo_io_poll(void);
void fgo_io_get_opbtns(uint8_t *opbtn);
/* Get the state of the cabinet's gameplay buttons as of the last poll. See
FGO_IO_GAMEBTN enum above: this contains bit mask definitions for button
states returned in *gamebtn. All buttons are active-high.
FGO_IO_GAMEBTN enum above for bit mask definitions. Inputs are split into
a left hand side set of inputs and a right hand side set of inputs: the bit
mappings are the same in both cases.
All buttons are active-high, even though some buttons' electrical signals
on a real cabinet are active-low.
Minimum API version: 0x0100 */
void fgo_io_get_gamebtns(uint8_t *gamebtn);
void fgo_io_get_gamebtns(uint8_t *btn);
/* Get the position of the cabinet stick as of the last poll. The center
position should be equal to or close to 32767.
@ -79,4 +83,4 @@ HRESULT fgo_io_led_init(void);
Exact layout is TBD. */
void fgo_io_led_set_colors(uint8_t board, uint8_t *rgb);
void fgo_io_led_set_leds(uint8_t board, uint8_t *rgb);

View File

@ -224,19 +224,9 @@ static HRESULT STDMETHODCALLTYPE my_IDirect3D9_CreateDevice(
gfx_util_frame_window(hwnd);
}
UINT max_adapter = IDirect3D9_GetAdapterCount(real);
adapter = gfx_config.monitor;
if (adapter >= max_adapter) {
dprintf(
"Gfx: Requested adapter %d but maximum is %d. Using primary monitor\n",
gfx_config.monitor, max_adapter - 1
);
adapter = D3DADAPTER_DEFAULT;
} else {
dprintf("Gfx: Using adapter %d\n", gfx_config.monitor);
}
dprintf("Gfx: Using adapter %d\n", gfx_config.monitor);
return IDirect3D9_CreateDevice(real, adapter, type, hwnd, flags, pp, pdev);
return IDirect3D9_CreateDevice(real, gfx_config.monitor, type, hwnd, flags, pp, pdev);
}
static HRESULT STDMETHODCALLTYPE my_IDirect3D9Ex_CreateDevice(

View File

@ -9,53 +9,18 @@
#include "util/dprintf.h"
/* Hook functions */
typedef BOOL (WINAPI *ShowWindow_t)(HWND hWnd, int nCmdShow);
static BOOL WINAPI hook_ShowWindow(HWND hWnd, int nCmdShow);
static BOOL WINAPI hook_CreateWindowExA(
DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
/* Link pointers */
static BOOL (WINAPI *next_ShowWindow)(HWND hWnd, int nCmdShow);
static BOOL (WINAPI *next_CreateWindowExA)(
DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
);
static struct gfx_config gfx_config;
static ShowWindow_t next_ShowWindow;
static const struct hook_symbol gfx_hooks[] = {
{
.name = "ShowWindow",
.patch = hook_ShowWindow,
.link = (void **) &next_ShowWindow,
}, {
.name = "CreateWindowExA",
.patch = hook_CreateWindowExA,
.link = (void **) &next_CreateWindowExA,
},
};
@ -81,45 +46,3 @@ static BOOL WINAPI hook_ShowWindow(HWND hWnd, int nCmdShow)
return next_ShowWindow(hWnd, nCmdShow);
}
static BOOL WINAPI hook_CreateWindowExA(
DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
DWORD dwStyle,
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
)
{
dprintf("Gfx: CreateWindowExA hook hit\n");
// Set to WS_OVERLAPPEDWINDOW to enable a window with a border and windowed style
if (gfx_config.windowed) {
dwStyle = WS_OVERLAPPEDWINDOW;
if (!gfx_config.framed) {
dwStyle = WS_POPUP;
}
}
return next_CreateWindowExA(
dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
X,
Y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam
);
}

View File

@ -1,77 +0,0 @@
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include "gfxhook/gfx.h"
#include "gfxhook/gl.h"
#include "hook/table.h"
#include "hooklib/dll.h"
#include "util/dprintf.h"
/* Hook functions */
static void WINAPI hook_glutFullScreen(void);
static void WINAPI hook_glutInitDisplayMode(unsigned int mode);
/* Link pointers */
static void (WINAPI *next_glutFullScreen)(void);
static void (WINAPI *next_glutInitDisplayMode)(unsigned int mode);
static struct gfx_config gfx_config;
static const struct hook_symbol glut_hooks[] = {
{
.name = "glutFullScreen",
.patch = hook_glutFullScreen,
.link = (void **) &next_glutFullScreen,
}, {
.name = "glutInitDisplayMode",
.patch = hook_glutInitDisplayMode,
.link = (void **) &next_glutInitDisplayMode,
},
};
void gfx_gl_hook_init(const struct gfx_config *cfg, HINSTANCE self)
{
assert(cfg != NULL);
if (!cfg->enable) {
return;
}
memcpy(&gfx_config, cfg, sizeof(*cfg));
hook_table_apply(NULL, "glut32.dll", glut_hooks, _countof(glut_hooks));
if (self != NULL) {
dll_hook_push(self, L"glut32.dll");
}
}
static void WINAPI hook_glutFullScreen(void)
{
dprintf("Gfx: glutFullScreen hook hit\n");
if (gfx_config.windowed) {
return;
}
return next_glutFullScreen();
}
static void WINAPI hook_glutInitDisplayMode(unsigned int mode)
{
dprintf("Gfx: glutInitDisplayMode hook hit\n");
// GLUT adds a frame when going windowed
if (gfx_config.windowed && !gfx_config.framed) {
// GLUT_BORDERLESS
mode |= 0x0800;
}
return next_glutInitDisplayMode(mode);
}

View File

@ -1,3 +0,0 @@
#pragma once
void gfx_gl_hook_init(const struct gfx_config *cfg, HINSTANCE self);

View File

@ -22,8 +22,6 @@ gfxhook_lib = static_library(
'dxgi.h',
'gfx.c',
'gfx.h',
'gl.c',
'gl.h',
'util.c',
'util.h',
],

View File

@ -80,6 +80,4 @@ void printer_config_load(struct printer_config *cfg, const wchar_t *filename)
cfg->printer_out_path,
_countof(cfg->printer_out_path),
filename);
cfg->wait_time = GetPrivateProfileIntW(L"printer", L"waitTime", 0, filename);
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct printer_config {
bool enable;
@ -12,13 +11,6 @@ struct printer_config {
wchar_t dsp_fw_path[MAX_PATH];
wchar_t param_fw_path[MAX_PATH];
wchar_t printer_out_path[MAX_PATH];
uint32_t wait_time;
};
void printer_hook_init(const struct printer_config *cfg, int rfid_port_no, HINSTANCE self);
void printer_hook_insert_hooks(HMODULE target);
void printer_set_dimensions(int width, int height);
int WINAPI fwdlusb_updateFirmware_main(uint8_t update, LPCSTR filename, uint16_t *rResult);
int WINAPI fwdlusb_updateFirmware_dsp(uint8_t update, LPCSTR filename, uint16_t *rResult);
int WINAPI fwdlusb_updateFirmware_param(uint8_t update, LPCSTR filename, uint16_t *rResult);

125
hooklib/procaddr.c Normal file
View File

@ -0,0 +1,125 @@
#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;
}

18
hooklib/procaddr.h Normal file
View File

@ -0,0 +1,18 @@
#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
);

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