forked from Hay1tsme/segatools
sekito: add hook
This commit is contained in:
21
Package.mk
21
Package.mk
@ -275,6 +275,27 @@ $(BUILD_DIR_ZIP)/ekt.zip:
|
||||
$(V)strip $(BUILD_DIR_ZIP)/ekt/*.{exe,dll}
|
||||
$(V)cd $(BUILD_DIR_ZIP)/ekt ; zip -r ../ekt.zip *
|
||||
|
||||
$(BUILD_DIR_ZIP)/sekito.zip:
|
||||
$(V)echo ... $@
|
||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/sekito
|
||||
$(V)mkdir -p $(BUILD_DIR_ZIP)/sekito/DEVICE
|
||||
$(V)cp $(BUILD_DIR_32)/subprojects/capnhook/inject/inject_x86.exe \
|
||||
$(V)cp $(BUILD_DIR_64)/subprojects/capnhook/inject/inject_x64.exe \
|
||||
$(BUILD_DIR_GAMES_64)/sekitohook/sekitohook_x64.dll \
|
||||
$(BUILD_DIR_GAMES_32)/sekitohook/sekitohook_x86.dll \
|
||||
$(DIST_DIR)/sekito/segatools_terminal.ini \
|
||||
$(DIST_DIR)/sekito/segatools_satellite.ini \
|
||||
$(DIST_DIR)/sekito/launch_terminal.bat \
|
||||
$(DIST_DIR)/sekito/launch_satellite.bat \
|
||||
$(DIST_DIR)/sekito/card_player.html \
|
||||
$(DIST_DIR)/sekito/config_hook.json \
|
||||
$(BUILD_DIR_ZIP)/sekito
|
||||
$(V)cp pki/billing.pub \
|
||||
pki/ca.crt \
|
||||
$(BUILD_DIR_ZIP)/sekito/DEVICE
|
||||
$(V)strip $(BUILD_DIR_ZIP)/sekito/*.{exe,dll}
|
||||
$(V)cd $(BUILD_DIR_ZIP)/sekito ; zip -r ../sekito.zip *
|
||||
|
||||
$(BUILD_DIR_ZIP)/doc.zip: \
|
||||
$(DOC_DIR)/config \
|
||||
$(DOC_DIR)/chunihook.md \
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
#include <wtypes.h>
|
||||
|
||||
|
224
dist/sekito/card_player.html
vendored
Normal file
224
dist/sekito/card_player.html
vendored
Normal file
@ -0,0 +1,224 @@
|
||||
<!-- very basic thing, I can't do UX/CSS/design, don't blame me, I'm a network engineer lmao -->
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Taisen Card Field</title>
|
||||
</head>
|
||||
<style>
|
||||
html, body {
|
||||
width: 99%;
|
||||
height: 99%;
|
||||
}
|
||||
.playfield {
|
||||
width: 79%;
|
||||
height: 100%;
|
||||
float: left;
|
||||
border: 1px solid black;
|
||||
}
|
||||
.card_menu {
|
||||
width: 20%;
|
||||
height: 100%;
|
||||
border: 1px solid black;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 200px;
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
#playfield .card {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#status {
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
var VERSION = 1;
|
||||
|
||||
var socket;
|
||||
var state = 0;
|
||||
var game_id;
|
||||
var cards = [];
|
||||
var current_card_fetch = 0;
|
||||
|
||||
function send(obj){
|
||||
if (!socket){ return; }
|
||||
var data = JSON.stringify(obj);
|
||||
console.log("Sending: " + data);
|
||||
socket.send(data);
|
||||
}
|
||||
|
||||
function connect(){
|
||||
socket = new WebSocket("ws://127.0.0.1:3497/y3io");
|
||||
|
||||
socket.onopen = function(e) {
|
||||
document.getElementById("status").innerText = "Connected. Loading information...";
|
||||
state = 0;
|
||||
send({
|
||||
version: VERSION,
|
||||
command: "get_game_id"
|
||||
});
|
||||
};
|
||||
|
||||
socket.onmessage = function(event) {
|
||||
console.log("Received: " + event.data);
|
||||
handle_response(JSON.parse(event.data));
|
||||
};
|
||||
|
||||
socket.onclose = function(event) {
|
||||
state = -1;
|
||||
document.getElementById("status").innerHTML = "Disconnected. <a href='javascript:window.location.reload();'>Reconnect</a>";
|
||||
};
|
||||
|
||||
socket.onerror = function(error) {
|
||||
console.log(error);
|
||||
};
|
||||
}
|
||||
|
||||
function handle_response(obj){
|
||||
if (!obj.success){
|
||||
alert("Error receiving data while in state " + state + ": " + obj.error);
|
||||
socket.close();
|
||||
return;
|
||||
}
|
||||
if (state == 0){
|
||||
game_id = obj.game_id;
|
||||
document.getElementById("status").innerText = "Connected to "+game_id+". Loading cards...";
|
||||
state = 1;
|
||||
send({
|
||||
version: VERSION,
|
||||
command: "get_cards"
|
||||
});
|
||||
} else if (state == 1){
|
||||
cards = obj.cards;
|
||||
document.getElementById("status").innerText = "Connected to "+game_id+". Loading card images...";
|
||||
document.getElementById("cards").innerHTML = "";
|
||||
document.getElementById("playfield").innerHTML = "";
|
||||
current_card_fetch = 0;
|
||||
state = 2;
|
||||
if (cards.length > 0){
|
||||
fetch_next_card();
|
||||
} else {
|
||||
document.getElementById("status").innerText = "Connected to "+game_id+". No cards available.";
|
||||
}
|
||||
} else if (state == 2){
|
||||
cards[current_card_fetch].image = obj.data;
|
||||
document.getElementById("cards").innerHTML += "<img class='card' src='data:image/bmp;base64, "+obj.data+"' onclick='spawn_card("+current_card_fetch+");' />";
|
||||
|
||||
if (++current_card_fetch >= cards.length){
|
||||
document.getElementById("status").innerText = "Connected to "+game_id+".";
|
||||
state = 3;
|
||||
} else {
|
||||
fetch_next_card();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function fetch_next_card(){
|
||||
var p = cards[current_card_fetch].path;
|
||||
if (!p.includes("_front")){
|
||||
current_card_fetch++;
|
||||
fetch_next_card();
|
||||
return;
|
||||
}
|
||||
send({
|
||||
version: VERSION,
|
||||
command: "get_card_image",
|
||||
path: p
|
||||
});
|
||||
}
|
||||
|
||||
function spawn_card(i){
|
||||
if (state != 3){
|
||||
return;
|
||||
}
|
||||
|
||||
document.getElementById("playfield").innerHTML += "<img class='card' src='data:image/bmp;base64, "+cards[i].image+"' onmousedown='startMoving(event, this, "+i+");' />";
|
||||
}
|
||||
|
||||
function update_pos(i, x, y){
|
||||
if (state != 3){
|
||||
return;
|
||||
}
|
||||
|
||||
var panelHeight = 1272;
|
||||
var panelWidth = 1260;
|
||||
|
||||
cards[i].x = panelHeight - ((y / window.screen.height) * panelHeight);
|
||||
cards[i].y = panelWidth - ((x / window.screen.width) * panelWidth);
|
||||
cards[i].rotation = 0;
|
||||
|
||||
|
||||
var list = [];
|
||||
for (var j = 0; j < cards.length; j++){
|
||||
var c = cards[j];
|
||||
if (c.x && c.y){
|
||||
list.push({
|
||||
card_id: c.card_id,
|
||||
x: c.x,
|
||||
y: c.y,
|
||||
rotation: c.rotation
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
send({
|
||||
version: VERSION,
|
||||
command: "set_field",
|
||||
cards: list
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
var mousePosition;
|
||||
var offset = [-75,-75];
|
||||
var div;
|
||||
var current_card = -1;
|
||||
var isDown = false;
|
||||
|
||||
function startMoving(e, el, card){
|
||||
div = el;
|
||||
isDown = true;
|
||||
current_card = card;
|
||||
offset = [
|
||||
div.offsetLeft - e.clientX,
|
||||
div.offsetTop - e.clientY
|
||||
];
|
||||
}
|
||||
|
||||
document.addEventListener('mouseup', function() {
|
||||
isDown = false;
|
||||
current_card = -1;
|
||||
}, true);
|
||||
|
||||
document.addEventListener('mousemove', function(event) {
|
||||
event.preventDefault();
|
||||
if (isDown) {
|
||||
mousePosition = {
|
||||
|
||||
x : event.clientX,
|
||||
y : event.clientY
|
||||
|
||||
};
|
||||
div.style.left = (mousePosition.x + offset[0]) + 'px';
|
||||
div.style.top = (mousePosition.y + offset[1]) + 'px';
|
||||
update_pos(current_card, event.clientX, event.clientY);
|
||||
}
|
||||
}, true);
|
||||
</script>
|
||||
<body onload="connect();">
|
||||
<div id="playfield" class="playfield">
|
||||
|
||||
</div>
|
||||
<div class="card_menu">
|
||||
<div id="status">Please wait...</div>
|
||||
<div id="cards">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
13
dist/sekito/config_hook.json
vendored
Normal file
13
dist/sekito/config_hook.json
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"common": {
|
||||
"language": "english"
|
||||
},
|
||||
"network": {
|
||||
"property": {
|
||||
"dhcp": true
|
||||
}
|
||||
},
|
||||
"allnet_auth": {
|
||||
"type": "1.0"
|
||||
}
|
||||
}
|
15
dist/sekito/launch_satellite.bat
vendored
Normal file
15
dist/sekito/launch_satellite.bat
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
@echo off
|
||||
set SEGATOOLS_CONFIG_PATH=.\segatools_satellite.ini
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
start "AM Daemon" /min inject_x64 -d -k sekitohook_x64.dll amdaemon.exe -c config_new.json -c config_video_single.json -c config_video_multi.json -c config_input_sate.json -c config_input_terminal.json -c config_input_terminal_exp.json -c config_hook.json
|
||||
|
||||
inject_x86 -d -k sekitohook_x86.dll appSate.exe
|
||||
|
||||
taskkill /f /im appSate.exe > nul 2>&1
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
echo.
|
||||
echo Game processes have terminated
|
||||
pause
|
19
dist/sekito/launch_terminal.bat
vendored
Normal file
19
dist/sekito/launch_terminal.bat
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
@echo off
|
||||
set SEGATOOLS_CONFIG_PATH=.\segatools_satellite.ini
|
||||
|
||||
pushd %~dp0
|
||||
|
||||
start "AM Daemon" /min inject_x64 -d -k sekitohook_x64.dll amdaemon.exe -c config_new.json -c config_video_single.json -c config_video_multi.json -c config_input_sate.json -c config_input_terminal.json -c config_input_terminal_exp.json -c config_hook.json
|
||||
|
||||
call server\server_start.bat
|
||||
|
||||
inject_x86 -d -k sekitohook_x86.dll appTerminal.exe
|
||||
|
||||
taskkill /f /im appTerminal.exe > nul 2>&1
|
||||
taskkill /f /im amdaemon.exe > nul 2>&1
|
||||
|
||||
call server\server_stop.bat
|
||||
|
||||
echo.
|
||||
echo Game processes have terminated
|
||||
pause
|
174
dist/sekito/segatools_satellite.ini
vendored
Normal file
174
dist/sekito/segatools_satellite.ini
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
; -----------------------------------------------------------------------------
|
||||
; 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
|
||||
|
||||
; Virtual-key code. If this button is **held** then the emulated IC card reader
|
||||
; emulates an IC card in its proximity. A variety of different IC cards can be
|
||||
; emulated; the exact choice of card that is emulated depends on the presence or
|
||||
; absence of the configured card ID files. Default is the Return key.
|
||||
scan=0x0D
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; 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]
|
||||
; Keychip serial number. Keychip serials observed in the wild follow this
|
||||
; pattern: `A\d{2}(E|X)-(01|20)[ABCDU]\d{8}`.
|
||||
id=A69E-01A88888888
|
||||
|
||||
; 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.189.0
|
||||
|
||||
; Override the game's four-character platform code (e.g. `AAV2` for Nu 2). This
|
||||
; is actually supposed to be a separate three-character `platformId` and
|
||||
; integer `modelType` setting, but they are combined here for convenience.
|
||||
; 1 = Terminal (TM)
|
||||
; 2 = Satellite (ST)
|
||||
platformId=AAV2
|
||||
|
||||
[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
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[flatPanelReader]
|
||||
; Enable the Y3 board emulation.
|
||||
enable=1
|
||||
|
||||
[y3ws]
|
||||
; Enable the Y3 websocket server.
|
||||
enable=1
|
||||
; Set the TCP port on which the Y3 websocket server runs.
|
||||
port=3594
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; LED settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[led15093]
|
||||
; Enable the 837-15093-06 board emulation.
|
||||
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=
|
||||
|
||||
[ektio]
|
||||
; To use a custom Eiketsu Taisen IO DLL enter its path here.
|
||||
; Leave empty if you want to use Segatools built-in keyboard/gamepad input.
|
||||
path=
|
||||
|
||||
[y3io]
|
||||
; To use a custom Y3 IO DLL enter its path here.
|
||||
; Leave empty if you want to use ... TBA ...
|
||||
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
|
||||
|
||||
; SW1. Default is the 4 key.
|
||||
sw1=0x34
|
||||
; SW2. Default is the 5 key.
|
||||
sw2=0x35
|
||||
|
||||
; Input API selection for IO4 input emulator.
|
||||
; For now only "keyboard" is supported.
|
||||
mode=keyboard
|
||||
|
||||
[keyboard]
|
||||
|
||||
menu=0x41
|
||||
start=0x42
|
||||
stratagem=0x43
|
||||
stratagem_lock=0x44
|
||||
hougu=0x45
|
||||
ryuuha=0x46
|
||||
|
||||
tenkey_0=0x60
|
||||
tenkey_1=0x61
|
||||
tenkey_2=0x62
|
||||
tenkey_3=0x63
|
||||
tenkey_4=0x64
|
||||
tenkey_5=0x65
|
||||
tenkey_6=0x66
|
||||
tenkey_7=0x67
|
||||
tenkey_8=0x68
|
||||
tenkey_9=0x69
|
||||
tenkey_clear=0x6E
|
||||
tenkey_enter=0x0D
|
||||
|
||||
vol_up=0x21
|
||||
vol_down=0x22
|
||||
|
||||
trackball_up=0x26
|
||||
trackball_right=0x27
|
||||
trackball_down=0x28
|
||||
trackball_left=0x25
|
||||
speed_modifier=10
|
137
dist/sekito/segatools_terminal.ini
vendored
Normal file
137
dist/sekito/segatools_terminal.ini
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
; -----------------------------------------------------------------------------
|
||||
; 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
|
||||
|
||||
; Virtual-key code. If this button is **held** then the emulated IC card reader
|
||||
; emulates an IC card in its proximity. A variety of different IC cards can be
|
||||
; emulated; the exact choice of card that is emulated depends on the presence or
|
||||
; absence of the configured card ID files. Default is the Return key.
|
||||
scan=0x0D
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; 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]
|
||||
; Keychip serial number. Keychip serials observed in the wild follow this
|
||||
; pattern: `A\d{2}(E|X)-(01|20)[ABCDU]\d{8}`.
|
||||
id=A69E-01A88888888
|
||||
|
||||
; 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.189.0
|
||||
|
||||
; Override the game's four-character platform code (e.g. `AAV2` for Nu 2). This
|
||||
; is actually supposed to be a separate three-character `platformId` and
|
||||
; integer `modelType` setting, but they are combined here for convenience.
|
||||
; 1 = Terminal (TM)
|
||||
; 2 = Satellite (ST)
|
||||
platformId=AAV1
|
||||
|
||||
[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
|
||||
|
||||
; -----------------------------------------------------------------------------
|
||||
; LED settings
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
[led15093]
|
||||
; Enable the 837-15093-06 board emulation.
|
||||
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=
|
||||
|
||||
[ektio]
|
||||
; To use a custom Eiketsu Taisen 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 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
|
||||
|
||||
; SW1. Default is the 4 key.
|
||||
sw1=0x34
|
||||
; SW2. Default is the 5 key.
|
||||
sw2=0x35
|
||||
|
||||
; Input API selection for IO4 input emulator.
|
||||
; For now only "keyboard" is supported.
|
||||
mode=keyboard
|
||||
|
||||
[keyboard]
|
||||
|
||||
cancel=0x53
|
||||
decide=0x41
|
||||
|
||||
up=0x26
|
||||
right=0x27
|
||||
down=0x28
|
||||
left=0x25
|
||||
|
||||
left_2=0x4F
|
||||
right_2=0x57
|
107
games/sekitohook/config.c
Normal file
107
games/sekitohook/config.c
Normal file
@ -0,0 +1,107 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "board/config.h"
|
||||
|
||||
#include "sekitohook/config.h"
|
||||
#include "sekitohook/sekito-dll.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
|
||||
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[0] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename);
|
||||
cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo2", 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 sekito_dll_config_load(
|
||||
struct sekito_dll_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"sekitoio",
|
||||
L"path",
|
||||
L"",
|
||||
cfg->path,
|
||||
_countof(cfg->path),
|
||||
filename);
|
||||
}
|
||||
|
||||
|
||||
void sekito_hook_config_load(
|
||||
struct sekito_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);
|
||||
io4_config_load(&cfg->io4, filename);
|
||||
dvd_config_load(&cfg->dvd, filename);
|
||||
led15093_config_load(&cfg->led15093, filename);
|
||||
y3_config_load(&cfg->y3, filename);
|
||||
printer_chc_config_load(&cfg->printer, filename);
|
||||
unity_config_load(&cfg->unity, filename);
|
||||
sekito_dll_config_load(&cfg->dll, filename);
|
||||
}
|
37
games/sekitohook/config.h
Normal file
37
games/sekitohook/config.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "board/sg-reader.h"
|
||||
#include "board/config.h"
|
||||
#include "board/led15093.h"
|
||||
|
||||
#include "sekitohook/sekito-dll.h"
|
||||
|
||||
#include "hooklib/config.h"
|
||||
#include "hooklib/dvd.h"
|
||||
#include "hooklib/printer_chc.h"
|
||||
|
||||
#include "platform/config.h"
|
||||
|
||||
#include "unityhook/config.h"
|
||||
|
||||
struct sekito_hook_config {
|
||||
struct platform_config platform;
|
||||
struct aime_config aime;
|
||||
struct io4_config io4;
|
||||
struct dvd_config dvd;
|
||||
struct led15093_config led15093;
|
||||
struct y3_config y3;
|
||||
struct sekito_dll_config dll;
|
||||
struct unity_config unity;
|
||||
struct printer_chc_config printer;
|
||||
};
|
||||
|
||||
void sekito_dll_config_load(
|
||||
struct sekito_dll_config *cfg,
|
||||
const wchar_t *filename);
|
||||
|
||||
void sekito_hook_config_load(
|
||||
struct sekito_hook_config *cfg,
|
||||
const wchar_t *filename);
|
178
games/sekitohook/dllmain.c
Normal file
178
games/sekitohook/dllmain.c
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
"Sangokushi Taisen" (sekito) hook
|
||||
|
||||
Devices
|
||||
|
||||
USB: 837-15257-01 "Type 4" I/O Board
|
||||
COM12: 837-15396 "Gen 3" Aime Reader
|
||||
|
||||
[Satellite]
|
||||
|
||||
USB: Printer
|
||||
COM1: 837-15093-06 LED Controller Board
|
||||
COM11: Printer Camera
|
||||
|
||||
[Terminal]
|
||||
|
||||
COM1: 837-15396 "Gen 3" Aime Reader
|
||||
COM3: 837-15093-06 LED Controller Board
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sekito-dll.h"
|
||||
#include "board/sg-reader.h"
|
||||
#include "board/led15093.h"
|
||||
|
||||
#include "hook/process.h"
|
||||
#include "hook/iohook.h"
|
||||
|
||||
#include "hooklib/serial.h"
|
||||
#include "hooklib/spike.h"
|
||||
|
||||
#include "sekitohook/config.h"
|
||||
#include "sekitohook/io4.h"
|
||||
#include "hooklib/printer_cx.h"
|
||||
|
||||
#include "platform/platform.h"
|
||||
|
||||
#include "unityhook/hook.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
#include "util/env.h"
|
||||
#include "hooklib/y3-dll.h"
|
||||
#include "hooklib/y3.h"
|
||||
|
||||
static HMODULE sekito_hook_mod;
|
||||
static process_entry_t sekito_startup;
|
||||
static struct sekito_hook_config sekito_hook_cfg;
|
||||
|
||||
static void unity_hook_callback(HMODULE hmodule, const wchar_t* p) {
|
||||
netenv_hook_apply_hooks(hmodule);
|
||||
}
|
||||
|
||||
static DWORD CALLBACK sekito_pre_startup(void)
|
||||
{
|
||||
HRESULT hr;
|
||||
bool is_terminal;
|
||||
|
||||
dprintf("--- Begin sekito_pre_startup ---\n");
|
||||
|
||||
/* Load config */
|
||||
|
||||
sekito_hook_config_load(&sekito_hook_cfg, get_config_path());
|
||||
|
||||
/* Hook Win32 APIs */
|
||||
|
||||
dvd_hook_init(&sekito_hook_cfg.dvd, sekito_hook_mod);
|
||||
serial_hook_init();
|
||||
|
||||
/* Hook external DLL APIs */
|
||||
|
||||
hr = y3_hook_init(&sekito_hook_cfg.y3, sekito_hook_mod, get_config_path());
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
printer_chc_hook_init(&sekito_hook_cfg.printer, 0, sekito_hook_mod);
|
||||
|
||||
/* Initialize emulation hooks */
|
||||
|
||||
hr = platform_hook_init(
|
||||
&sekito_hook_cfg.platform,
|
||||
"SDDD",
|
||||
"AAV2",
|
||||
sekito_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Initialize Terminal/Satellite hooks */
|
||||
if (strncmp(sekito_hook_cfg.platform.nusec.platform_id, "AAV1", 4) == 0) {
|
||||
// Terminal
|
||||
is_terminal = true;
|
||||
} else if (strncmp(sekito_hook_cfg.platform.nusec.platform_id, "AAV2", 4) == 0) {
|
||||
// Satellite
|
||||
is_terminal = false;
|
||||
} else {
|
||||
// Unknown
|
||||
dprintf("Unknown platform ID: %s\n", sekito_hook_cfg.platform.nusec.platform_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// LED: terminal uses COM 3 and satellite use COM 2
|
||||
unsigned int led_port_no[2] = {is_terminal ? 3 : 2, 0};
|
||||
|
||||
hr = sekito_dll_init(&sekito_hook_cfg.dll, sekito_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = sekito_io4_hook_init(&sekito_hook_cfg.io4, is_terminal);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = led15093_hook_init(&sekito_hook_cfg.led15093,
|
||||
sekito_dll.led_init, sekito_dll.led_set_leds, led_port_no);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hr = sg_reader_hook_init(&sekito_hook_cfg.aime, 12, 3,
|
||||
sekito_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (is_terminal) {
|
||||
|
||||
hr = sg_reader_hook_init(&sekito_hook_cfg.aime, 1, 3,
|
||||
sekito_hook_mod);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Initialize debug helpers */
|
||||
|
||||
spike_hook_init(get_config_path());
|
||||
|
||||
dprintf("--- End sekito_pre_startup ---\n");
|
||||
|
||||
/* Jump to EXE start address */
|
||||
|
||||
return sekito_startup();
|
||||
|
||||
fail:
|
||||
ExitProcess(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
BOOL WINAPI DllMain(HMODULE mod, DWORD cause, void *ctx)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
if (cause != DLL_PROCESS_ATTACH) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sekito_hook_mod = mod;
|
||||
|
||||
hr = process_hijack_startup(sekito_pre_startup, &sekito_startup);
|
||||
|
||||
if (!SUCCEEDED(hr)) {
|
||||
dprintf("Failed to hijack process startup: %x\n", (int) hr);
|
||||
}
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
212
games/sekitohook/io4.c
Normal file
212
games/sekitohook/io4.c
Normal file
@ -0,0 +1,212 @@
|
||||
#include "io4.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
||||
#include "sekitohook/sekito-dll.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static HRESULT sekito_io4_poll(void *ctx, struct io4_state *state);
|
||||
static uint16_t coins;
|
||||
|
||||
static const struct io4_ops sekito_io4_ops = {
|
||||
.poll = sekito_io4_poll,
|
||||
};
|
||||
|
||||
static bool io_is_terminal;
|
||||
|
||||
HRESULT sekito_io4_hook_init(const struct io4_config *cfg, bool is_terminal)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
assert(sekito_dll.init != NULL);
|
||||
|
||||
hr = io4_hook_init(cfg, &sekito_io4_ops, NULL);
|
||||
|
||||
io_is_terminal = is_terminal;
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
return sekito_dll.init();
|
||||
}
|
||||
|
||||
static HRESULT sekito_io4_poll(void *ctx, struct io4_state *state)
|
||||
{
|
||||
uint8_t opbtn;
|
||||
uint16_t x, y;
|
||||
uint32_t gamebtn;
|
||||
HRESULT hr;
|
||||
|
||||
assert(sekito_dll.poll != NULL);
|
||||
assert(sekito_dll.get_opbtns != NULL);
|
||||
assert(sekito_dll.get_gamebtns != NULL);
|
||||
assert(sekito_dll.get_trackball_position != NULL);
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
hr = sekito_dll.poll();
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
opbtn = 0;
|
||||
gamebtn = 0;
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
||||
sekito_dll.get_opbtns(&opbtn);
|
||||
sekito_dll.get_gamebtns(&gamebtn);
|
||||
sekito_dll.get_trackball_position(&x, &y);
|
||||
|
||||
if (opbtn & SEKITO_IO_OPBTN_TEST) {
|
||||
state->buttons[0] |= IO4_BUTTON_TEST;
|
||||
}
|
||||
|
||||
if (opbtn & SEKITO_IO_OPBTN_SERVICE) {
|
||||
state->buttons[0] |= IO4_BUTTON_SERVICE;
|
||||
}
|
||||
|
||||
if (opbtn & SEKITO_IO_OPBTN_SW1) {
|
||||
state->buttons[0] |= 1 << 10;
|
||||
}
|
||||
|
||||
if (opbtn & SEKITO_IO_OPBTN_SW2) {
|
||||
state->buttons[0] |= 1 << 11;
|
||||
}
|
||||
|
||||
if (opbtn & SEKITO_IO_OPBTN_COIN) {
|
||||
coins++;
|
||||
}
|
||||
state->chutes[0] = coins << 8;
|
||||
|
||||
if (!io_is_terminal) {
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_HOUGU) {
|
||||
state->buttons[1] |= 1 << 6;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_MENU) {
|
||||
state->buttons[1] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_START) {
|
||||
state->buttons[0] |= 1 << 15;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_STRATAGEM) {
|
||||
state->buttons[1] |= 1 << 7;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_STRATAGEM_LOCK) {
|
||||
state->buttons[1] |= 1 << 5;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_0) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C2;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R4;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_1) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C1;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R1;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_2) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C2;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R1;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_3) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C3;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R1;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_4) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C1;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R2;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_5) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C2;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R2;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_6) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C3;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R2;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_7) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C1;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R3;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_8) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C2;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R3;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_9) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C3;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R3;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_CLEAR) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C1;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R4;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_NUMPAD_ENTER) {
|
||||
state->buttons[0] |= SEKITO_NUMPAD_C3;
|
||||
state->buttons[0] |= SEKITO_NUMPAD_R4;
|
||||
}
|
||||
|
||||
if (io_is_terminal) {
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_CANCEL) {
|
||||
state->buttons[1] |= 1 << 0;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_DECIDE) {
|
||||
state->buttons[1] |= 1 << 1;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_LEFT) {
|
||||
state->buttons[0] |= 1 << 3;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_UP) {
|
||||
state->buttons[0] |= 1 << 5;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_RIGHT) {
|
||||
state->buttons[0] |= 1 << 2;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_DOWN) {
|
||||
state->buttons[0] |= 1 << 4;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_LEFT_2) {
|
||||
state->buttons[1] |= 1 << 3;
|
||||
}
|
||||
|
||||
if (gamebtn & SEKITO_IO_GAMEBTN_TERMINAL_RIGHT_2) {
|
||||
state->buttons[1] |= 1 << 2;
|
||||
}
|
||||
}
|
||||
|
||||
state->spinners[2] = x;
|
||||
state->spinners[3] = y;
|
||||
|
||||
return S_OK;
|
||||
}
|
17
games/sekitohook/io4.h
Normal file
17
games/sekitohook/io4.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "board/io4.h"
|
||||
|
||||
enum {
|
||||
SEKITO_NUMPAD_R1 = 1 << 9,
|
||||
SEKITO_NUMPAD_R2 = 1 << 8,
|
||||
SEKITO_NUMPAD_R3 = 1 << 7,
|
||||
SEKITO_NUMPAD_R4 = 1 << 6,
|
||||
SEKITO_NUMPAD_C1 = 1 << 5,
|
||||
SEKITO_NUMPAD_C2 = 1 << 4,
|
||||
SEKITO_NUMPAD_C3 = 1 << 3
|
||||
};
|
||||
|
||||
HRESULT sekito_io4_hook_init(const struct io4_config *cfg, bool is_terminal);
|
31
games/sekitohook/meson.build
Normal file
31
games/sekitohook/meson.build
Normal file
@ -0,0 +1,31 @@
|
||||
shared_library(
|
||||
'sekitohook',
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
vs_module_defs : 'sekitohook.def',
|
||||
dependencies : [
|
||||
capnhook.get_variable('hook_dep'),
|
||||
capnhook.get_variable('hooklib_dep')
|
||||
],
|
||||
link_with : [
|
||||
aimeio_lib,
|
||||
board_lib,
|
||||
sekitoio_lib,
|
||||
hooklib_lib,
|
||||
jvs_lib,
|
||||
platform_lib,
|
||||
unityhook_lib,
|
||||
util_lib,
|
||||
y3io_lib,
|
||||
],
|
||||
sources : [
|
||||
'config.c',
|
||||
'config.h',
|
||||
'dllmain.c',
|
||||
'io4.c',
|
||||
'io4.h',
|
||||
'sekito-dll.c',
|
||||
'sekito-dll.h',
|
||||
],
|
||||
)
|
118
games/sekitohook/sekito-dll.c
Normal file
118
games/sekitohook/sekito-dll.c
Normal file
@ -0,0 +1,118 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sekitohook/sekito-dll.h"
|
||||
|
||||
#include "util/dll-bind.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
const struct dll_bind_sym sekito_dll_syms[] = {
|
||||
{
|
||||
.sym = "sekito_io_init",
|
||||
.off = offsetof(struct sekito_dll, init),
|
||||
}, {
|
||||
.sym = "sekito_io_poll",
|
||||
.off = offsetof(struct sekito_dll, poll),
|
||||
}, {
|
||||
.sym = "sekito_io_get_opbtns",
|
||||
.off = offsetof(struct sekito_dll, get_opbtns),
|
||||
}, {
|
||||
.sym = "sekito_io_get_gamebtns",
|
||||
.off = offsetof(struct sekito_dll, get_gamebtns),
|
||||
}, {
|
||||
.sym = "sekito_io_get_trackball_position",
|
||||
.off = offsetof(struct sekito_dll, get_trackball_position),
|
||||
}, {
|
||||
.sym = "sekito_io_led_init",
|
||||
.off = offsetof(struct sekito_dll, led_init),
|
||||
}, {
|
||||
.sym = "sekito_io_led_set_colors",
|
||||
.off = offsetof(struct sekito_dll, led_set_leds),
|
||||
}
|
||||
};
|
||||
|
||||
struct sekito_dll sekito_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 sekito_dll_init(const struct sekito_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("Sekito IO: Failed to load IO DLL: %lx: %S\n",
|
||||
hr,
|
||||
cfg->path);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
dprintf("Sekito IO: Using custom IO DLL: %S\n", cfg->path);
|
||||
src = owned;
|
||||
} else {
|
||||
owned = NULL;
|
||||
src = self;
|
||||
}
|
||||
|
||||
get_api_version = (void *) GetProcAddress(src, "sekito_io_get_api_version");
|
||||
|
||||
if (get_api_version != NULL) {
|
||||
sekito_dll.api_version = get_api_version();
|
||||
} else {
|
||||
sekito_dll.api_version = 0x0100;
|
||||
dprintf("Custom IO DLL does not expose sekito_io_get_api_version, "
|
||||
"assuming API version 1.0.\n"
|
||||
"Please ask the developer to update their DLL.\n");
|
||||
}
|
||||
|
||||
if (sekito_dll.api_version >= 0x0200) {
|
||||
hr = E_NOTIMPL;
|
||||
dprintf("Sekito IO: Custom IO DLL implements an unsupported "
|
||||
"API version (%#04x). Please update Segatools.\n",
|
||||
sekito_dll.api_version);
|
||||
|
||||
goto end;
|
||||
}
|
||||
|
||||
sym = sekito_dll_syms;
|
||||
hr = dll_bind(&sekito_dll, src, &sym, _countof(sekito_dll_syms));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if (src != self) {
|
||||
dprintf("Sekito 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;
|
||||
}
|
24
games/sekitohook/sekito-dll.h
Normal file
24
games/sekitohook/sekito-dll.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "sekitoio/sekitoio.h"
|
||||
|
||||
struct sekito_dll {
|
||||
uint16_t api_version;
|
||||
HRESULT (*init)(void);
|
||||
HRESULT (*poll)(void);
|
||||
void (*get_opbtns)(uint8_t *opbtn);
|
||||
void (*get_gamebtns)(uint32_t *gamebtn);
|
||||
void (*get_trackball_position)(uint16_t *x, uint16_t *y);
|
||||
HRESULT (*led_init)(void);
|
||||
void (*led_set_leds)(uint8_t board, uint8_t *rgb);
|
||||
};
|
||||
|
||||
struct sekito_dll_config {
|
||||
wchar_t path[MAX_PATH];
|
||||
};
|
||||
|
||||
extern struct sekito_dll sekito_dll;
|
||||
|
||||
HRESULT sekito_dll_init(const struct sekito_dll_config *cfg, HINSTANCE self);
|
61
games/sekitohook/sekitohook.def
Normal file
61
games/sekitohook/sekitohook.def
Normal file
@ -0,0 +1,61 @@
|
||||
LIBRARY taisenhook
|
||||
|
||||
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
|
||||
sekito_io_get_api_version
|
||||
sekito_io_get_gamebtns
|
||||
sekito_io_get_opbtns
|
||||
sekito_io_get_trackball_position
|
||||
sekito_io_init
|
||||
sekito_io_poll
|
||||
sekito_io_led_init
|
||||
sekito_io_led_set_colors
|
||||
y3_io_get_api_version
|
||||
y3_io_init
|
||||
y3_io_close
|
||||
y3_io_get_cards
|
||||
API_DLLVersion @1
|
||||
API_GetLastError @2
|
||||
API_GetErrorMessage @3
|
||||
API_Connect @4
|
||||
API_Close @5
|
||||
API_Start @6
|
||||
API_Stop @7
|
||||
API_GetFirmVersion @8
|
||||
API_GetFirmName @9
|
||||
API_GetTargetCode @10
|
||||
API_GetStatus @11
|
||||
API_GetCounter @12
|
||||
API_ClearError @13
|
||||
API_Reset @14
|
||||
API_GetCardInfo @15
|
||||
API_GetCardInfoCharSize @16
|
||||
API_SetDevice @17
|
||||
API_SetCommand @18
|
||||
API_FirmwareUpdate @19
|
||||
API_Calibration @20
|
||||
API_GetCalibrationResult @21
|
||||
API_GetProcTime @22
|
||||
API_GetMemStatus @23
|
||||
API_GetMemCounter @24
|
||||
API_SetSysControl @25
|
||||
API_GetSysControl @26
|
||||
API_SetParameter @27
|
||||
API_GetParameter @28
|
||||
API_TestReset @29
|
||||
API_DebugReset @30
|
||||
API_GetBoardType @31
|
||||
API_GetCardDataSize @32
|
||||
API_GetFirmDate @33
|
||||
API_SystemCommand @34
|
||||
API_CalcCheckSum @35
|
||||
API_GetCheckSumResult @36
|
||||
API_BlockRead @37
|
||||
API_GetBlockReadResult @38
|
||||
API_BlockWrite @39
|
||||
API_GetDebugParam @40
|
10
games/sekitoio/backend.h
Normal file
10
games/sekitoio/backend.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sekitoio/sekitoio.h"
|
||||
|
||||
struct sekito_io_backend {
|
||||
void (*get_gamebtns)(uint32_t *gamebtn);
|
||||
void (*get_trackball)(uint16_t *x, uint16_t *y);
|
||||
};
|
77
games/sekitoio/config.c
Normal file
77
games/sekitoio/config.c
Normal file
@ -0,0 +1,77 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sekitoio/config.h"
|
||||
|
||||
#include <xinput.h>
|
||||
|
||||
|
||||
void sekito_kb_config_load(
|
||||
struct sekito_kb_config *cfg,
|
||||
const wchar_t *filename) {
|
||||
|
||||
cfg->vk_menu = GetPrivateProfileIntW(L"keyboard", L"menu", 'A', filename);
|
||||
cfg->vk_start = GetPrivateProfileIntW(L"keyboard", L"start", 'S', filename);
|
||||
cfg->vk_stratagem = GetPrivateProfileIntW(L"keyboard", L"stratagem", 'D', filename);
|
||||
cfg->vk_stratagem_lock = GetPrivateProfileIntW(L"keyboard", L"stratagem_lock", 'F', filename);
|
||||
cfg->vk_hougu = GetPrivateProfileIntW(L"keyboard", L"hougu", 'G', filename);
|
||||
cfg->vk_ryuuha = GetPrivateProfileIntW(L"keyboard", L"ryuuha", 'H', filename);
|
||||
|
||||
cfg->vk_tenkey_0 = GetPrivateProfileIntW(L"keyboard", L"tenkey_0", VK_NUMPAD0, filename);
|
||||
cfg->vk_tenkey_1 = GetPrivateProfileIntW(L"keyboard", L"tenkey_1", VK_NUMPAD1, filename);
|
||||
cfg->vk_tenkey_2 = GetPrivateProfileIntW(L"keyboard", L"tenkey_2", VK_NUMPAD2, filename);
|
||||
cfg->vk_tenkey_3 = GetPrivateProfileIntW(L"keyboard", L"tenkey_3", VK_NUMPAD3, filename);
|
||||
cfg->vk_tenkey_4 = GetPrivateProfileIntW(L"keyboard", L"tenkey_4", VK_NUMPAD4, filename);
|
||||
cfg->vk_tenkey_5 = GetPrivateProfileIntW(L"keyboard", L"tenkey_5", VK_NUMPAD5, filename);
|
||||
cfg->vk_tenkey_6 = GetPrivateProfileIntW(L"keyboard", L"tenkey_6", VK_NUMPAD6, filename);
|
||||
cfg->vk_tenkey_7 = GetPrivateProfileIntW(L"keyboard", L"tenkey_7", VK_NUMPAD7, filename);
|
||||
cfg->vk_tenkey_8 = GetPrivateProfileIntW(L"keyboard", L"tenkey_8", VK_NUMPAD8, filename);
|
||||
cfg->vk_tenkey_9 = GetPrivateProfileIntW(L"keyboard", L"tenkey_9", VK_NUMPAD9, filename);
|
||||
cfg->vk_tenkey_clear = GetPrivateProfileIntW(L"keyboard", L"tenkey_clear", VK_DECIMAL, filename);
|
||||
cfg->vk_tenkey_enter = GetPrivateProfileIntW(L"keyboard", L"tenkey_enter", VK_RETURN, filename);
|
||||
|
||||
cfg->vk_vol_down = GetPrivateProfileIntW(L"keyboard", L"vol_down", VK_NEXT, filename);
|
||||
cfg->vk_vol_up = GetPrivateProfileIntW(L"keyboard", L"vol_up", VK_PRIOR, filename);
|
||||
|
||||
cfg->vk_terminal_decide = GetPrivateProfileIntW(L"keyboard", L"decide", 'A', filename);
|
||||
cfg->vk_terminal_cancel = GetPrivateProfileIntW(L"keyboard", L"cancel", 'S', filename);
|
||||
cfg->vk_terminal_up = GetPrivateProfileIntW(L"keyboard", L"up", VK_UP, filename);
|
||||
cfg->vk_terminal_right = GetPrivateProfileIntW(L"keyboard", L"right", VK_RIGHT, filename);
|
||||
cfg->vk_terminal_down = GetPrivateProfileIntW(L"keyboard", L"down", VK_DOWN, filename);
|
||||
cfg->vk_terminal_left = GetPrivateProfileIntW(L"keyboard", L"left", VK_LEFT, filename);
|
||||
cfg->vk_terminal_left_2 = GetPrivateProfileIntW(L"keyboard", L"left2", 'Q', filename);
|
||||
cfg->vk_terminal_right_2 = GetPrivateProfileIntW(L"keyboard", L"right2", 'W', filename);
|
||||
|
||||
cfg->x_down = GetPrivateProfileIntW(L"keyboard", L"trackball_left", VK_LEFT, filename);
|
||||
cfg->x_up = GetPrivateProfileIntW(L"keyboard", L"trackball_right", VK_RIGHT, filename);
|
||||
cfg->y_down = GetPrivateProfileIntW(L"keyboard", L"trackball_up", VK_UP, filename);
|
||||
cfg->y_up = GetPrivateProfileIntW(L"keyboard", L"trackball_down", VK_DOWN, filename);
|
||||
cfg->speed = GetPrivateProfileIntW(L"keyboard", L"speed_modifier", 1, filename);
|
||||
}
|
||||
|
||||
void sekito_io_config_load(
|
||||
struct sekito_io_config *cfg,
|
||||
const wchar_t *filename)
|
||||
{
|
||||
assert(cfg != NULL);
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->vk_test = GetPrivateProfileIntW(L"io4", L"test", '1', filename);
|
||||
cfg->vk_service = GetPrivateProfileIntW(L"io4", L"service", '2', filename);
|
||||
cfg->vk_coin = GetPrivateProfileIntW(L"io4", L"coin", '3', filename);
|
||||
cfg->vk_sw1 = GetPrivateProfileIntW(L"io4", L"sw1", '4', filename);
|
||||
cfg->vk_sw2 = GetPrivateProfileIntW(L"io4", L"sw2", '5', filename);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"io4",
|
||||
L"mode",
|
||||
L"keyboard",
|
||||
cfg->mode,
|
||||
_countof(cfg->mode),
|
||||
filename);
|
||||
|
||||
sekito_kb_config_load(&cfg->kb, filename);
|
||||
}
|
62
games/sekitoio/config.h
Normal file
62
games/sekitoio/config.h
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct sekito_kb_config {
|
||||
uint8_t vk_menu;
|
||||
uint8_t vk_start;
|
||||
uint8_t vk_stratagem;
|
||||
uint8_t vk_stratagem_lock;
|
||||
uint8_t vk_hougu;
|
||||
uint8_t vk_ryuuha;
|
||||
|
||||
uint8_t vk_tenkey_0;
|
||||
uint8_t vk_tenkey_1;
|
||||
uint8_t vk_tenkey_2;
|
||||
uint8_t vk_tenkey_3;
|
||||
uint8_t vk_tenkey_4;
|
||||
uint8_t vk_tenkey_5;
|
||||
uint8_t vk_tenkey_6;
|
||||
uint8_t vk_tenkey_7;
|
||||
uint8_t vk_tenkey_8;
|
||||
uint8_t vk_tenkey_9;
|
||||
uint8_t vk_tenkey_clear;
|
||||
uint8_t vk_tenkey_enter;
|
||||
|
||||
uint8_t vk_vol_down;
|
||||
uint8_t vk_vol_up;
|
||||
|
||||
uint8_t vk_terminal_up;
|
||||
uint8_t vk_terminal_right;
|
||||
uint8_t vk_terminal_down;
|
||||
uint8_t vk_terminal_left;
|
||||
uint8_t vk_terminal_left_2;
|
||||
uint8_t vk_terminal_right_2;
|
||||
uint8_t vk_terminal_cancel;
|
||||
uint8_t vk_terminal_decide;
|
||||
|
||||
uint8_t x_down;
|
||||
uint8_t x_up;
|
||||
uint8_t y_down;
|
||||
uint8_t y_up;
|
||||
uint8_t speed;
|
||||
};
|
||||
|
||||
struct sekito_io_config {
|
||||
uint8_t vk_test;
|
||||
uint8_t vk_service;
|
||||
uint8_t vk_coin;
|
||||
uint8_t vk_sw1;
|
||||
uint8_t vk_sw2;
|
||||
|
||||
wchar_t mode[12];
|
||||
struct sekito_kb_config kb;
|
||||
};
|
||||
|
||||
void sekito_kb_config_load(struct sekito_kb_config *cfg, const wchar_t *filename);
|
||||
void sekito_io_config_load(
|
||||
struct sekito_io_config *cfg,
|
||||
const wchar_t *filename);
|
164
games/sekitoio/keyboard.c
Normal file
164
games/sekitoio/keyboard.c
Normal file
@ -0,0 +1,164 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "sekitoio/backend.h"
|
||||
#include "sekitoio/config.h"
|
||||
#include "sekitoio/sekitoio.h"
|
||||
#include "sekitoio/keyboard.h"
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static void sekito_kb_get_gamebtns(uint32_t* gamebtn_out);
|
||||
static void sekito_kb_get_trackball(uint16_t* x, uint16_t* y);
|
||||
|
||||
static const struct sekito_io_backend sekito_kb_backend = {
|
||||
.get_gamebtns = sekito_kb_get_gamebtns,
|
||||
.get_trackball = sekito_kb_get_trackball
|
||||
};
|
||||
|
||||
static uint16_t current_x;
|
||||
static uint16_t current_y;
|
||||
|
||||
static struct sekito_kb_config config;
|
||||
|
||||
HRESULT sekito_kb_init(const struct sekito_kb_config* cfg, const struct sekito_io_backend** backend) {
|
||||
assert(cfg != NULL);
|
||||
assert(backend != NULL);
|
||||
|
||||
dprintf("Keyboard: Using keyboard input\n");
|
||||
*backend = &sekito_kb_backend;
|
||||
config = *cfg;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void sekito_kb_get_gamebtns(uint32_t* gamebtn_out) {
|
||||
assert(gamebtn_out != NULL);
|
||||
|
||||
uint32_t gamebtn = 0;
|
||||
|
||||
if (GetAsyncKeyState(config.vk_hougu) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_HOUGU;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_menu) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_MENU;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_start) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_START;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_stratagem) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_STRATAGEM;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_stratagem_lock) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_STRATAGEM_LOCK;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_0) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_0;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_1) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_1;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_2) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_2;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_3) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_3;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_4) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_4;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_5) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_5;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_6) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_6;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_7) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_7;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_8) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_8;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_9) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_9;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_clear) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_CLEAR;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_tenkey_enter) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_NUMPAD_ENTER;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_cancel) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_CANCEL;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_decide) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_DECIDE;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_up) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_UP;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_right) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_RIGHT;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_down) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_DOWN;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_left) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_LEFT;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_left_2) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_LEFT_2;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(config.vk_terminal_right_2) & 0x8000) {
|
||||
gamebtn |= SEKITO_IO_GAMEBTN_TERMINAL_RIGHT_2;
|
||||
}
|
||||
|
||||
*gamebtn_out = gamebtn;
|
||||
}
|
||||
|
||||
static void sekito_kb_get_trackball(uint16_t* x, uint16_t* y) {
|
||||
assert(x != NULL);
|
||||
assert(y != NULL);
|
||||
|
||||
if (GetAsyncKeyState(config.x_down) & 0x8000) {
|
||||
current_x -= config.speed;
|
||||
} else if (GetAsyncKeyState(config.x_up) & 0x8000) {
|
||||
current_x += config.speed;
|
||||
}
|
||||
if (GetAsyncKeyState(config.y_down) & 0x8000) {
|
||||
current_y += config.speed;
|
||||
} else if (GetAsyncKeyState(config.y_up) & 0x8000) {
|
||||
current_y -= config.speed;
|
||||
}
|
||||
|
||||
*x = current_x;
|
||||
*y = current_y;
|
||||
}
|
8
games/sekitoio/keyboard.h
Normal file
8
games/sekitoio/keyboard.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "sekitoio/backend.h"
|
||||
#include "sekitoio/config.h"
|
||||
|
||||
HRESULT sekito_kb_init(const struct sekito_kb_config *cfg, const struct sekito_io_backend **backend);
|
18
games/sekitoio/meson.build
Normal file
18
games/sekitoio/meson.build
Normal file
@ -0,0 +1,18 @@
|
||||
sekitoio_lib = static_library(
|
||||
'sekitoio',
|
||||
name_prefix : '',
|
||||
include_directories : inc,
|
||||
implicit_include_directories : false,
|
||||
dependencies : [
|
||||
xinput_lib,
|
||||
],
|
||||
sources : [
|
||||
'config.c',
|
||||
'config.h',
|
||||
'backend.h',
|
||||
'keyboard.c',
|
||||
'keyboard.h',
|
||||
'sekitoio.c',
|
||||
'sekitoio.h',
|
||||
],
|
||||
)
|
108
games/sekitoio/sekitoio.c
Normal file
108
games/sekitoio/sekitoio.c
Normal file
@ -0,0 +1,108 @@
|
||||
#include <windows.h>
|
||||
#include <xinput.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sekitoio/sekitoio.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "sekitoio/config.h"
|
||||
#include "util/dprintf.h"
|
||||
#include "util/env.h"
|
||||
#include "util/str.h"
|
||||
|
||||
static uint8_t sekito_opbtn;
|
||||
static uint32_t sekito_gamebtn;
|
||||
static uint8_t sekito_stick_x;
|
||||
static uint8_t sekito_stick_y;
|
||||
static struct sekito_io_config sekito_io_cfg;
|
||||
static const struct sekito_io_backend* sekito_io_backend;
|
||||
static bool sekito_io_coin;
|
||||
|
||||
uint16_t sekito_io_get_api_version(void) {
|
||||
return 0x0100;
|
||||
}
|
||||
|
||||
HRESULT sekito_io_init(void) {
|
||||
sekito_io_config_load(&sekito_io_cfg, get_config_path());
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
if (wstr_ieq(sekito_io_cfg.mode, L"keyboard")) {
|
||||
hr = sekito_kb_init(&sekito_io_cfg.kb, &sekito_io_backend);
|
||||
} else {
|
||||
hr = E_INVALIDARG;
|
||||
dprintf("Sekito IO: Invalid IO mode \"%S\", use keyboard\n",
|
||||
sekito_io_cfg.mode);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT sekito_io_poll(void) {
|
||||
assert(sekito_io_backend != NULL);
|
||||
|
||||
sekito_opbtn = 0;
|
||||
sekito_gamebtn = 0;
|
||||
sekito_stick_x = 0;
|
||||
sekito_stick_y = 0;
|
||||
|
||||
if (GetAsyncKeyState(sekito_io_cfg.vk_test) & 0x8000) {
|
||||
sekito_opbtn |= SEKITO_IO_OPBTN_TEST;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(sekito_io_cfg.vk_service) & 0x8000) {
|
||||
sekito_opbtn |= SEKITO_IO_OPBTN_SERVICE;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(sekito_io_cfg.vk_sw1) & 0x8000) {
|
||||
sekito_opbtn |= SEKITO_IO_OPBTN_SW1;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(sekito_io_cfg.vk_sw2) & 0x8000) {
|
||||
sekito_opbtn |= SEKITO_IO_OPBTN_SW2;
|
||||
}
|
||||
|
||||
if (GetAsyncKeyState(sekito_io_cfg.vk_coin) & 0x8000) {
|
||||
if (!sekito_io_coin) {
|
||||
sekito_io_coin = true;
|
||||
sekito_opbtn |= SEKITO_IO_OPBTN_COIN;
|
||||
}
|
||||
} else {
|
||||
sekito_io_coin = false;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void sekito_io_get_opbtns(uint8_t* opbtn) {
|
||||
if (opbtn != NULL) {
|
||||
*opbtn = sekito_opbtn;
|
||||
}
|
||||
}
|
||||
|
||||
void sekito_io_get_gamebtns(uint32_t* btn) {
|
||||
assert(sekito_io_backend != NULL);
|
||||
assert(btn != NULL);
|
||||
|
||||
sekito_io_backend->get_gamebtns(btn);
|
||||
}
|
||||
|
||||
void sekito_io_get_trackball_position(uint16_t* stick_x, uint16_t* stick_y) {
|
||||
assert(sekito_io_backend != NULL);
|
||||
assert(stick_x != NULL);
|
||||
assert(stick_y != NULL);
|
||||
|
||||
sekito_io_backend->get_trackball(stick_x, stick_y);
|
||||
}
|
||||
|
||||
HRESULT sekito_io_led_init(void) {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void sekito_io_led_set_colors(uint8_t board, uint8_t* rgb) {
|
||||
return;
|
||||
}
|
103
games/sekitoio/sekitoio.h
Normal file
103
games/sekitoio/sekitoio.h
Normal file
@ -0,0 +1,103 @@
|
||||
#pragma once
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum {
|
||||
SEKITO_IO_OPBTN_TEST = 0x01,
|
||||
SEKITO_IO_OPBTN_SERVICE = 0x02,
|
||||
SEKITO_IO_OPBTN_COIN = 0x04,
|
||||
SEKITO_IO_OPBTN_SW1 = 0x08,
|
||||
SEKITO_IO_OPBTN_SW2 = 0x10,
|
||||
};
|
||||
|
||||
enum {
|
||||
SEKITO_IO_GAMEBTN_MENU = 0x01,
|
||||
SEKITO_IO_GAMEBTN_START = 0x02,
|
||||
SEKITO_IO_GAMEBTN_STRATAGEM = 0x04,
|
||||
SEKITO_IO_GAMEBTN_STRATAGEM_LOCK = 0x08,
|
||||
SEKITO_IO_GAMEBTN_HOUGU = 0x10,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_0 = 0x100,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_1 = 0x200,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_2 = 0x400,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_3 = 0x800,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_4 = 0x1000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_5 = 0x2000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_6 = 0x4000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_7 = 0x8000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_8 = 0x10000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_9 = 0x20000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_CLEAR = 0x40000,
|
||||
SEKITO_IO_GAMEBTN_NUMPAD_ENTER = 0x80000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_LEFT = 0x400000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_UP = 0x800000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_RIGHT = 0x1000000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_DOWN = 0x2000000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_LEFT_2 = 0x4000000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_RIGHT_2 = 0x8000000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_DECIDE = 0x10000000,
|
||||
SEKITO_IO_GAMEBTN_TERMINAL_CANCEL = 0x20000000,
|
||||
};
|
||||
|
||||
/* Get the version of the Eiketsu Taisen 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 sekito_io_get_api_version(void);
|
||||
|
||||
/* Initialize the IO DLL. This is the second function that will be called on
|
||||
your DLL, after sekito_io_get_api_version.
|
||||
|
||||
All subsequent calls to this API may originate from arbitrary threads.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
HRESULT sekito_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 sekito_io_poll(void);
|
||||
|
||||
/* Get the state of the cabinet's operator buttons as of the last poll. See
|
||||
SEKITO_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 sekito_io_get_opbtns(uint8_t *opbtn);
|
||||
|
||||
/* Get the state of the cabinet's gameplay buttons as of the last poll. See
|
||||
SEKITO_IO_GAMEBTN enum above: this contains bit mask definitions for button
|
||||
states returned in *gamebtn. All buttons are active-high.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
void sekito_io_get_gamebtns(uint32_t *gamebtn);
|
||||
|
||||
/* Get the position of the trackball as of the last poll.
|
||||
|
||||
Minimum API version: 0x0100 */
|
||||
|
||||
void sekito_io_get_trackball_position(uint16_t *stick_x, uint16_t *stick_y);
|
||||
|
||||
/* Initialize LED emulation. This function will be called before any
|
||||
other sekito_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. */
|
||||
|
||||
HRESULT sekito_io_led_init(void);
|
||||
|
||||
/* Update the RGB LEDs.
|
||||
|
||||
Exact layout is TBD. */
|
||||
|
||||
void sekito_io_led_set_colors(uint8_t board, uint8_t *rgb);
|
@ -127,6 +127,7 @@ subdir('games/tokyoio')
|
||||
subdir('games/fgoio')
|
||||
subdir('games/kemonoio')
|
||||
subdir('games/apm3io')
|
||||
subdir('games/sekitoio')
|
||||
subdir('games/ektio')
|
||||
|
||||
subdir('games/chunihook')
|
||||
@ -145,4 +146,4 @@ subdir('games/tokyohook')
|
||||
subdir('games/fgohook')
|
||||
subdir('games/kemonohook')
|
||||
subdir('games/apm3hook')
|
||||
subdir('games/ekthook')
|
||||
subdir('games/sekitohook')
|
||||
|
Reference in New Issue
Block a user