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)strip $(BUILD_DIR_ZIP)/ekt/*.{exe,dll}
|
||||||
$(V)cd $(BUILD_DIR_ZIP)/ekt ; zip -r ../ekt.zip *
|
$(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: \
|
$(BUILD_DIR_ZIP)/doc.zip: \
|
||||||
$(DOC_DIR)/config \
|
$(DOC_DIR)/config \
|
||||||
$(DOC_DIR)/chunihook.md \
|
$(DOC_DIR)/chunihook.md \
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <wtypes.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/fgoio')
|
||||||
subdir('games/kemonoio')
|
subdir('games/kemonoio')
|
||||||
subdir('games/apm3io')
|
subdir('games/apm3io')
|
||||||
|
subdir('games/sekitoio')
|
||||||
subdir('games/ektio')
|
subdir('games/ektio')
|
||||||
|
|
||||||
subdir('games/chunihook')
|
subdir('games/chunihook')
|
||||||
@ -145,4 +146,4 @@ subdir('games/tokyohook')
|
|||||||
subdir('games/fgohook')
|
subdir('games/fgohook')
|
||||||
subdir('games/kemonohook')
|
subdir('games/kemonohook')
|
||||||
subdir('games/apm3hook')
|
subdir('games/apm3hook')
|
||||||
subdir('games/ekthook')
|
subdir('games/sekitohook')
|
||||||
|
Reference in New Issue
Block a user