Compare commits

...

7 Commits

23 changed files with 980 additions and 7 deletions

12
.vscode/settings.json vendored
View File

@ -1,4 +1,8 @@
{
"editor.formatOnSave": false,
"mesonbuild.configureOnOpen": false,
}
{
"editor.formatOnSave": false,
"mesonbuild.configureOnOpen": false,
"files.associations": {
"*.embeddedhtml": "html",
"config.h": "c"
},
}

View File

@ -203,6 +203,21 @@ $(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)/apm3.zip:
$(V)echo ... $@
$(V)mkdir -p $(BUILD_DIR_ZIP)/apm3
$(V)mkdir -p $(BUILD_DIR_ZIP)/apm3/DEVICE
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject.exe \
$(BUILD_DIR_64)/apm3hook/apm3hook.dll \
$(DIST_DIR)/apm3/segatools.ini \
$(DIST_DIR)/apm3/start.bat \
$(BUILD_DIR_ZIP)/apm3
$(V)cp pki/billing.pub \
pki/ca.crt \
$(BUILD_DIR_ZIP)/apm3/DEVICE
$(V)strip $(BUILD_DIR_ZIP)/apm3/*.{exe,dll}
$(V)cd $(BUILD_DIR_ZIP)/apm3 ; zip -r ../apm3.zip *
$(BUILD_DIR_ZIP)/tokyo.zip:
$(V)echo ... $@
$(V)mkdir -p $(BUILD_DIR_ZIP)/tokyo
@ -241,6 +256,7 @@ $(BUILD_DIR_ZIP)/segatools.zip: \
$(BUILD_DIR_ZIP)/mu3.zip \
$(BUILD_DIR_ZIP)/mai2.zip \
$(BUILD_DIR_ZIP)/cm.zip \
$(BUILD_DIR_ZIP)/apm3.zip \
$(BUILD_DIR_ZIP)/tokyo.zip \
$(BUILD_DIR_ZIP)/fgo.zip \
CHANGELOG.md \

112
apm3hook/apm3-dll.c Normal file
View File

@ -0,0 +1,112 @@
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include "apm3hook/apm3-dll.h"
#include "util/dll-bind.h"
#include "util/dprintf.h"
const struct dll_bind_sym apm3_dll_syms[] = {
{
.sym = "apm3_io_init",
.off = offsetof(struct apm3_dll, init),
}, {
.sym = "apm3_io_poll",
.off = offsetof(struct apm3_dll, poll),
}, {
.sym = "apm3_io_get_opbtns",
.off = offsetof(struct apm3_dll, get_opbtns),
}, {
.sym = "apm3_io_led_init",
.off = offsetof(struct apm3_dll, led_init),
}, {
.sym = "apm3_io_led_set_colors",
.off = offsetof(struct apm3_dll, led_set_leds),
}
};
struct apm3_dll apm3_dll;
// Copypasta DLL binding and diagnostic message boilerplate.
// Not much of this lends itself to being easily factored out. Also there
// will be a lot of API-specific branching code here eventually as new API
// versions get defined, so even though these functions all look the same
// now this won't remain the case forever.
HRESULT apm3_dll_init(const struct apm3_dll_config *cfg, HINSTANCE self)
{
uint16_t (*get_api_version)(void);
const struct dll_bind_sym *sym;
HINSTANCE owned;
HINSTANCE src;
HRESULT hr;
assert(cfg != NULL);
assert(self != NULL);
if (cfg->path[0] != L'\0') {
owned = LoadLibraryW(cfg->path);
if (owned == NULL) {
hr = HRESULT_FROM_WIN32(GetLastError());
dprintf("CardMaker IO: Failed to load IO DLL: %lx: %S\n",
hr,
cfg->path);
goto end;
}
dprintf("CardMaker IO: Using custom IO DLL: %S\n", cfg->path);
src = owned;
} else {
owned = NULL;
src = self;
}
get_api_version = (void *) GetProcAddress(src, "apm3_io_get_api_version");
if (get_api_version != NULL) {
apm3_dll.api_version = get_api_version();
} else {
apm3_dll.api_version = 0x0100;
dprintf("Custom IO DLL does not expose apm3_io_get_api_version, "
"assuming API version 1.0.\n"
"Please ask the developer to update their DLL.\n");
}
if (apm3_dll.api_version >= 0x0200) {
hr = E_NOTIMPL;
dprintf("CardMaker IO: Custom IO DLL implements an unsupported "
"API version (%#04x). Please update Segatools.\n",
apm3_dll.api_version);
goto end;
}
sym = apm3_dll_syms;
hr = dll_bind(&apm3_dll, src, &sym, _countof(apm3_dll_syms));
if (FAILED(hr)) {
if (src != self) {
dprintf("CardMaker IO: Custom IO DLL does not provide function "
"\"%s\". Please contact your IO DLL's developer for "
"further assistance.\n",
sym->sym);
goto end;
} else {
dprintf("Internal error: could not reflect \"%s\"\n", sym->sym);
}
}
owned = NULL;
end:
if (owned != NULL) {
FreeLibrary(owned);
}
return hr;
}

22
apm3hook/apm3-dll.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <windows.h>
#include "apm3io/apm3io.h"
struct apm3_dll {
uint16_t api_version;
HRESULT (*init)(void);
HRESULT (*poll)(void);
void (*get_opbtns)(uint8_t *opbtn);
HRESULT (*led_init)(void);
void (*led_set_leds)(uint8_t board, uint8_t *rgb);
};
struct apm3_dll_config {
wchar_t path[MAX_PATH];
};
extern struct apm3_dll apm3_dll;
HRESULT apm3_dll_init(const struct apm3_dll_config *cfg, HINSTANCE self);

75
apm3hook/apm3hook.def Normal file
View File

@ -0,0 +1,75 @@
LIBRARY apm3hook
EXPORTS
aime_io_get_api_version
aime_io_init
aime_io_led_set_color
aime_io_nfc_get_aime_id
aime_io_nfc_get_felica_id
aime_io_nfc_poll
amDllVideoClose @2
amDllVideoGetVBiosVersion @4
amDllVideoOpen @1
amDllVideoSetResolution @3
apm3_io_get_api_version
apm3_io_get_opbtns
apm3_io_init
apm3_io_poll
apm3_io_led_init
apm3_io_led_set_colors
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

105
apm3hook/config.c Normal file
View File

@ -0,0 +1,105 @@
#include <assert.h>
#include <stddef.h>
#include "board/config.h"
#include "hooklib/config.h"
#include "hooklib/dvd.h"
#include "apm3hook/config.h"
#include "platform/config.h"
void apm3_dll_config_load(
struct apm3_dll_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
GetPrivateProfileStringW(
L"apm3io",
L"path",
L"",
cfg->path,
_countof(cfg->path),
filename);
}
void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
wchar_t tmpstr[16];
memset(cfg->board_number, ' ', sizeof(cfg->board_number));
memset(cfg->chip_number, ' ', sizeof(cfg->chip_number));
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->port_no = GetPrivateProfileIntW(L"led15093", L"portNo", 0, filename);
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaud", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xAA53, filename);
GetPrivateProfileStringW(
L"led15093",
L"boardNumber",
L"15093-06",
tmpstr,
_countof(tmpstr),
filename);
size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number));
for (int i = n; i < sizeof(cfg->board_number); i++)
{
cfg->board_number[i] = ' ';
}
GetPrivateProfileStringW(
L"led15093",
L"chipNumber",
L"6710A",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number));
for (int i = n; i < sizeof(cfg->chip_number); i++)
{
cfg->chip_number[i] = ' ';
}
GetPrivateProfileStringW(
L"led15093",
L"bootChipNumber",
L"6709 ",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->boot_chip_number, tmpstr, sizeof(cfg->boot_chip_number));
for (int i = n; i < sizeof(cfg->boot_chip_number); i++)
{
cfg->boot_chip_number[i] = ' ';
}
}
void apm3_hook_config_load(
struct apm3_hook_config *cfg,
const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
platform_config_load(&cfg->platform, filename);
aime_config_load(&cfg->aime, filename);
dvd_config_load(&cfg->dvd, filename);
io4_config_load(&cfg->io4, filename);
led15093_config_load(&cfg->led15093, filename);
vfd_config_load(&cfg->vfd, filename);
touch_screen_config_load(&cfg->touch, filename);
apm3_dll_config_load(&cfg->dll, filename);
unity_config_load(&cfg->unity, filename);
}

36
apm3hook/config.h Normal file
View File

@ -0,0 +1,36 @@
#pragma once
#include <stddef.h>
#include "board/config.h"
#include "board/led15093.h"
#include "hooklib/dvd.h"
#include "hooklib/touch.h"
#include "hooklib/printer.h"
#include "apm3hook/apm3-dll.h"
#include "platform/config.h"
#include "unityhook/config.h"
struct apm3_hook_config {
struct platform_config platform;
struct aime_config aime;
struct dvd_config dvd;
struct io4_config io4;
struct led15093_config led15093;
struct vfd_config vfd;
struct apm3_dll_config dll;
struct touch_screen_config touch;
struct unity_config unity;
};
void apm3_dll_config_load(
struct apm3_dll_config *cfg,
const wchar_t *filename);
void apm3_hook_config_load(
struct apm3_hook_config *cfg,
const wchar_t *filename);

139
apm3hook/dllmain.c Normal file
View File

@ -0,0 +1,139 @@
/*
"ALLS.NET PRAS MULTI 3" (apm3) hook
Devices
USB: 837-15257-01 "Type 4" I/O Board
USB: 838-20006 "WinTouch" Controller Board
COM1: 200-6275 VFD GP1232A02A FUTABA Board
COM2: 837-15093-06 LED Controller Board
COM3: 837-15396 "Gen 3" Aime Reader
*/
#include <windows.h>
#include <stdlib.h>
#include "board/io4.h"
#include "board/sg-reader.h"
#include "board/vfd.h"
#include "hook/process.h"
#include "hooklib/dvd.h"
#include "hooklib/touch.h"
#include "hooklib/serial.h"
#include "hooklib/spike.h"
#include "apm3hook/config.h"
#include "apm3hook/io4.h"
#include "apm3hook/apm3-dll.h"
#include "platform/platform.h"
#include "unityhook/hook.h"
#include "util/dprintf.h"
static HMODULE apm3_hook_mod;
static process_entry_t apm3_startup;
static struct apm3_hook_config apm3_hook_cfg;
static DWORD CALLBACK apm3_pre_startup(void)
{
HRESULT hr;
dprintf("--- Begin apm3_pre_startup ---\n");
/* Load config */
apm3_hook_config_load(&apm3_hook_cfg, L".\\segatools.ini");
/* Hook Win32 APIs */
dvd_hook_init(&apm3_hook_cfg.dvd, apm3_hook_mod);
touch_screen_hook_init(&apm3_hook_cfg.touch, apm3_hook_mod);
serial_hook_init();
/* Initialize emulation hooks */
hr = platform_hook_init(
&apm3_hook_cfg.platform,
"SDEM",
"ACA1",
apm3_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = apm3_dll_init(&apm3_hook_cfg.dll, apm3_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = led15093_hook_init(&apm3_hook_cfg.led15093,
apm3_dll.led_init, apm3_dll.led_set_leds, 2, 1, 1, 2);
if (FAILED(hr)) {
return hr;
}
hr = sg_reader_hook_init(&apm3_hook_cfg.aime, 3, 1, apm3_hook_mod);
if (FAILED(hr)) {
goto fail;
}
hr = vfd_hook_init(&apm3_hook_cfg.vfd, 1);
if (FAILED(hr)) {
goto fail;
}
hr = apm3_io4_hook_init(&apm3_hook_cfg.io4);
if (FAILED(hr)) {
goto fail;
}
/* Initialize Unity native plugin DLL hooks
There seems to be an issue with other DLL hooks if `LoadLibraryW` is
hooked earlier in the `apm3hook` initialization. */
unity_hook_init(&apm3_hook_cfg.unity, apm3_hook_mod);
/* Initialize debug helpers */
spike_hook_init(L".\\segatools.ini");
dprintf("--- End apm3_pre_startup ---\n");
/* Jump to EXE start address */
return apm3_startup();
fail:
ExitProcess(EXIT_FAILURE);
}
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
{
HRESULT hr;
if (cause != DLL_PROCESS_ATTACH) {
return TRUE;
}
apm3_hook_mod = mod;
hr = process_hijack_startup(apm3_pre_startup, &apm3_startup);
if (!SUCCEEDED(hr)) {
dprintf("Failed to hijack process startup: %x\n", (int) hr);
}
return SUCCEEDED(hr);
}

69
apm3hook/io4.c Normal file
View File

@ -0,0 +1,69 @@
#include <windows.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "board/io4.h"
#include "apm3hook/apm3-dll.h"
#include "util/dprintf.h"
static HRESULT apm3_io4_poll(void *ctx, struct io4_state *state);
static uint16_t coins;
static const struct io4_ops apm3_io4_ops = {
.poll = apm3_io4_poll,
};
HRESULT apm3_io4_hook_init(const struct io4_config *cfg)
{
HRESULT hr;
assert(apm3_dll.init != NULL);
hr = io4_hook_init(cfg, &apm3_io4_ops, NULL);
if (FAILED(hr)) {
return hr;
}
return apm3_dll.init();
}
static HRESULT apm3_io4_poll(void *ctx, struct io4_state *state)
{
uint8_t opbtn;
HRESULT hr;
assert(apm3_dll.poll != NULL);
assert(apm3_dll.get_opbtns != NULL);
memset(state, 0, sizeof(*state));
hr = apm3_dll.poll();
if (FAILED(hr)) {
return hr;
}
opbtn = 0;
apm3_dll.get_opbtns(&opbtn);
if (opbtn & apm3_IO_OPBTN_TEST) {
state->buttons[0] |= IO4_BUTTON_TEST;
}
if (opbtn & apm3_IO_OPBTN_SERVICE) {
state->buttons[0] |= IO4_BUTTON_SERVICE;
}
if (opbtn & apm3_IO_OPBTN_COIN) {
coins++;
}
state->chutes[0] = coins << 8;
return S_OK;
}

7
apm3hook/io4.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
#include <windows.h>
#include "board/io4.h"
HRESULT apm3_io4_hook_init(const struct io4_config *cfg);

31
apm3hook/meson.build Normal file
View File

@ -0,0 +1,31 @@
shared_library(
'apm3hook',
name_prefix : '',
include_directories : inc,
implicit_include_directories : false,
vs_module_defs : 'apm3hook.def',
c_pch : '../precompiled.h',
dependencies : [
capnhook.get_variable('hook_dep'),
capnhook.get_variable('hooklib_dep'),
xinput_lib,
],
link_with : [
aimeio_lib,
board_lib,
hooklib_lib,
apm3io_lib,
platform_lib,
unityhook_lib,
util_lib,
],
sources : [
'config.c',
'config.h',
'dllmain.c',
'io4.c',
'io4.h',
'apm3-dll.c',
'apm3-dll.h',
],
)

72
apm3io/apm3io.c Normal file
View File

@ -0,0 +1,72 @@
#include <windows.h>
#include <xinput.h>
#include <limits.h>
#include <stdint.h>
#include "apm3io/apm3io.h"
#include "apm3io/config.h"
static uint8_t apm3_opbtn;
static uint8_t apm3_gamebtn;
static struct apm3_io_config apm3_io_cfg;
static bool apm3_io_coin;
uint16_t apm3_io_get_api_version(void)
{
return 0x0100;
}
HRESULT apm3_io_init(void)
{
apm3_io_config_load(&apm3_io_cfg, L".\\segatools.ini");
return S_OK;
}
HRESULT apm3_io_poll(void)
{
apm3_opbtn = 0;
if (GetAsyncKeyState(apm3_io_cfg.vk_test) & 0x8000) {
apm3_opbtn |= apm3_IO_OPBTN_TEST;
}
if (GetAsyncKeyState(apm3_io_cfg.vk_service) & 0x8000) {
apm3_opbtn |= apm3_IO_OPBTN_SERVICE;
}
if (GetAsyncKeyState(apm3_io_cfg.vk_coin) & 0x8000) {
if (!apm3_io_coin) {
apm3_io_coin = true;
apm3_opbtn |= apm3_IO_OPBTN_COIN;
}
} else {
apm3_io_coin = false;
}
return S_OK;
}
void apm3_io_get_opbtns(uint8_t *opbtn)
{
if (opbtn != NULL) {
*opbtn = apm3_opbtn;
}
}
void apm3_io_get_gamebtns(uint8_t *btn)
{
if (btn != NULL) {
*btn = apm3_gamebtn;
}
}
HRESULT apm3_io_led_init(void)
{
return S_OK;
}
void apm3_io_led_set_colors(uint8_t board, uint8_t *rgb)
{
return;
}

65
apm3io/apm3io.h Normal file
View File

@ -0,0 +1,65 @@
#pragma once
#include <windows.h>
#include <stdint.h>
enum {
apm3_IO_OPBTN_TEST = 0x01,
apm3_IO_OPBTN_SERVICE = 0x02,
apm3_IO_OPBTN_COIN = 0x04,
};
enum {
apm3_IO_GAMEBTN_1 = 0x01,
};
/* Get the version of the AllS.Net PRAS Multi 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
Semantic Versioning standard).
The latest API version as of this writing is 0x0100. */
uint16_t apm3_io_get_api_version(void);
/* Initialize the IO DLL. This is the second function that will be called on
your DLL, after apm3_io_get_api_version.
All subsequent calls to this API may originate from arbitrary threads.
Minimum API version: 0x0100 */
HRESULT apm3_io_init(void);
/* Send any queued outputs (of which there are currently none, though this may
change in subsequent API versions) and retrieve any new inputs.
Minimum API version: 0x0100 */
HRESULT apm3_io_poll(void);
/* Get the state of the cabinet's operator buttons as of the last poll. See
apm3_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 apm3_io_get_opbtns(uint8_t *opbtn);
/* Initialize LED emulation. This function will be called before any
other apm3_io_led_*() function calls.
All subsequent calls may originate from arbitrary threads and some may
overlap with each other. Ensuring synchronization inside your IO DLL is
your responsibility.
Minimum API version: 0x0101 */
HRESULT apm3_io_led_init(void);
/* Update the RGB LEDs. rgb is a pointer to an array of up to 61 * 3 = 183 bytes.
Minimum API version: 0x0101 */
void apm3_io_led_set_colors(uint8_t board, uint8_t *rgb);

22
apm3io/config.c Normal file
View File

@ -0,0 +1,22 @@
#include <windows.h>
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include "apm3io/config.h"
void apm3_io_config_load(
struct apm3_io_config *cfg,
const wchar_t *filename)
{
wchar_t key[16];
int i;
assert(cfg != NULL);
assert(filename != NULL);
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", VK_F1, filename);
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", VK_F2, filename);
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", VK_F3, filename);
}

16
apm3io/config.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
struct apm3_io_config {
uint8_t vk_test;
uint8_t vk_service;
uint8_t vk_coin;
};
void apm3_io_config_load(
struct apm3_io_config *cfg,
const wchar_t *filename);

13
apm3io/meson.build Normal file
View File

@ -0,0 +1,13 @@
apm3io_lib = static_library(
'apm3io',
name_prefix : '',
include_directories : inc,
implicit_include_directories : false,
c_pch : '../precompiled.h',
sources : [
'apm3io.c',
'apm3io.h',
'config.c',
'config.h',
],
)

View File

@ -189,13 +189,13 @@ static HRESULT sg_nfc_dispatch(
&req->felica_encap,
&res->felica_encap);
case SG_NFC_CMD_MIFARE_AUTHENTICATE:
case SG_NFC_CMD_MIFARE_AUTHENTICATE_A:
case SG_NFC_CMD_SEND_HEX_DATA:
return sg_nfc_cmd_send_hex_data(nfc, &req->simple, &res->simple);
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_MIFARE_SET_KEY_A:
case SG_NFC_CMD_MIFARE_SET_KEY_B:
case SG_NFC_CMD_RADIO_ON:
case SG_NFC_CMD_RADIO_OFF:
case SG_NFC_CMD_TO_UPDATE_MODE:

108
dist/apm3/segatools.ini vendored Normal file
View File

@ -0,0 +1,108 @@
; -----------------------------------------------------------------------------
; 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 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 their LAN environment, so leaving this
; setting enabled is recommended.
enable=1
; -----------------------------------------------------------------------------
; 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.165.0
[system]
; Enable ALLS system settings.
enable=1
; LAN Install: If multiple machines are present on the same LAN then set
; this to 0 on exactly one machine and set this to 1 on all others.
dipsw1=0
; -----------------------------------------------------------------------------
; Misc. hooks settings
; -----------------------------------------------------------------------------
[touch]
; Enable/Disable WinTouch emulation
enable=1
[unity]
; Path to a .NET DLL that should run before the game. Useful for loading
; modding frameworks such as BepInEx.
targetAssembly=
; -----------------------------------------------------------------------------
; Custom IO settings
; -----------------------------------------------------------------------------
[aimeio]
; To use a custom card reader IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input.
path=
; -----------------------------------------------------------------------------
; Input settings
; -----------------------------------------------------------------------------
; Keyboard bindings are 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
up=0x57
down=0x53
left=0x41
right=0x44

11
dist/apm3/start.bat vendored Normal file
View File

@ -0,0 +1,11 @@
@echo off
pushd %~dp0
start "AM Daemon" /min inject -d -k apm3hook.dll amdaemonD.exe -c daemon_config\common.json daemon_config\standalone.json
inject -d -k apm3hook.dll Apmv3System.exe -screen-fullscreen 0 -popupwindow -screen-width 1920 -screen-height 1080
taskkill /f /im amdaemonD.exe > nul 2>&1
echo.
echo Game processes have terminated

View File

@ -106,6 +106,7 @@ subdir('swdcio')
subdir('mu3io')
subdir('mai2io')
subdir('cmio')
subdir('apm3io')
subdir('mercuryio')
subdir('cxbio')
subdir('tokyoio')
@ -122,6 +123,7 @@ subdir('chusanhook')
subdir('mu3hook')
subdir('mai2hook')
subdir('cmhook')
subdir('apm3hook')
subdir('mercuryhook')
subdir('cxbhook')
subdir('tokyohook')

0
multihook/dllmain.c Normal file
View File

31
multihook/meson.build Normal file
View File

@ -0,0 +1,31 @@
shared_library(
'multihook',
name_prefix : '',
include_directories : inc,
implicit_include_directories : false,
vs_module_defs : 'multihook.def',
c_pch : '../precompiled.h',
dependencies : [
capnhook.get_variable('hook_dep'),
capnhook.get_variable('hooklib_dep'),
xinput_lib,
],
link_with : [
aimeio_lib,
board_lib,
hooklib_lib,
multiio_lib,
platform_lib,
unityhook_lib,
util_lib,
],
sources : [
'config.c',
'config.h',
'dllmain.c',
'io4.c',
'io4.h',
'multi-dll.c',
'multi-dll.h',
],
)

17
multihook/multihook.def Normal file
View File

@ -0,0 +1,17 @@
LIBRARY multihook
EXPORTS
aime_io_get_api_version
aime_io_init
aime_io_led_set_color
aime_io_nfc_get_aime_id
aime_io_nfc_get_felica_id
aime_io_nfc_poll
amDllVideoClose @2
amDllVideoGetVBiosVersion @4
amDllVideoOpen @1
amDllVideoSetResolution @3
multi_io_get_api_version
multi_io_get_opbtns
multi_io_init
multi_io_poll