chore: CRLF to LF

This commit is contained in:
smpn2
2022-12-16 23:18:35 +09:00
parent b7a60638a4
commit 6c914266d9
725 changed files with 131020 additions and 131020 deletions
+4 -4
View File
@@ -1,4 +1,4 @@
bin/** bin/**
dist/** dist/**
docker/** docker/**
cmake-build* cmake-build*
+6 -6
View File
@@ -1,6 +1,6 @@
FROM spicetools/deps FROM spicetools/deps
WORKDIR /src WORKDIR /src
RUN chown user:user /src RUN chown user:user /src
USER user USER user
COPY --chown=user:user . /src COPY --chown=user:user . /src
CMD ./build_all.sh CMD ./build_all.sh
+674 -674
View File
File diff suppressed because it is too large Load Diff
+261 -261
View File
@@ -1,261 +1,261 @@
SpiceTools SpiceTools
========== ==========
This is a loader for various arcade games developed by 573. This is a loader for various arcade games developed by 573.
The project is using CMake as it's build system, with a custom build The project is using CMake as it's build system, with a custom build
script for making packages ready for distribution and to keep it easy script for making packages ready for distribution and to keep it easy
for people not knowing how to use CMake. for people not knowing how to use CMake.
## Building/Distribution ## Building/Distribution
We're currently using Arch Linux for building the binaries. We're currently using Arch Linux for building the binaries.
You'll need: You'll need:
- MinGW-64 packages (can be found in the AUR) - MinGW-64 packages (can be found in the AUR)
- bash - bash
- git - git
- zip - zip
- upx (optional) - upx (optional)
For any other GNU/Linux distributions (or Windows lol), you're on your For any other GNU/Linux distributions (or Windows lol), you're on your
own. own.
To build the project, run: To build the project, run:
$ ./build_all.sh $ ./build_all.sh
## Build Configuration ## Build Configuration
You can tweak some settings at the beginning of the build script. You You can tweak some settings at the beginning of the build script. You
might want to modify the paths of the toolchains if yours differ. It's might want to modify the paths of the toolchains if yours differ. It's
also possible to disable UPX compression and source distribution for also possible to disable UPX compression and source distribution for
example. example.
If you're not using an IDE and want to run the build script from command If you're not using an IDE and want to run the build script from command
line manually each time you make a change, you can set CLEAN_BUILD to 0 line manually each time you make a change, you can set CLEAN_BUILD to 0
so it will only compile what's needed. When modifying the resources you so it will only compile what's needed. When modifying the resources you
should build from scratch, since CMake isn't able to track changes of should build from scratch, since CMake isn't able to track changes of
those files (e.g. changelog.txt, licenses.txt). those files (e.g. changelog.txt, licenses.txt).
You can put your custom build script under "build_all.local.sh" if you You can put your custom build script under "build_all.local.sh" if you
don't want git to track the changes you made to the build settings. don't want git to track the changes you made to the build settings.
## Debug Build ## Debug Build
To get proper stackstraces, you need to build with the DEBUG setting To get proper stackstraces, you need to build with the DEBUG setting
enabled. This will set the CMake build type to debug and the script enabled. This will set the CMake build type to debug and the script
will try to make use of cv2pdb. will try to make use of cv2pdb.
Check external/cv2pdb/README.md for details on how to set it up. Check external/cv2pdb/README.md for details on how to set it up.
It is required to use cv2pdb to generate PDB output, because at time of It is required to use cv2pdb to generate PDB output, because at time of
writing, MinGW still didn't support Microsoft's proprietary file format. writing, MinGW still didn't support Microsoft's proprietary file format.
## API ## API
SpiceTools is providing a TCP/JSON based API. You can enable it with the SpiceTools is providing a TCP/JSON based API. You can enable it with the
`-api [PORT]` option. It's recommended to also set a password with `-api [PORT]` option. It's recommended to also set a password with
`-apipass [PASS]`. `-apipass [PASS]`.
The protocol is meant to be simple, easy to use and with few overhead. The protocol is meant to be simple, easy to use and with few overhead.
To connect to the API, just open a TCP connection to the host computer To connect to the API, just open a TCP connection to the host computer
at the specified port. at the specified port.
To make a request you write the UTF-8 encoded JSON contents to the To make a request you write the UTF-8 encoded JSON contents to the
socket. To mark the end of the request, you need to terminate the JSON socket. To mark the end of the request, you need to terminate the JSON
string with `0x00`. The server returns its answer on the same way, string with `0x00`. The server returns its answer on the same way,
UTF-8 encoded JSON terminated with NULL. UTF-8 encoded JSON terminated with NULL.
To save space, by default the JSONs are without whitespace. To enable To save space, by default the JSONs are without whitespace. To enable
pretty printing, use `-apipretty`. pretty printing, use `-apipretty`.
If you want to test the API server without running a game, you can If you want to test the API server without running a game, you can
run it headless via `-apidebug`. run it headless via `-apidebug`.
If a password is specified, both request and response are encrypted If a password is specified, both request and response are encrypted
using RC4 with the key being the password encoded in UTF-8. using RC4 with the key being the password encoded in UTF-8.
While only providing weak security when the password is static, While only providing weak security when the password is static,
it's simple to implement and requires no authentication protocol. it's simple to implement and requires no authentication protocol.
The password is also able to change dynamically, see The password is also able to change dynamically, see
`control.session_refresh()` for details. `control.session_refresh()` for details.
If you don't want to worry about all the details, you can just use one If you don't want to worry about all the details, you can just use one
of the supplied libraries (check /api/resources). There's also a little of the supplied libraries (check /api/resources). There's also a little
remote control GUI available for python. remote control GUI available for python.
### WebSocket ### WebSocket
SpiceTools opens a WebSocket server on the specified port plus one. SpiceTools opens a WebSocket server on the specified port plus one.
That means if the API is on 1337, the WebSocket server will be on 1338. That means if the API is on 1337, the WebSocket server will be on 1338.
The protocol is the very same as for the normal API, but instead of The protocol is the very same as for the normal API, but instead of
directly sending the data over TCP you need to send binary datapackets. directly sending the data over TCP you need to send binary datapackets.
The included dart spiceapi library also has a WebSocket implementation. The included dart spiceapi library also has a WebSocket implementation.
### Example Call ### Example Call
This example inserts the a card into P1's reader slot. This example inserts the a card into P1's reader slot.
If you need more examples, you can check the example code. If you need more examples, you can check the example code.
#### Request #### Request
```JSON ```JSON
{ {
"id": 1, "id": 1,
"module": "card", "module": "card",
"function": "insert", "function": "insert",
"params": [0, "E004000000000000"] "params": [0, "E004000000000000"]
} }
``` ```
#### Response #### Response
```JSON ```JSON
{ {
"id": 1, "id": 1,
"errors": [], "errors": [],
"data": [] "data": []
} }
``` ```
### Modules ### Modules
For the sake of simplifying this documentation, I will describe functions For the sake of simplifying this documentation, I will describe functions
as if they were called via a normal programming language. That means, as if they were called via a normal programming language. That means,
besides `module`/`function` needing to be set accordingly, the `params` field besides `module`/`function` needing to be set accordingly, the `params` field
must contain all the parameters described below. Some of them are optional. must contain all the parameters described below. Some of them are optional.
The returning data will always be in the `data` field of the response. The returning data will always be in the `data` field of the response.
Errors will be reported as strings in the `errors` field. Sometimes, you can Errors will be reported as strings in the `errors` field. Sometimes, you can
receive more than one error. The error messages may be changed/improved in the receive more than one error. The error messages may be changed/improved in the
future, so you shouldn't rely on them. If the error list is empty, the function future, so you shouldn't rely on them. If the error list is empty, the function
executed successfully. executed successfully.
The `id` of the response will always match the `id` of the request. The API The `id` of the response will always match the `id` of the request. The API
server itself doesn't expect any logic of your ID choices, however you can use server itself doesn't expect any logic of your ID choices, however you can use
them to make sure your answers aren't arriving out of order. Currently it them to make sure your answers aren't arriving out of order. Currently it
doesn't matter since the TCP protocol doesn't allow for out of order data, doesn't matter since the TCP protocol doesn't allow for out of order data,
however this may change when/if support for UDP is being introduced. The only however this may change when/if support for UDP is being introduced. The only
restriction is that the ID has to be a valid 64-bit unsigned integer. restriction is that the ID has to be a valid 64-bit unsigned integer.
#### Card #### Card
- insert(index: uint, card_id: hex) - insert(index: uint, card_id: hex)
- inserts a card which gets read by the emulated card readers for the game - inserts a card which gets read by the emulated card readers for the game
- index has to be either 0 (for P1) or 1 (for P2) - index has to be either 0 (for P1) or 1 (for P2)
- card_id has to be a valid 16-character hex string - card_id has to be a valid 16-character hex string
#### Coin #### Coin
- get() - get()
- returns the amount of unprocessed coins in queue - returns the amount of unprocessed coins in queue
- not equal to the amount of coins shown ingame since the game may drain it - not equal to the amount of coins shown ingame since the game may drain it
- set(amount: int) - set(amount: int)
- sets the amount of coins in queue for the game to process - sets the amount of coins in queue for the game to process
- insert(amount: int) - insert(amount: int)
- adds the amount to the coins in queue - adds the amount to the coins in queue
- amount is optional and defaults to 1 - amount is optional and defaults to 1
- blocker_get() - blocker_get()
- returns the current coin blocker state (false: open, true: closed) - returns the current coin blocker state (false: open, true: closed)
#### Info #### Info
- avs() - avs()
- returns a dict including the AVS model, dest, spec, rev and ext - returns a dict including the AVS model, dest, spec, rev and ext
- launcher() - launcher()
- returns a dict including the version, compile date/time, system time and - returns a dict including the version, compile date/time, system time and
the arguments used to start the process the arguments used to start the process
- memory() - memory()
- returns a dict including total, total used and bytes used by the process - returns a dict including total, total used and bytes used by the process
for both physical and virtual RAM for both physical and virtual RAM
#### Keypads #### Keypads
For all functions in this module, the keypad parameter must be For all functions in this module, the keypad parameter must be
either 0 (for P1) or 1 (for P2). Accepted keypad characters are "0" to "9" for either 0 (for P1) or 1 (for P2). Accepted keypad characters are "0" to "9" for
the single digit numbers, "A" for the double zero and "D" for the decimal key. the single digit numbers, "A" for the double zero and "D" for the decimal key.
- write(keypad: uint, input: str) - write(keypad: uint, input: str)
- writes all characters in input sequentially to the keypad - writes all characters in input sequentially to the keypad
- this should be used for things like PIN input - this should be used for things like PIN input
- set(keypad: uint, key: char, ...) - set(keypad: uint, key: char, ...)
- clears all overrides, then applies each given key as override - clears all overrides, then applies each given key as override
- if a key is overridden, it shows up as pressed in-game - if a key is overridden, it shows up as pressed in-game
- get(keypad: uint) - get(keypad: uint)
- returns all pressed keys of the specified keypad - returns all pressed keys of the specified keypad
#### Analogs/Buttons/Lights #### Analogs/Buttons/Lights
All of those three modules have equally named methods for you to call. All of those three modules have equally named methods for you to call.
- read() - read()
- returns an array of state objects containing name, state and a bool - returns an array of state objects containing name, state and a bool
- the bool indicates if the object is active (e.g. the button was overridden) - the bool indicates if the object is active (e.g. the button was overridden)
- write([name: str, state: float], ...) - write([name: str, state: float], ...)
- applies the states as an override value - applies the states as an override value
- the device binding via the config will be ignored while an override is set - the device binding via the config will be ignored while an override is set
- if an override value is set, the object will be marked as active - if an override value is set, the object will be marked as active
- write_reset([name: str], ...) - write_reset([name: str], ...)
- removes the override value from the objects specified by name - removes the override value from the objects specified by name
- if no names were passed, all overrides will be removed - if no names were passed, all overrides will be removed
#### Touch #### Touch
- read() - read()
- returns an array of state objects containing id, x and y - returns an array of state objects containing id, x and y
- write([id: uint, x: int, y: int], ...) - write([id: uint, x: int, y: int], ...)
- adds the given touch points having an unknown ID - adds the given touch points having an unknown ID
- overrides old touch points when the ID matches - overrides old touch points when the ID matches
- write_reset(id: uint, ...) - write_reset(id: uint, ...)
- removes the touch points matching one of the given IDs - removes the touch points matching one of the given IDs
#### Control #### Control
This module only functions if a password is being used to communicate, This module only functions if a password is being used to communicate,
with the single exception of session_refresh(). with the single exception of session_refresh().
- raise(signal: str) - raise(signal: str)
- raises a signal to the current process - raises a signal to the current process
- signal is a string and must be one of the following values: - signal is a string and must be one of the following values:
"SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM" "SIGABRT", "SIGFPE", "SIGILL", "SIGINT", "SIGSEGV", "SIGTERM"
- the signal will be raised while the message is being processed - the signal will be raised while the message is being processed
- exit(code: int) - exit(code: int)
- code is optional and defaults to 0 - code is optional and defaults to 0
- the process will end while the message is being processed - the process will end while the message is being processed
- restart() - restart()
- spawns a new instance with the same arguments as passed to the main executable - spawns a new instance with the same arguments as passed to the main executable
- session_refresh() - session_refresh()
- generates a new secure password and applies it after the response - generates a new secure password and applies it after the response
- can be used to increase the security by using the password as some kind of - can be used to increase the security by using the password as some kind of
session token session token
- recommended to call directly after connecting and once in a while for - recommended to call directly after connecting and once in a while for
persistent connections persistent connections
- shutdown() - shutdown()
- tries to force shutdown the computer - tries to force shutdown the computer
- reboot() - reboot()
- tries to force reboot the computer - tries to force reboot the computer
#### Memory #### Memory
This module only functions if a password is being used to communicate. This module only functions if a password is being used to communicate.
All offsets are specified in file offsets of the corresponding `dll_name`, All offsets are specified in file offsets of the corresponding `dll_name`,
which also means that your hex edits are applicable directly. which also means that your hex edits are applicable directly.
- write(dll_name: str, data: hex, offset: uint) - write(dll_name: str, data: hex, offset: uint)
- writes the bytes in data to the specified offset - writes the bytes in data to the specified offset
- read(dll_name: str, offset: uint, size: uint) - read(dll_name: str, offset: uint, size: uint)
- reads bytes starting from offset and returns it - reads bytes starting from offset and returns it
- signature(dll_name: str, signature: hex, replacement: hex, offset: uint, - signature(dll_name: str, signature: hex, replacement: hex, offset: uint,
usage: uint) usage: uint)
- tries to find the signature in the module's memory - tries to find the signature in the module's memory
- unknown bytes are masked out via "??" (e.g. "75??90????74") - unknown bytes are masked out via "??" (e.g. "75??90????74")
- masking out bytes works for both the signature and the replacement - masking out bytes works for both the signature and the replacement
- offset is the byte difference between the offset of the found signature and - offset is the byte difference between the offset of the found signature and
the offset where the replacement data gets written to the offset where the replacement data gets written to
- usage is the number of the result being used for replacement, starting at 0 - usage is the number of the result being used for replacement, starting at 0
- returns the offset where the replacement data gets written to - returns the offset where the replacement data gets written to
- the replacement string can be empty, so you can only get the address of the - the replacement string can be empty, so you can only get the address of the
signature while not actually replacing anything signature while not actually replacing anything
#### IIDX #### IIDX
- ticker_get() - ticker_get()
- returns a string of the characters displayed on the 16 segment display - returns a string of the characters displayed on the 16 segment display
- ticker_set(text: str) - ticker_set(text: str)
- sets the contents of the 16 segment display and disables writes from game - sets the contents of the 16 segment display and disables writes from game
- ticker_reset() - ticker_reset()
- re-enables writes from game - re-enables writes from game
#### LCD #### LCD
- info() - info()
- returns information about the serial LCD controller some games use - returns information about the serial LCD controller some games use
## License ## License
Unless otherwise noted, all files are licensed under the GPLv3. Unless otherwise noted, all files are licensed under the GPLv3.
See the LICENSE file for the full license text. See the LICENSE file for the full license text.
Files not originating from this project should be placed in "external", Files not originating from this project should be placed in "external",
they each have their own license. they each have their own license.
###### What that means for you ###### What that means for you
- If you want to distribute the binaries, you'll have to include the - If you want to distribute the binaries, you'll have to include the
sources, otherwise you're violating the GPL. sources, otherwise you're violating the GPL.
- If you want to merge some of this project's code into similar - If you want to merge some of this project's code into similar
software, that software has to be put under the GPL as well. software, that software has to be put under the GPL as well.
You'll probably have to modify a lot anyways, so you can just use the You'll probably have to modify a lot anyways, so you can just use the
source as some kind of documentation. source as some kind of documentation.
+18 -18
View File
@@ -1,18 +1,18 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <windows.h> #include <windows.h>
#include "module.h" #include "module.h"
namespace acio { namespace acio {
// globals // globals
extern HINSTANCE DLL_INSTANCE; extern HINSTANCE DLL_INSTANCE;
extern std::vector<acio::ACIOModule *> MODULES; extern std::vector<acio::ACIOModule *> MODULES;
void attach(); void attach();
void attach_icca(); void attach_icca();
void detach(); void detach();
} }
+510 -510
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class BI2AModule : public ACIOModule { class BI2AModule : public ACIOModule {
public: public:
BI2AModule(HMODULE module, HookMode hookMode); BI2AModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+596 -596
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class BMPUModule : public ACIOModule { class BMPUModule : public ACIOModule {
public: public:
BMPUModule(HMODULE module, HookMode hookMode); BMPUModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+190 -190
View File
@@ -1,190 +1,190 @@
#include "core.h" #include "core.h"
#include "avs/game.h" #include "avs/game.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
#include "misc/wintouchemu.h" #include "misc/wintouchemu.h"
#include "rawinput/rawinput.h" #include "rawinput/rawinput.h"
// static stuff // static stuff
static int ACIO_WARMUP = 0; static int ACIO_WARMUP = 0;
static HHOOK ACIO_KB_HOOK = nullptr; static HHOOK ACIO_KB_HOOK = nullptr;
/* /*
* Implementations * Implementations
*/ */
// needed for some games to make GetAsyncKeyState() working // needed for some games to make GetAsyncKeyState() working
static LRESULT CALLBACK ac_io_kb_hook_callback(int nCode, WPARAM wParam, LPARAM lParam) { static LRESULT CALLBACK ac_io_kb_hook_callback(int nCode, WPARAM wParam, LPARAM lParam) {
CallNextHookEx(ACIO_KB_HOOK, nCode, wParam, lParam); CallNextHookEx(ACIO_KB_HOOK, nCode, wParam, lParam);
return 0; return 0;
} }
static char __cdecl ac_io_begin( static char __cdecl ac_io_begin(
size_t dev, size_t dev,
const char *ver, const char *ver,
unsigned int *val, unsigned int *val,
size_t flags, size_t flags,
void *ptr, void *ptr,
size_t baud) size_t baud)
{ {
if (ACIO_KB_HOOK == nullptr) { if (ACIO_KB_HOOK == nullptr) {
ACIO_KB_HOOK = SetWindowsHookEx(WH_KEYBOARD_LL, ac_io_kb_hook_callback, GetModuleHandle(nullptr), 0); ACIO_KB_HOOK = SetWindowsHookEx(WH_KEYBOARD_LL, ac_io_kb_hook_callback, GetModuleHandle(nullptr), 0);
} }
// always return success // always return success
if (val && avs::game::is_model("KFC")) { if (val && avs::game::is_model("KFC")) {
*val = 2; *val = 2;
} }
return 1; return 1;
} }
static char __cdecl ac_io_begin_get_status() { static char __cdecl ac_io_begin_get_status() {
return 1; return 1;
} }
static int __cdecl ac_io_end(int a1) { static int __cdecl ac_io_end(int a1) {
return 1; return 1;
} }
static int __cdecl ac_io_end_get_status(int a1) { static int __cdecl ac_io_end_get_status(int a1) {
return 1; return 1;
} }
static void *__cdecl ac_io_get_rs232c_status(char *a1, int a2) { static void *__cdecl ac_io_get_rs232c_status(char *a1, int a2) {
return memset(a1, 0, 88); return memset(a1, 0, 88);
} }
static char __cdecl ac_io_get_version(uint8_t *a1, int a2) { static char __cdecl ac_io_get_version(uint8_t *a1, int a2) {
// some games have version checks // some games have version checks
// pop'n music only accepts versions bigger than 1.X.X (check yourself), anything starting with 2 works though // pop'n music only accepts versions bigger than 1.X.X (check yourself), anything starting with 2 works though
memset(a1 + 5, 2, 1); memset(a1 + 5, 2, 1);
memset(a1 + 6, 0, 1); memset(a1 + 6, 0, 1);
memset(a1 + 7, 0, 1); memset(a1 + 7, 0, 1);
return 1; return 1;
} }
static const char *__cdecl ac_io_get_version_string() { static const char *__cdecl ac_io_get_version_string() {
static const char *version = "1.25.0"; static const char *version = "1.25.0";
return version; return version;
} }
static char __cdecl ac_io_is_active(int a1, int a2) { static char __cdecl ac_io_is_active(int a1, int a2) {
if (a1 == 1 && avs::game::is_model("JMA")) { if (a1 == 1 && avs::game::is_model("JMA")) {
return 1; return 1;
} }
return (char) (++ACIO_WARMUP > 601 ? 1 : 0); return (char) (++ACIO_WARMUP > 601 ? 1 : 0);
} }
static int __cdecl ac_io_is_active2(int a1, int *a2, int a3) { static int __cdecl ac_io_is_active2(int a1, int *a2, int a3) {
ACIO_WARMUP = 601; ACIO_WARMUP = 601;
*a2 = 6; *a2 = 6;
return 1; return 1;
} }
static char __cdecl ac_io_is_active_device(int index, int a2) { static char __cdecl ac_io_is_active_device(int index, int a2) {
// for scotto // for scotto
static bool CHECKED_24 = false; static bool CHECKED_24 = false;
// dance evolution // dance evolution
if (avs::game::is_model("KDM")) { if (avs::game::is_model("KDM")) {
// disable mysterious LED devices // disable mysterious LED devices
if (index >= 12 && index <= 15) if (index >= 12 && index <= 15)
return false; return false;
} }
// scotto // scotto
if (avs::game::is_model("NSC") && index == 24) { if (avs::game::is_model("NSC") && index == 24) {
// scotto expects device index 24 to come online after // scotto expects device index 24 to come online after
// it initializes device index 22 // it initializes device index 22
if (!CHECKED_24) { if (!CHECKED_24) {
CHECKED_24 = true; CHECKED_24 = true;
return false; return false;
} }
return true; return true;
} }
// dunno for what game we did this again // dunno for what game we did this again
return (char) (index != 5); return (char) (index != 5);
} }
static int __cdecl ac_io_reset(int a1) { static int __cdecl ac_io_reset(int a1) {
return a1; return a1;
} }
static int __cdecl ac_io_secplug_set_encodedpasswd(void *a1, int a2) { static int __cdecl ac_io_secplug_set_encodedpasswd(void *a1, int a2) {
return 1; return 1;
} }
static int __cdecl ac_io_set_soft_watch_dog(int a1, int a2) { static int __cdecl ac_io_set_soft_watch_dog(int a1, int a2) {
return 1; return 1;
} }
static int __cdecl ac_io_soft_watch_dog_on(int a1) { static int __cdecl ac_io_soft_watch_dog_on(int a1) {
return 1; return 1;
} }
static int __cdecl ac_io_soft_watch_dog_off() { static int __cdecl ac_io_soft_watch_dog_off() {
return 1; return 1;
} }
static int __cdecl ac_io_update(int a1) { static int __cdecl ac_io_update(int a1) {
// flush device output // flush device output
RI_MGR->devices_flush_output(); RI_MGR->devices_flush_output();
// update wintouchemu // update wintouchemu
wintouchemu::update(); wintouchemu::update();
return 1; return 1;
} }
static int __cdecl ac_io_get_firmware_update_device_index() { static int __cdecl ac_io_get_firmware_update_device_index() {
return 0xFF; return 0xFF;
} }
static void __cdecl ac_io_go_firmware_update() { static void __cdecl ac_io_go_firmware_update() {
} }
static int __cdecl ac_io_set_get_status_device(int a1) { static int __cdecl ac_io_set_get_status_device(int a1) {
return a1; return a1;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::CoreModule::CoreModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("Core", module, hookMode) { acio::CoreModule::CoreModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("Core", module, hookMode) {
} }
void acio::CoreModule::attach() { void acio::CoreModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_begin); ACIO_MODULE_HOOK(ac_io_begin);
ACIO_MODULE_HOOK(ac_io_begin_get_status); ACIO_MODULE_HOOK(ac_io_begin_get_status);
ACIO_MODULE_HOOK(ac_io_end); ACIO_MODULE_HOOK(ac_io_end);
ACIO_MODULE_HOOK(ac_io_end_get_status); ACIO_MODULE_HOOK(ac_io_end_get_status);
ACIO_MODULE_HOOK(ac_io_get_rs232c_status); ACIO_MODULE_HOOK(ac_io_get_rs232c_status);
ACIO_MODULE_HOOK(ac_io_get_version); ACIO_MODULE_HOOK(ac_io_get_version);
ACIO_MODULE_HOOK(ac_io_get_version_string); ACIO_MODULE_HOOK(ac_io_get_version_string);
ACIO_MODULE_HOOK(ac_io_is_active); ACIO_MODULE_HOOK(ac_io_is_active);
ACIO_MODULE_HOOK(ac_io_is_active2); ACIO_MODULE_HOOK(ac_io_is_active2);
ACIO_MODULE_HOOK(ac_io_is_active_device); ACIO_MODULE_HOOK(ac_io_is_active_device);
ACIO_MODULE_HOOK(ac_io_reset); ACIO_MODULE_HOOK(ac_io_reset);
ACIO_MODULE_HOOK(ac_io_secplug_set_encodedpasswd); ACIO_MODULE_HOOK(ac_io_secplug_set_encodedpasswd);
ACIO_MODULE_HOOK(ac_io_set_soft_watch_dog); ACIO_MODULE_HOOK(ac_io_set_soft_watch_dog);
ACIO_MODULE_HOOK(ac_io_soft_watch_dog_on); ACIO_MODULE_HOOK(ac_io_soft_watch_dog_on);
ACIO_MODULE_HOOK(ac_io_soft_watch_dog_off); ACIO_MODULE_HOOK(ac_io_soft_watch_dog_off);
ACIO_MODULE_HOOK(ac_io_update); ACIO_MODULE_HOOK(ac_io_update);
ACIO_MODULE_HOOK(ac_io_get_firmware_update_device_index); ACIO_MODULE_HOOK(ac_io_get_firmware_update_device_index);
ACIO_MODULE_HOOK(ac_io_go_firmware_update); ACIO_MODULE_HOOK(ac_io_go_firmware_update);
ACIO_MODULE_HOOK(ac_io_set_get_status_device); ACIO_MODULE_HOOK(ac_io_set_get_status_device);
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class CoreModule : public ACIOModule { class CoreModule : public ACIOModule {
public: public:
CoreModule(HMODULE module, HookMode hookMode); CoreModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class HBHIModule : public ACIOModule { class HBHIModule : public ACIOModule {
public: public:
HBHIModule(HMODULE module, HookMode hookMode); HBHIModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class HDXSModule : public ACIOModule { class HDXSModule : public ACIOModule {
public: public:
HDXSModule(HMODULE module, HookMode hookMode); HDXSModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+122 -122
View File
@@ -1,122 +1,122 @@
#include "hgth.h" #include "hgth.h"
#include "acio/icca/icca.h" #include "acio/icca/icca.h"
#include "avs/game.h" #include "avs/game.h"
#include "cfg/api.h" #include "cfg/api.h"
#include "games/rf3d/io.h" #include "games/rf3d/io.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
using namespace GameAPI; using namespace GameAPI;
// state // state
static uint8_t STATUS_BUFFER[32] {}; static uint8_t STATUS_BUFFER[32] {};
static bool STATUS_BUFFER_FREEZE = false; static bool STATUS_BUFFER_FREEZE = false;
/* /*
* Implementations * Implementations
*/ */
static int __cdecl ac_io_hgth_set_senddata(int a1) { static int __cdecl ac_io_hgth_set_senddata(int a1) {
return 1; return 1;
} }
static char __cdecl ac_io_hgth_update_recvdata() { static char __cdecl ac_io_hgth_update_recvdata() {
// check freeze // check freeze
if (STATUS_BUFFER_FREEZE) { if (STATUS_BUFFER_FREEZE) {
return true; return true;
} }
// Road Fighters 3D // Road Fighters 3D
if (avs::game::is_model("JGT")) { if (avs::game::is_model("JGT")) {
// keypad mirror fix // keypad mirror fix
acio::ICCA_FLIP_ROWS = true; acio::ICCA_FLIP_ROWS = true;
// variables // variables
uint16_t wheel = 0x7FFF; uint16_t wheel = 0x7FFF;
uint16_t accelerator = 0x00; uint16_t accelerator = 0x00;
uint16_t brake = 0x00; uint16_t brake = 0x00;
// get buttons // get buttons
auto &buttons = games::rf3d::get_buttons(); auto &buttons = games::rf3d::get_buttons();
// check buttons // check buttons
bool wheel_button = false; bool wheel_button = false;
bool accelerate_button = false; bool accelerate_button = false;
bool brake_button = false; bool brake_button = false;
if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelLeft))) { if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelLeft))) {
wheel -= 0x7FFF; wheel -= 0x7FFF;
wheel_button = true; wheel_button = true;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelRight))) { if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::WheelRight))) {
wheel += 0x8000; wheel += 0x8000;
wheel_button = true; wheel_button = true;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Accelerate))) { if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Accelerate))) {
accelerator = 0xFFFF; accelerator = 0xFFFF;
accelerate_button = true; accelerate_button = true;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Brake))) { if (Buttons::getState(RI_MGR, buttons.at(games::rf3d::Buttons::Brake))) {
brake = 0xFFFF; brake = 0xFFFF;
brake_button = true; brake_button = true;
} }
// analogs // analogs
auto &analogs = games::rf3d::get_analogs(); auto &analogs = games::rf3d::get_analogs();
if (!wheel_button && analogs.at(games::rf3d::Analogs::Wheel).isSet()) { if (!wheel_button && analogs.at(games::rf3d::Analogs::Wheel).isSet()) {
wheel = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Wheel)) * 0xFFFF); wheel = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Wheel)) * 0xFFFF);
} }
if (!accelerate_button && analogs.at(games::rf3d::Analogs::Accelerate).isSet()) { if (!accelerate_button && analogs.at(games::rf3d::Analogs::Accelerate).isSet()) {
accelerator = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Accelerate)) * 0xFFFF); accelerator = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Accelerate)) * 0xFFFF);
} }
if (!brake_button && analogs.at(games::rf3d::Analogs::Brake).isSet()) { if (!brake_button && analogs.at(games::rf3d::Analogs::Brake).isSet()) {
brake = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Brake)) * 0xFFFF); brake = (uint16_t) (Analogs::getState(RI_MGR, analogs.at(games::rf3d::Analogs::Brake)) * 0xFFFF);
} }
// write values // write values
*((uint16_t *) STATUS_BUFFER + 1) = wheel; *((uint16_t *) STATUS_BUFFER + 1) = wheel;
*((uint16_t *) STATUS_BUFFER + 2) = accelerator; *((uint16_t *) STATUS_BUFFER + 2) = accelerator;
*((uint16_t *) STATUS_BUFFER + 3) = brake; *((uint16_t *) STATUS_BUFFER + 3) = brake;
} }
// success // success
return true; return true;
} }
static void __cdecl ac_io_hgth_get_recvdata(void *buffer) { static void __cdecl ac_io_hgth_get_recvdata(void *buffer) {
// copy buffer // copy buffer
memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER)); memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER));
} }
static char __cdecl ac_io_hgth_directreq_set_handle_limit(char a1, int *a2) { static char __cdecl ac_io_hgth_directreq_set_handle_limit(char a1, int *a2) {
*a2 = 1; *a2 = 1;
return 1; return 1;
} }
static bool __cdecl ac_io_hgth_directreq_set_handle_limit_isfinished(int *a1) { static bool __cdecl ac_io_hgth_directreq_set_handle_limit_isfinished(int *a1) {
*a1 = 2; *a1 = 2;
return true; return true;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::HGTHModule::HGTHModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("HGTH", module, hookMode) { acio::HGTHModule::HGTHModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("HGTH", module, hookMode) {
this->status_buffer = STATUS_BUFFER; this->status_buffer = STATUS_BUFFER;
this->status_buffer_size = sizeof(STATUS_BUFFER); this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
} }
void acio::HGTHModule::attach() { void acio::HGTHModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_hgth_set_senddata); ACIO_MODULE_HOOK(ac_io_hgth_set_senddata);
ACIO_MODULE_HOOK(ac_io_hgth_update_recvdata); ACIO_MODULE_HOOK(ac_io_hgth_update_recvdata);
ACIO_MODULE_HOOK(ac_io_hgth_get_recvdata); ACIO_MODULE_HOOK(ac_io_hgth_get_recvdata);
ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit); ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit);
ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit_isfinished); ACIO_MODULE_HOOK(ac_io_hgth_directreq_set_handle_limit_isfinished);
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class HGTHModule : public ACIOModule { class HGTHModule : public ACIOModule {
public: public:
HGTHModule(HMODULE module, HookMode hookMode); HGTHModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+375 -375
View File
@@ -1,375 +1,375 @@
#include "i36g.h" #include "i36g.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
#include "avs/game.h" #include "avs/game.h"
#include "rawinput/rawinput.h" #include "rawinput/rawinput.h"
#include "games/mga/io.h" #include "games/mga/io.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "util/utils.h" #include "util/utils.h"
using namespace GameAPI; using namespace GameAPI;
// static stuff // static stuff
static uint8_t STATUS_BUFFER[88 * 2] {}; static uint8_t STATUS_BUFFER[88 * 2] {};
static bool STATUS_BUFFER_FREEZE = false; static bool STATUS_BUFFER_FREEZE = false;
/* /*
* Implementations * Implementations
*/ */
static int __cdecl ac_io_i36g_add_coin(int a1, int a2, int a3) { static int __cdecl ac_io_i36g_add_coin(int a1, int a2, int a3) {
// not so sure we want to add coins // not so sure we want to add coins
return 1; return 1;
} }
static char __cdecl ac_io_i36g_consume_coinstock(int a1, int a2, int a3) { static char __cdecl ac_io_i36g_consume_coinstock(int a1, int a2, int a3) {
eamuse_coin_consume_stock(); eamuse_coin_consume_stock();
return 1; return 1;
} }
static int __cdecl ac_io_i36g_control_coin_blocker_close(int a1, int a2) { static int __cdecl ac_io_i36g_control_coin_blocker_close(int a1, int a2) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return 1; return 1;
} }
static int __cdecl ac_io_i36g_control_coin_blocker_open(int a1, int a2) { static int __cdecl ac_io_i36g_control_coin_blocker_open(int a1, int a2) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return 1; return 1;
} }
static int __cdecl ac_io_i36g_control_lamp_bright(uint32_t device, uint32_t lamp_bits, uint8_t brightness) { static int __cdecl ac_io_i36g_control_lamp_bright(uint32_t device, uint32_t lamp_bits, uint8_t brightness) {
// calculate value // calculate value
float value = (float) brightness / 255.f; float value = (float) brightness / 255.f;
// get lights // get lights
auto &lights = games::mga::get_lights(); auto &lights = games::mga::get_lights();
// cabinet device // cabinet device
if (device == 21) { if (device == 21) {
if (lamp_bits & 1) { if (lamp_bits & 1) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftR], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftR], value);
} }
if (lamp_bits & 2) { if (lamp_bits & 2) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftG], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftG], value);
} }
if (lamp_bits & 4) { if (lamp_bits & 4) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftB], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::LeftB], value);
} }
if (lamp_bits & 8) { if (lamp_bits & 8) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightR], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightR], value);
} }
if (lamp_bits & 16) { if (lamp_bits & 16) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightG], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightG], value);
} }
if (lamp_bits & 32) { if (lamp_bits & 32) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightB], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::RightB], value);
} }
if (lamp_bits & 512) { if (lamp_bits & 512) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::Start], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::Start], value);
} }
} }
// gun device // gun device
if (device == 22) { if (device == 22) {
if (lamp_bits & 1) { if (lamp_bits & 1) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunR], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunR], value);
} }
if (lamp_bits & 2) { if (lamp_bits & 2) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunG], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunG], value);
} }
if (lamp_bits & 4) { if (lamp_bits & 4) {
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunB], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunB], value);
} }
} }
// success // success
return 1; return 1;
} }
static int __cdecl ac_io_i36g_control_motor_power(int device, uint8_t strength) { static int __cdecl ac_io_i36g_control_motor_power(int device, uint8_t strength) {
// gun device // gun device
if (device == 22) { if (device == 22) {
float value = (float) strength / 255.f; float value = (float) strength / 255.f;
auto &lights = games::mga::get_lights(); auto &lights = games::mga::get_lights();
Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunVibration], value); Lights::writeLight(RI_MGR, lights[games::mga::Lights::GunVibration], value);
} }
// success // success
return 1; return 1;
} }
static char __cdecl ac_io_i36g_current_coinstock(int a1, int a2, int *a3) { static char __cdecl ac_io_i36g_current_coinstock(int a1, int a2, int *a3) {
// get coinstock // get coinstock
*a3 = eamuse_coin_get_stock(); *a3 = eamuse_coin_get_stock();
return 1; return 1;
} }
static char __cdecl ac_io_i36g_get_coin_input_wave_buffer(int a1, char *a2) { static char __cdecl ac_io_i36g_get_coin_input_wave_buffer(int a1, char *a2) {
return 1; return 1;
} }
static void __cdecl ac_io_i36g_get_control_status_buffer(int device, void *buffer) { static void __cdecl ac_io_i36g_get_control_status_buffer(int device, void *buffer) {
// cabinet buffer // cabinet buffer
if (device == 21) { if (device == 21) {
memcpy(buffer, &STATUS_BUFFER[0], 88); memcpy(buffer, &STATUS_BUFFER[0], 88);
} }
// gun buffer // gun buffer
if (device == 22) { if (device == 22) {
memcpy(buffer, &STATUS_BUFFER[88], 88); memcpy(buffer, &STATUS_BUFFER[88], 88);
} }
} }
static char __cdecl ac_io_i36g_get_softwareid(int a1, int a2) { static char __cdecl ac_io_i36g_get_softwareid(int a1, int a2) {
return 1; return 1;
} }
static char __cdecl ac_io_i36g_get_systemid(int a1, int a2) { static char __cdecl ac_io_i36g_get_systemid(int a1, int a2) {
return 1; return 1;
} }
static bool __cdecl ac_io_i36g_get_watchdog_status(int a1) { static bool __cdecl ac_io_i36g_get_watchdog_status(int a1) {
return false; return false;
} }
static short __cdecl ac_io_i36g_get_watchdog_time_min(int a1) { static short __cdecl ac_io_i36g_get_watchdog_time_min(int a1) {
return 0; return 0;
} }
static short __cdecl ac_io_i36g_get_watchdog_time_now(int a1) { static short __cdecl ac_io_i36g_get_watchdog_time_now(int a1) {
return 0; return 0;
} }
static char __cdecl ac_io_i36g_lock_coincounter(int a1, int a2) { static char __cdecl ac_io_i36g_lock_coincounter(int a1, int a2) {
return 1; return 1;
} }
static char __cdecl ac_io_i36g_req_coin_input_wave(int a1) { static char __cdecl ac_io_i36g_req_coin_input_wave(int a1) {
return 1; return 1;
} }
static char __cdecl ac_io_i36g_req_get_control_status(int a1, int *a2) { static char __cdecl ac_io_i36g_req_get_control_status(int a1, int *a2) {
return 1; return 1;
} }
static char __cdecl ac_io_i36g_req_secplug_check(int a1, char *a2) { static char __cdecl ac_io_i36g_req_secplug_check(int a1, char *a2) {
return 1; return 1;
} }
static bool __cdecl ac_io_i36g_req_secplug_check_isfinished(int a1, int *a2) { static bool __cdecl ac_io_i36g_req_secplug_check_isfinished(int a1, int *a2) {
return true; return true;
} }
static char __cdecl ac_io_i36g_req_secplug_check_softwareplug(int a1, char *a2) { static char __cdecl ac_io_i36g_req_secplug_check_softwareplug(int a1, char *a2) {
return 1; return 1;
} }
static char __cdecl ac_io_i36g_req_secplug_check_systemplug(int a1) { static char __cdecl ac_io_i36g_req_secplug_check_systemplug(int a1) {
return 1; return 1;
} }
static char __cdecl ac_io_i36g_req_secplug_missing_check(int a1) { static char __cdecl ac_io_i36g_req_secplug_missing_check(int a1) {
return 1; return 1;
} }
static bool __cdecl ac_io_i36g_req_secplug_missing_check_isfinished(int a1, int *a2) { static bool __cdecl ac_io_i36g_req_secplug_missing_check_isfinished(int a1, int *a2) {
return true; return true;
} }
static bool __cdecl ac_io_i36g_req_volume_control(int a1, char a2, char a3, char a4, char a5) { static bool __cdecl ac_io_i36g_req_volume_control(int a1, char a2, char a3, char a4, char a5) {
return true; return true;
} }
static bool __cdecl ac_io_i36g_req_volume_control_isfinished(int a1, int *ret_state) { static bool __cdecl ac_io_i36g_req_volume_control_isfinished(int a1, int *ret_state) {
*ret_state = 3; *ret_state = 3;
return true; return true;
} }
static int __cdecl ac_io_i36g_set_cmdmode(int a1, int a2) { static int __cdecl ac_io_i36g_set_cmdmode(int a1, int a2) {
return 1; return 1;
} }
static int __cdecl ac_io_i36g_set_framing_err_packet_send_interval(int a1) { static int __cdecl ac_io_i36g_set_framing_err_packet_send_interval(int a1) {
return 1; return 1;
} }
static bool __cdecl ac_io_i36g_set_watchdog_time(int a1, short a2) { static bool __cdecl ac_io_i36g_set_watchdog_time(int a1, short a2) {
return true; return true;
} }
static char __cdecl ac_io_i36g_unlock_coincounter(int a1, int a2) { static char __cdecl ac_io_i36g_unlock_coincounter(int a1, int a2) {
return 1; return 1;
} }
static bool __cdecl ac_io_i36g_update_control_status_buffer(int node) { static bool __cdecl ac_io_i36g_update_control_status_buffer(int node) {
// check freeze // check freeze
if (STATUS_BUFFER_FREEZE) { if (STATUS_BUFFER_FREEZE) {
return true; return true;
} }
// Metal Gear Arcade // Metal Gear Arcade
if (avs::game::is_model("I36")) { if (avs::game::is_model("I36")) {
// get buttons // get buttons
auto &buttons = games::mga::get_buttons(); auto &buttons = games::mga::get_buttons();
// cabinet device // cabinet device
if (node == 21) { if (node == 21) {
// clear status buffer // clear status buffer
memset(&STATUS_BUFFER[0], 0, 88); memset(&STATUS_BUFFER[0], 0, 88);
// update buttons // update buttons
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Service))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Service))) {
ARRAY_SETB(&STATUS_BUFFER[0], 44); ARRAY_SETB(&STATUS_BUFFER[0], 44);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Test))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Test))) {
ARRAY_SETB(&STATUS_BUFFER[0], 45); ARRAY_SETB(&STATUS_BUFFER[0], 45);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::CoinMech))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::CoinMech))) {
ARRAY_SETB(&STATUS_BUFFER[0], 42); ARRAY_SETB(&STATUS_BUFFER[0], 42);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Start))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Start))) {
ARRAY_SETB(&STATUS_BUFFER[0], 124); ARRAY_SETB(&STATUS_BUFFER[0], 124);
} }
} }
// gun device // gun device
if (node == 22) { if (node == 22) {
// clear status buffer // clear status buffer
memset(&STATUS_BUFFER[88], 0, 88); memset(&STATUS_BUFFER[88], 0, 88);
// update buttons // update buttons
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::TriggerButton)) if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::TriggerButton))
|| (GetKeyState(VK_LBUTTON) & 0x100) != 0) { // mouse button || (GetKeyState(VK_LBUTTON) & 0x100) != 0) { // mouse button
ARRAY_SETB(&STATUS_BUFFER[88], 109); ARRAY_SETB(&STATUS_BUFFER[88], 109);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontTop))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontTop))) {
ARRAY_SETB(&STATUS_BUFFER[88], 108); ARRAY_SETB(&STATUS_BUFFER[88], 108);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontBottom))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::FrontBottom))) {
ARRAY_SETB(&STATUS_BUFFER[88], 106); ARRAY_SETB(&STATUS_BUFFER[88], 106);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLeft))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLeft))) {
ARRAY_SETB(&STATUS_BUFFER[88], 107); ARRAY_SETB(&STATUS_BUFFER[88], 107);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideRight))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideRight))) {
ARRAY_SETB(&STATUS_BUFFER[88], 105); ARRAY_SETB(&STATUS_BUFFER[88], 105);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLever))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SideLever))) {
ARRAY_SETB(&STATUS_BUFFER[88], 104); ARRAY_SETB(&STATUS_BUFFER[88], 104);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SwitchButton))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::SwitchButton))) {
ARRAY_SETB(&STATUS_BUFFER[88], 125); ARRAY_SETB(&STATUS_BUFFER[88], 125);
} }
if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Top))) { if (Buttons::getState(RI_MGR, buttons.at(games::mga::Buttons::Top))) {
ARRAY_SETB(&STATUS_BUFFER[88], 124); ARRAY_SETB(&STATUS_BUFFER[88], 124);
} }
// joy stick // joy stick
unsigned short joy_x = 0x7FFF; unsigned short joy_x = 0x7FFF;
unsigned short joy_y = 0x7FFF; unsigned short joy_y = 0x7FFF;
bool joy_x_pressed = false; bool joy_x_pressed = false;
bool joy_y_pressed = false; bool joy_y_pressed = false;
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyForwards])) { if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyForwards])) {
joy_y -= 0x7FFF; joy_y -= 0x7FFF;
joy_y_pressed = true; joy_y_pressed = true;
} }
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyBackwards])) { if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyBackwards])) {
joy_y += 0x7FFF; joy_y += 0x7FFF;
joy_y_pressed = true; joy_y_pressed = true;
} }
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyLeft])) { if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyLeft])) {
joy_x -= 0x7FFF; joy_x -= 0x7FFF;
joy_x_pressed = true; joy_x_pressed = true;
} }
if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyRight])) { if (Buttons::getState(RI_MGR, buttons[games::mga::Buttons::JoyRight])) {
joy_x += 0x7FFF; joy_x += 0x7FFF;
joy_x_pressed = true; joy_x_pressed = true;
} }
// joy stick raw input // joy stick raw input
auto &analogs = games::mga::get_analogs(); auto &analogs = games::mga::get_analogs();
if (!joy_x_pressed && analogs[games::mga::Analogs::JoyX].isSet()) { if (!joy_x_pressed && analogs[games::mga::Analogs::JoyX].isSet()) {
joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyX]) * 0xFFFF); joy_x = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyX]) * 0xFFFF);
} }
if (!joy_y_pressed && analogs[games::mga::Analogs::JoyY].isSet()) { if (!joy_y_pressed && analogs[games::mga::Analogs::JoyY].isSet()) {
joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyY]) * 0xFFFF); joy_y = (unsigned short) (Analogs::getState(RI_MGR, analogs[games::mga::Analogs::JoyY]) * 0xFFFF);
} }
// save joy stick // save joy stick
STATUS_BUFFER[88 + 42] = LOBYTE(joy_y); STATUS_BUFFER[88 + 42] = LOBYTE(joy_y);
STATUS_BUFFER[88 + 43] = HIBYTE(joy_y); STATUS_BUFFER[88 + 43] = HIBYTE(joy_y);
STATUS_BUFFER[88 + 44] = LOBYTE(joy_x); STATUS_BUFFER[88 + 44] = LOBYTE(joy_x);
STATUS_BUFFER[88 + 45] = HIBYTE(joy_x); STATUS_BUFFER[88 + 45] = HIBYTE(joy_x);
} }
} }
// return success // return success
return true; return true;
} }
static int __cdecl ac_io_i36g_watchdog_off(int a1) { static int __cdecl ac_io_i36g_watchdog_off(int a1) {
return 1; return 1;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::I36GModule::I36GModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("I36G", module, hookMode) { acio::I36GModule::I36GModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("I36G", module, hookMode) {
this->status_buffer = &STATUS_BUFFER[0]; this->status_buffer = &STATUS_BUFFER[0];
this->status_buffer_size = sizeof(STATUS_BUFFER); this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
} }
void acio::I36GModule::attach() { void acio::I36GModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_i36g_add_coin); ACIO_MODULE_HOOK(ac_io_i36g_add_coin);
ACIO_MODULE_HOOK(ac_io_i36g_consume_coinstock); ACIO_MODULE_HOOK(ac_io_i36g_consume_coinstock);
ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_close); ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_close);
ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_open); ACIO_MODULE_HOOK(ac_io_i36g_control_coin_blocker_open);
ACIO_MODULE_HOOK(ac_io_i36g_control_lamp_bright); ACIO_MODULE_HOOK(ac_io_i36g_control_lamp_bright);
ACIO_MODULE_HOOK(ac_io_i36g_control_motor_power); ACIO_MODULE_HOOK(ac_io_i36g_control_motor_power);
ACIO_MODULE_HOOK(ac_io_i36g_current_coinstock); ACIO_MODULE_HOOK(ac_io_i36g_current_coinstock);
ACIO_MODULE_HOOK(ac_io_i36g_get_coin_input_wave_buffer); ACIO_MODULE_HOOK(ac_io_i36g_get_coin_input_wave_buffer);
ACIO_MODULE_HOOK(ac_io_i36g_get_control_status_buffer); ACIO_MODULE_HOOK(ac_io_i36g_get_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_i36g_get_softwareid); ACIO_MODULE_HOOK(ac_io_i36g_get_softwareid);
ACIO_MODULE_HOOK(ac_io_i36g_get_systemid); ACIO_MODULE_HOOK(ac_io_i36g_get_systemid);
ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_status); ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_status);
ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_min); ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_min);
ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_now); ACIO_MODULE_HOOK(ac_io_i36g_get_watchdog_time_now);
ACIO_MODULE_HOOK(ac_io_i36g_lock_coincounter); ACIO_MODULE_HOOK(ac_io_i36g_lock_coincounter);
ACIO_MODULE_HOOK(ac_io_i36g_req_coin_input_wave); ACIO_MODULE_HOOK(ac_io_i36g_req_coin_input_wave);
ACIO_MODULE_HOOK(ac_io_i36g_req_get_control_status); ACIO_MODULE_HOOK(ac_io_i36g_req_get_control_status);
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check); ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check);
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_isfinished); ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_isfinished);
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_softwareplug); ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_softwareplug);
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_systemplug); ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_check_systemplug);
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check); ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check);
ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check_isfinished); ACIO_MODULE_HOOK(ac_io_i36g_req_secplug_missing_check_isfinished);
ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control); ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control);
ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control_isfinished); ACIO_MODULE_HOOK(ac_io_i36g_req_volume_control_isfinished);
ACIO_MODULE_HOOK(ac_io_i36g_set_cmdmode); ACIO_MODULE_HOOK(ac_io_i36g_set_cmdmode);
ACIO_MODULE_HOOK(ac_io_i36g_set_framing_err_packet_send_interval); ACIO_MODULE_HOOK(ac_io_i36g_set_framing_err_packet_send_interval);
ACIO_MODULE_HOOK(ac_io_i36g_set_watchdog_time); ACIO_MODULE_HOOK(ac_io_i36g_set_watchdog_time);
ACIO_MODULE_HOOK(ac_io_i36g_unlock_coincounter); ACIO_MODULE_HOOK(ac_io_i36g_unlock_coincounter);
ACIO_MODULE_HOOK(ac_io_i36g_update_control_status_buffer); ACIO_MODULE_HOOK(ac_io_i36g_update_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_i36g_watchdog_off); ACIO_MODULE_HOOK(ac_io_i36g_watchdog_off);
// I36S links // I36S links
this->hook((void *) ac_io_i36g_update_control_status_buffer, this->hook((void *) ac_io_i36g_update_control_status_buffer,
"ac_io_i36s_update_control_status_buffer"); "ac_io_i36s_update_control_status_buffer");
this->hook((void *) ac_io_i36g_get_control_status_buffer, this->hook((void *) ac_io_i36g_get_control_status_buffer,
"ac_io_i36s_get_control_status_buffer"); "ac_io_i36s_get_control_status_buffer");
this->hook((void *) ac_io_i36g_set_cmdmode, this->hook((void *) ac_io_i36g_set_cmdmode,
"ac_io_i36s_set_cmdmode"); "ac_io_i36s_set_cmdmode");
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class I36GModule : public ACIOModule { class I36GModule : public ACIOModule {
public: public:
I36GModule(HMODULE module, HookMode hookMode); I36GModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class I36IModule : public ACIOModule { class I36IModule : public ACIOModule {
public: public:
I36IModule(HMODULE module, HookMode hookMode); I36IModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+21 -21
View File
@@ -1,21 +1,21 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
// settings // settings
extern bool ICCA_FLIP_ROWS; extern bool ICCA_FLIP_ROWS;
extern bool ICCA_COMPAT_ACTIVE; extern bool ICCA_COMPAT_ACTIVE;
class ICCAModule : public ACIOModule { class ICCAModule : public ACIOModule {
public: public:
ICCAModule(HMODULE module, HookMode hookMode); ICCAModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
static inline bool is_card_uid_felica(uint8_t *uid) { static inline bool is_card_uid_felica(uint8_t *uid) {
return uid[0] != 0xE0 && uid[1] != 0x04; return uid[0] != 0xE0 && uid[1] != 0x04;
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class J32DModule : public ACIOModule { class J32DModule : public ACIOModule {
public: public:
J32DModule(HMODULE module, HookMode hookMode); J32DModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+483 -483
View File
@@ -1,483 +1,483 @@
#include "kfca.h" #include "kfca.h"
#include "avs/game.h" #include "avs/game.h"
#include "games/bs/io.h" #include "games/bs/io.h"
#include "games/nost/io.h" #include "games/nost/io.h"
#include "games/scotto/io.h" #include "games/scotto/io.h"
#include "games/sdvx/io.h" #include "games/sdvx/io.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "rawinput/rawinput.h" #include "rawinput/rawinput.h"
#include "util/utils.h" #include "util/utils.h"
using namespace GameAPI; using namespace GameAPI;
// globals // globals
uint8_t KFCA_VOL_SOUND = 96; uint8_t KFCA_VOL_SOUND = 96;
uint8_t KFCA_VOL_HEADPHONE = 96; uint8_t KFCA_VOL_HEADPHONE = 96;
uint8_t KFCA_VOL_EXTERNAL = 96; uint8_t KFCA_VOL_EXTERNAL = 96;
uint8_t KFCA_VOL_WOOFER = 96; uint8_t KFCA_VOL_WOOFER = 96;
// static stuff // static stuff
static uint8_t STATUS_BUFFER[64] {}; static uint8_t STATUS_BUFFER[64] {};
static bool STATUS_BUFFER_FREEZE = false; static bool STATUS_BUFFER_FREEZE = false;
static unsigned int KFCA_VOLL = 0; static unsigned int KFCA_VOLL = 0;
static unsigned int KFCA_VOLR = 0; static unsigned int KFCA_VOLR = 0;
/* /*
* Implementations * Implementations
*/ */
static int __cdecl ac_io_kfca_control_button_led(unsigned int button, bool state) { static int __cdecl ac_io_kfca_control_button_led(unsigned int button, bool state) {
// Sound Voltex // Sound Voltex
if (avs::game::is_model("KFC")) { if (avs::game::is_model("KFC")) {
// control mapping // control mapping
static const size_t mapping[] = { static const size_t mapping[] = {
games::sdvx::Lights::BT_A, games::sdvx::Lights::BT_A,
games::sdvx::Lights::BT_B, games::sdvx::Lights::BT_B,
games::sdvx::Lights::BT_C, games::sdvx::Lights::BT_C,
games::sdvx::Lights::BT_D, games::sdvx::Lights::BT_D,
games::sdvx::Lights::FX_L, games::sdvx::Lights::FX_L,
games::sdvx::Lights::FX_R, games::sdvx::Lights::FX_R,
games::sdvx::Lights::START, games::sdvx::Lights::START,
games::sdvx::Lights::GENERATOR_B, games::sdvx::Lights::GENERATOR_B,
}; };
// check if button is mapped // check if button is mapped
if (button < 8) { if (button < 8) {
// get lights // get lights
auto &lights = games::sdvx::get_lights(); auto &lights = games::sdvx::get_lights();
// write light // write light
float value = state ? 1.f : 0.f; float value = state ? 1.f : 0.f;
Lights::writeLight(RI_MGR, lights.at(mapping[button]), value); Lights::writeLight(RI_MGR, lights.at(mapping[button]), value);
} }
} }
// Scotto // Scotto
if (avs::game::is_model("NSC")) { if (avs::game::is_model("NSC")) {
// control mapping // control mapping
static const size_t mapping[] = { static const size_t mapping[] = {
games::scotto::Lights::PAD_F_B, games::scotto::Lights::PAD_F_B,
games::scotto::Lights::PAD_E_R, games::scotto::Lights::PAD_E_R,
games::scotto::Lights::PAD_E_B, games::scotto::Lights::PAD_E_B,
~0u, ~0u,
~0u, ~0u,
~0u, ~0u,
games::scotto::Lights::PAD_F_R, games::scotto::Lights::PAD_F_R,
games::scotto::Lights::BUTTON, games::scotto::Lights::BUTTON,
}; };
// check if button is mapped // check if button is mapped
if (button < std::size(mapping) && button[mapping] != ~0u) { if (button < std::size(mapping) && button[mapping] != ~0u) {
// get lights // get lights
auto &lights = games::scotto::get_lights(); auto &lights = games::scotto::get_lights();
// write light // write light
float value = state ? 1.f : 0.f; float value = state ? 1.f : 0.f;
Lights::writeLight(RI_MGR, lights.at(mapping[button]), value); Lights::writeLight(RI_MGR, lights.at(mapping[button]), value);
} }
} }
// return success // return success
return 1; return 1;
} }
static int __cdecl ac_io_kfca_control_coin_blocker_close(int a1) { static int __cdecl ac_io_kfca_control_coin_blocker_close(int a1) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return 1; return 1;
} }
static int __cdecl ac_io_kfca_control_coin_blocker_open(int a1) { static int __cdecl ac_io_kfca_control_coin_blocker_open(int a1) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return 1; return 1;
} }
static int __cdecl ac_io_kfca_control_led_bright(uint32_t led_field, uint8_t brightness) { static int __cdecl ac_io_kfca_control_led_bright(uint32_t led_field, uint8_t brightness) {
// Sound Voltex // Sound Voltex
if (avs::game::is_model("KFC")) { if (avs::game::is_model("KFC")) {
// get lights // get lights
auto &lights = games::sdvx::get_lights(); auto &lights = games::sdvx::get_lights();
// control mapping // control mapping
static const size_t mapping[] { static const size_t mapping[] {
games::sdvx::Lights::WING_LEFT_UP_R, games::sdvx::Lights::WING_LEFT_UP_R,
games::sdvx::Lights::WING_LEFT_UP_G, games::sdvx::Lights::WING_LEFT_UP_G,
games::sdvx::Lights::WING_LEFT_UP_B, games::sdvx::Lights::WING_LEFT_UP_B,
games::sdvx::Lights::WING_RIGHT_UP_R, games::sdvx::Lights::WING_RIGHT_UP_R,
games::sdvx::Lights::WING_RIGHT_UP_G, games::sdvx::Lights::WING_RIGHT_UP_G,
games::sdvx::Lights::WING_RIGHT_UP_B, games::sdvx::Lights::WING_RIGHT_UP_B,
games::sdvx::Lights::WING_LEFT_LOW_R, games::sdvx::Lights::WING_LEFT_LOW_R,
games::sdvx::Lights::WING_LEFT_LOW_G, games::sdvx::Lights::WING_LEFT_LOW_G,
games::sdvx::Lights::WING_LEFT_LOW_B, games::sdvx::Lights::WING_LEFT_LOW_B,
games::sdvx::Lights::WING_RIGHT_LOW_R, games::sdvx::Lights::WING_RIGHT_LOW_R,
games::sdvx::Lights::WING_RIGHT_LOW_G, games::sdvx::Lights::WING_RIGHT_LOW_G,
games::sdvx::Lights::WING_RIGHT_LOW_B, games::sdvx::Lights::WING_RIGHT_LOW_B,
games::sdvx::Lights::WOOFER_R, games::sdvx::Lights::WOOFER_R,
games::sdvx::Lights::WOOFER_G, games::sdvx::Lights::WOOFER_G,
games::sdvx::Lights::WOOFER_B, games::sdvx::Lights::WOOFER_B,
games::sdvx::Lights::CONTROLLER_R, games::sdvx::Lights::CONTROLLER_R,
games::sdvx::Lights::CONTROLLER_G, games::sdvx::Lights::CONTROLLER_G,
games::sdvx::Lights::CONTROLLER_B, games::sdvx::Lights::CONTROLLER_B,
games::sdvx::Lights::GENERATOR_R, games::sdvx::Lights::GENERATOR_R,
games::sdvx::Lights::GENERATOR_G, games::sdvx::Lights::GENERATOR_G,
}; };
// write light // write light
float value = brightness / 255.f; float value = brightness / 255.f;
for (size_t i = 0; i < std::size(mapping); i++) { for (size_t i = 0; i < std::size(mapping); i++) {
if (led_field & (1 << i)) { if (led_field & (1 << i)) {
Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
} }
} }
} }
// BeatStream // BeatStream
if (avs::game::is_model("NBT")) { if (avs::game::is_model("NBT")) {
// get lights // get lights
auto &lights = games::bs::get_lights(); auto &lights = games::bs::get_lights();
// mapping // mapping
static const size_t mapping[] { static const size_t mapping[] {
~0u, ~0u, ~0u, ~0u, ~0u, ~0u,
games::bs::Lights::RightR, games::bs::Lights::RightR,
games::bs::Lights::RightG, games::bs::Lights::RightG,
games::bs::Lights::RightB, games::bs::Lights::RightB,
games::bs::Lights::LeftR, games::bs::Lights::LeftR,
games::bs::Lights::LeftG, games::bs::Lights::LeftG,
games::bs::Lights::LeftB, games::bs::Lights::LeftB,
games::bs::Lights::BottomR, games::bs::Lights::BottomR,
games::bs::Lights::BottomG, games::bs::Lights::BottomG,
games::bs::Lights::BottomB, games::bs::Lights::BottomB,
}; };
// write light // write light
float value = brightness / 127.f; float value = brightness / 127.f;
for (size_t i = 0; i < std::size(mapping); i++) { for (size_t i = 0; i < std::size(mapping); i++) {
if (mapping[i] != ~0u && led_field & (1 << i)) { if (mapping[i] != ~0u && led_field & (1 << i)) {
Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
} }
} }
} }
// Nostalgia // Nostalgia
if (avs::game::is_model("PAN")) { if (avs::game::is_model("PAN")) {
// get lights // get lights
auto &lights = games::nost::get_lights(); auto &lights = games::nost::get_lights();
// mapping // mapping
static const size_t mapping[] { static const size_t mapping[] {
~0u, ~0u, ~0u, ~0u, ~0u, ~0u,
games::nost::Lights::TitleR, games::nost::Lights::TitleR,
games::nost::Lights::TitleG, games::nost::Lights::TitleG,
games::nost::Lights::TitleB, games::nost::Lights::TitleB,
~0u, ~0u, ~0u, ~0u, ~0u, ~0u,
games::nost::Lights::BottomR, games::nost::Lights::BottomR,
games::nost::Lights::BottomG, games::nost::Lights::BottomG,
games::nost::Lights::BottomB, games::nost::Lights::BottomB,
}; };
// write light // write light
float value = brightness / 127.f; float value = brightness / 127.f;
for (size_t i = 0; i < std::size(mapping); i++) { for (size_t i = 0; i < std::size(mapping); i++) {
if (mapping[i] != ~0u && led_field & (1 << i)) { if (mapping[i] != ~0u && led_field & (1 << i)) {
Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
} }
} }
} }
// Scotto // Scotto
if (avs::game::is_model("NSC")) { if (avs::game::is_model("NSC")) {
// get lights // get lights
auto &lights = games::scotto::get_lights(); auto &lights = games::scotto::get_lights();
// mapping // mapping
static const size_t mapping[] { static const size_t mapping[] {
games::scotto::Lights::CUP_R, games::scotto::Lights::CUP_R,
games::scotto::Lights::CUP_G, games::scotto::Lights::CUP_G,
games::scotto::Lights::CUP_B, games::scotto::Lights::CUP_B,
games::scotto::Lights::PAD_A_R, games::scotto::Lights::PAD_A_R,
games::scotto::Lights::PAD_A_G, games::scotto::Lights::PAD_A_G,
games::scotto::Lights::PAD_A_B, games::scotto::Lights::PAD_A_B,
games::scotto::Lights::PAD_B_R, games::scotto::Lights::PAD_B_R,
games::scotto::Lights::PAD_B_G, games::scotto::Lights::PAD_B_G,
games::scotto::Lights::PAD_B_B, games::scotto::Lights::PAD_B_B,
games::scotto::Lights::PAD_C_R, games::scotto::Lights::PAD_C_R,
games::scotto::Lights::PAD_C_G, games::scotto::Lights::PAD_C_G,
games::scotto::Lights::PAD_C_B, games::scotto::Lights::PAD_C_B,
games::scotto::Lights::PAD_D_R, games::scotto::Lights::PAD_D_R,
games::scotto::Lights::PAD_D_G, games::scotto::Lights::PAD_D_G,
games::scotto::Lights::PAD_D_B, games::scotto::Lights::PAD_D_B,
games::scotto::Lights::FIRST_PAD_R, games::scotto::Lights::FIRST_PAD_R,
games::scotto::Lights::FIRST_PAD_G, games::scotto::Lights::FIRST_PAD_G,
games::scotto::Lights::FIRST_PAD_B, games::scotto::Lights::FIRST_PAD_B,
games::scotto::Lights::PAD_F_G, games::scotto::Lights::PAD_F_G,
games::scotto::Lights::PAD_E_G, games::scotto::Lights::PAD_E_G,
}; };
// write light // write light
float value = brightness / 255.f; float value = brightness / 255.f;
for (size_t i = 0; i < std::size(mapping); i++) { for (size_t i = 0; i < std::size(mapping); i++) {
if (led_field & (1 << i)) { if (led_field & (1 << i)) {
Lights::writeLight(RI_MGR, lights.at(mapping[i]), value); Lights::writeLight(RI_MGR, lights.at(mapping[i]), value);
} }
} }
} }
// return success // return success
return 1; return 1;
} }
static char __cdecl ac_io_kfca_current_coinstock(int a1, DWORD *a2) { static char __cdecl ac_io_kfca_current_coinstock(int a1, DWORD *a2) {
*a2 = (DWORD) eamuse_coin_get_stock(); *a2 = (DWORD) eamuse_coin_get_stock();
return 1; return 1;
} }
static void *__cdecl ac_io_kfca_get_control_status_buffer(void *target_buffer) { static void *__cdecl ac_io_kfca_get_control_status_buffer(void *target_buffer) {
// copy buffer // copy buffer
return memcpy(target_buffer, STATUS_BUFFER, 64); return memcpy(target_buffer, STATUS_BUFFER, 64);
} }
static int __cdecl ac_io_kfca_lock_coincounter(int a1) { static int __cdecl ac_io_kfca_lock_coincounter(int a1) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return 1; return 1;
} }
static bool __cdecl ac_io_kfca_req_volume_control( static bool __cdecl ac_io_kfca_req_volume_control(
uint8_t vol_sound, uint8_t vol_headphone, uint8_t vol_external, uint8_t vol_woofer) { uint8_t vol_sound, uint8_t vol_headphone, uint8_t vol_external, uint8_t vol_woofer) {
// update globals // update globals
KFCA_VOL_SOUND = vol_sound; KFCA_VOL_SOUND = vol_sound;
KFCA_VOL_HEADPHONE = vol_headphone; KFCA_VOL_HEADPHONE = vol_headphone;
KFCA_VOL_EXTERNAL = vol_external; KFCA_VOL_EXTERNAL = vol_external;
KFCA_VOL_WOOFER = vol_woofer; KFCA_VOL_WOOFER = vol_woofer;
// Sound Voltex // Sound Voltex
if (avs::game::is_model("KFC")) { if (avs::game::is_model("KFC")) {
// get lights // get lights
auto &lights = games::sdvx::get_lights(); auto &lights = games::sdvx::get_lights();
GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_SOUND], GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_SOUND],
(100 - vol_sound) / 100.f); (100 - vol_sound) / 100.f);
GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_HEADPHONE], GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_HEADPHONE],
(100 - vol_headphone) / 100.f); (100 - vol_headphone) / 100.f);
GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_EXTERNAL], GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_EXTERNAL],
(100 - vol_external) / 100.f); (100 - vol_external) / 100.f);
GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_WOOFER], GameAPI::Lights::writeLight(RI_MGR, lights[games::sdvx::Lights::VOLUME_WOOFER],
(100 - vol_woofer) / 100.f); (100 - vol_woofer) / 100.f);
} }
return true; return true;
} }
static bool __cdecl ac_io_kfca_set_watchdog_time(short a1) { static bool __cdecl ac_io_kfca_set_watchdog_time(short a1) {
return true; return true;
} }
static char __cdecl ac_io_kfca_unlock_coincounter(int a1) { static char __cdecl ac_io_kfca_unlock_coincounter(int a1) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return 1; return 1;
} }
static char __cdecl ac_io_kfca_update_control_status_buffer() { static char __cdecl ac_io_kfca_update_control_status_buffer() {
static const int input_offset = 4; static const int input_offset = 4;
// check freeze // check freeze
if (STATUS_BUFFER_FREEZE) { if (STATUS_BUFFER_FREEZE) {
return true; return true;
} }
// clear buffer // clear buffer
memset(STATUS_BUFFER, 0, 64); memset(STATUS_BUFFER, 0, 64);
// SDVX // SDVX
if (avs::game::is_model("KFC")) { if (avs::game::is_model("KFC")) {
// get buttons // get buttons
auto &buttons = games::sdvx::get_buttons(); auto &buttons = games::sdvx::get_buttons();
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Test))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Test))) {
STATUS_BUFFER[input_offset + 1] |= 0x20; STATUS_BUFFER[input_offset + 1] |= 0x20;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Service))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Service))) {
STATUS_BUFFER[input_offset + 1] |= 0x10; STATUS_BUFFER[input_offset + 1] |= 0x10;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::CoinMech))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::CoinMech))) {
STATUS_BUFFER[input_offset + 1] |= 0x04; STATUS_BUFFER[input_offset + 1] |= 0x04;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Start))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Start))) {
STATUS_BUFFER[input_offset + 9] |= 0x08; STATUS_BUFFER[input_offset + 9] |= 0x08;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_A))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_A))) {
STATUS_BUFFER[input_offset + 9] |= 0x04; STATUS_BUFFER[input_offset + 9] |= 0x04;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_B))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_B))) {
STATUS_BUFFER[input_offset + 9] |= 0x02; STATUS_BUFFER[input_offset + 9] |= 0x02;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_C))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_C))) {
STATUS_BUFFER[input_offset + 9] |= 0x01; STATUS_BUFFER[input_offset + 9] |= 0x01;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_D))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::BT_D))) {
STATUS_BUFFER[input_offset + 11] |= 0x20; STATUS_BUFFER[input_offset + 11] |= 0x20;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_L))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_L))) {
STATUS_BUFFER[input_offset + 11] |= 0x10; STATUS_BUFFER[input_offset + 11] |= 0x10;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_R))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::FX_R))) {
STATUS_BUFFER[input_offset + 11] |= 0x08; STATUS_BUFFER[input_offset + 11] |= 0x08;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Headphone))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::Headphone))) {
STATUS_BUFFER[input_offset + 9] |= 0x20; STATUS_BUFFER[input_offset + 9] |= 0x20;
} }
// volume left // volume left
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Left))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Left))) {
KFCA_VOLL = (KFCA_VOLL - 16) & 1023; KFCA_VOLL = (KFCA_VOLL - 16) & 1023;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Right))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_L_Right))) {
KFCA_VOLL = (KFCA_VOLL + 16) & 1023; KFCA_VOLL = (KFCA_VOLL + 16) & 1023;
} }
// volume right // volume right
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Left))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Left))) {
KFCA_VOLR = (KFCA_VOLR - 16) & 1023; KFCA_VOLR = (KFCA_VOLR - 16) & 1023;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Right))) { if (Buttons::getState(RI_MGR, buttons.at(games::sdvx::Buttons::VOL_R_Right))) {
KFCA_VOLR = (KFCA_VOLR + 16) & 1023; KFCA_VOLR = (KFCA_VOLR + 16) & 1023;
} }
// update volumes // update volumes
auto &analogs = games::sdvx::get_analogs(); auto &analogs = games::sdvx::get_analogs();
auto vol_left = KFCA_VOLL; auto vol_left = KFCA_VOLL;
auto vol_right = KFCA_VOLR; auto vol_right = KFCA_VOLR;
if (analogs.at(0).isSet() || analogs.at(1).isSet()) { if (analogs.at(0).isSet() || analogs.at(1).isSet()) {
vol_left += (unsigned int) (Analogs::getState(RI_MGR, vol_left += (unsigned int) (Analogs::getState(RI_MGR,
analogs.at(games::sdvx::Analogs::VOL_L)) * 1023.99f); analogs.at(games::sdvx::Analogs::VOL_L)) * 1023.99f);
vol_right += (unsigned int) (Analogs::getState(RI_MGR, vol_right += (unsigned int) (Analogs::getState(RI_MGR,
analogs.at(games::sdvx::Analogs::VOL_R)) * 1023.99f); analogs.at(games::sdvx::Analogs::VOL_R)) * 1023.99f);
} }
// proper loops // proper loops
vol_left %= 1024; vol_left %= 1024;
vol_right %= 1024; vol_right %= 1024;
// save volumes in buffer // save volumes in buffer
STATUS_BUFFER[input_offset + 16 + 0] |= (unsigned char) ((vol_left << 6) & 0xFF); STATUS_BUFFER[input_offset + 16 + 0] |= (unsigned char) ((vol_left << 6) & 0xFF);
STATUS_BUFFER[input_offset + 16 + 1] |= (unsigned char) ((vol_left >> 2) & 0xFF); STATUS_BUFFER[input_offset + 16 + 1] |= (unsigned char) ((vol_left >> 2) & 0xFF);
STATUS_BUFFER[input_offset + 16 + 2] |= (unsigned char) ((vol_right << 6) & 0xFF); STATUS_BUFFER[input_offset + 16 + 2] |= (unsigned char) ((vol_right << 6) & 0xFF);
STATUS_BUFFER[input_offset + 16 + 3] |= (unsigned char) ((vol_right >> 2) & 0xFF); STATUS_BUFFER[input_offset + 16 + 3] |= (unsigned char) ((vol_right >> 2) & 0xFF);
} }
// Beatstream // Beatstream
if (avs::game::is_model("NBT")) { if (avs::game::is_model("NBT")) {
// get buttons // get buttons
auto &buttons = games::bs::get_buttons(); auto &buttons = games::bs::get_buttons();
if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Test))) { if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Test))) {
STATUS_BUFFER[input_offset + 1] |= 0x20; STATUS_BUFFER[input_offset + 1] |= 0x20;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Service))) { if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::Service))) {
STATUS_BUFFER[input_offset + 1] |= 0x10; STATUS_BUFFER[input_offset + 1] |= 0x10;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::CoinMech))) { if (Buttons::getState(RI_MGR, buttons.at(games::bs::Buttons::CoinMech))) {
STATUS_BUFFER[input_offset + 1] |= 0x04; STATUS_BUFFER[input_offset + 1] |= 0x04;
} }
} }
// Nostalgia // Nostalgia
if (avs::game::is_model("PAN")) { if (avs::game::is_model("PAN")) {
// get buttons // get buttons
auto &buttons = games::nost::get_buttons(); auto &buttons = games::nost::get_buttons();
if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Service))) { if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Service))) {
STATUS_BUFFER[input_offset + 1] |= 0x10; STATUS_BUFFER[input_offset + 1] |= 0x10;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Test))) { if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::Test))) {
STATUS_BUFFER[input_offset + 1] |= 0x20; STATUS_BUFFER[input_offset + 1] |= 0x20;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::CoinMech))) { if (Buttons::getState(RI_MGR, buttons.at(games::nost::Buttons::CoinMech))) {
STATUS_BUFFER[input_offset + 1] |= 0x04; STATUS_BUFFER[input_offset + 1] |= 0x04;
} }
} }
// Scotto // Scotto
if (avs::game::is_model("NSC")) { if (avs::game::is_model("NSC")) {
// get buttons // get buttons
auto &buttons = games::scotto::get_buttons(); auto &buttons = games::scotto::get_buttons();
if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[input_offset + 1] |= 0x20; STATUS_BUFFER[input_offset + 1] |= 0x20;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[input_offset + 1] |= 0x10; STATUS_BUFFER[input_offset + 1] |= 0x10;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::CoinMech)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::CoinMech)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[input_offset + 1] |= 0x04; STATUS_BUFFER[input_offset + 1] |= 0x04;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Start)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Start)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[input_offset + 9] |= 0x20; STATUS_BUFFER[input_offset + 9] |= 0x20;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Up)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Up)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[input_offset + 9] |= 0x10; STATUS_BUFFER[input_offset + 9] |= 0x10;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Down)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::scotto::Buttons::Down)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[input_offset + 9] |= 0x08; STATUS_BUFFER[input_offset + 9] |= 0x08;
} }
// the code also checks `input_offset + 9` for 0x01 but that does not trigger any response // the code also checks `input_offset + 9` for 0x01 but that does not trigger any response
// in the "I/O CHECK" scene // in the "I/O CHECK" scene
} }
// success // success
return true; return true;
} }
static void __cdecl ac_io_kfca_watchdog_off() { static void __cdecl ac_io_kfca_watchdog_off() {
} }
// yes this is spelled "marge" instead of "merge" // yes this is spelled "marge" instead of "merge"
static int __cdecl ac_io_kfca_set_status_marge_func(void *cb) { static int __cdecl ac_io_kfca_set_status_marge_func(void *cb) {
return 1; return 1;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::KFCAModule::KFCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KFCA", module, hookMode) { acio::KFCAModule::KFCAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KFCA", module, hookMode) {
this->status_buffer = STATUS_BUFFER; this->status_buffer = STATUS_BUFFER;
this->status_buffer_size = sizeof(STATUS_BUFFER); this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
} }
void acio::KFCAModule::attach() { void acio::KFCAModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_kfca_control_button_led); ACIO_MODULE_HOOK(ac_io_kfca_control_button_led);
ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_close); ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_close);
ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_open); ACIO_MODULE_HOOK(ac_io_kfca_control_coin_blocker_open);
ACIO_MODULE_HOOK(ac_io_kfca_control_led_bright); ACIO_MODULE_HOOK(ac_io_kfca_control_led_bright);
ACIO_MODULE_HOOK(ac_io_kfca_current_coinstock); ACIO_MODULE_HOOK(ac_io_kfca_current_coinstock);
ACIO_MODULE_HOOK(ac_io_kfca_get_control_status_buffer); ACIO_MODULE_HOOK(ac_io_kfca_get_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_kfca_lock_coincounter); ACIO_MODULE_HOOK(ac_io_kfca_lock_coincounter);
ACIO_MODULE_HOOK(ac_io_kfca_req_volume_control); ACIO_MODULE_HOOK(ac_io_kfca_req_volume_control);
ACIO_MODULE_HOOK(ac_io_kfca_set_watchdog_time); ACIO_MODULE_HOOK(ac_io_kfca_set_watchdog_time);
ACIO_MODULE_HOOK(ac_io_kfca_unlock_coincounter); ACIO_MODULE_HOOK(ac_io_kfca_unlock_coincounter);
ACIO_MODULE_HOOK(ac_io_kfca_update_control_status_buffer); ACIO_MODULE_HOOK(ac_io_kfca_update_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_kfca_watchdog_off); ACIO_MODULE_HOOK(ac_io_kfca_watchdog_off);
ACIO_MODULE_HOOK(ac_io_kfca_set_status_marge_func); ACIO_MODULE_HOOK(ac_io_kfca_set_status_marge_func);
} }
+18 -18
View File
@@ -1,18 +1,18 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
extern uint8_t KFCA_VOL_SOUND; extern uint8_t KFCA_VOL_SOUND;
extern uint8_t KFCA_VOL_HEADPHONE; extern uint8_t KFCA_VOL_HEADPHONE;
extern uint8_t KFCA_VOL_EXTERNAL; extern uint8_t KFCA_VOL_EXTERNAL;
extern uint8_t KFCA_VOL_WOOFER; extern uint8_t KFCA_VOL_WOOFER;
class KFCAModule : public ACIOModule { class KFCAModule : public ACIOModule {
public: public:
KFCAModule(HMODULE module, HookMode hookMode); KFCAModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+238 -238
View File
@@ -1,238 +1,238 @@
#include "klpa.h" #include "klpa.h"
#include "avs/game.h" #include "avs/game.h"
#include "games/loveplus/io.h" #include "games/loveplus/io.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "rawinput/rawinput.h" #include "rawinput/rawinput.h"
#include "util/utils.h" #include "util/utils.h"
using namespace GameAPI; using namespace GameAPI;
static uint8_t STATUS_BUFFER[48]; static uint8_t STATUS_BUFFER[48];
static bool STATUS_BUFFER_FREEZE = false; static bool STATUS_BUFFER_FREEZE = false;
static const size_t LOVEPLUS_LIGHTS_MAPPING[] = { static const size_t LOVEPLUS_LIGHTS_MAPPING[] = {
games::loveplus::Lights::Red, games::loveplus::Lights::Red,
games::loveplus::Lights::Green, games::loveplus::Lights::Green,
games::loveplus::Lights::Blue, games::loveplus::Lights::Blue,
SIZE_MAX, SIZE_MAX,
games::loveplus::Lights::Right, games::loveplus::Lights::Right,
games::loveplus::Lights::Left, games::loveplus::Lights::Left,
}; };
static char __cdecl ac_io_klpa_consume_coinstock(int a1, DWORD *a2) { static char __cdecl ac_io_klpa_consume_coinstock(int a1, DWORD *a2) {
*a2 = (DWORD) eamuse_coin_get_stock(); *a2 = (DWORD) eamuse_coin_get_stock();
return 1; return 1;
} }
static int __cdecl ac_io_klpa_control_coin_blocker_close(int a1) { static int __cdecl ac_io_klpa_control_coin_blocker_close(int a1) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return 1; return 1;
} }
static int __cdecl ac_io_klpa_control_coin_blocker_open(int a1) { static int __cdecl ac_io_klpa_control_coin_blocker_open(int a1) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return 1; return 1;
} }
static int __cdecl ac_io_klpa_control_led_off(size_t index) { static int __cdecl ac_io_klpa_control_led_off(size_t index) {
// LovePlus // LovePlus
if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) {
// get lights // get lights
auto &lights = games::loveplus::get_lights(); auto &lights = games::loveplus::get_lights();
if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) {
Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 0.f); Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 0.f);
} }
} }
// return success // return success
return 1; return 1;
} }
static int __cdecl ac_io_klpa_control_led_on(size_t index) { static int __cdecl ac_io_klpa_control_led_on(size_t index) {
// LovePlus // LovePlus
if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) {
// get lights // get lights
auto &lights = games::loveplus::get_lights(); auto &lights = games::loveplus::get_lights();
if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) {
Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 1.f); Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), 1.f);
} }
} }
// return success // return success
return 1; return 1;
} }
static bool __cdecl ac_io_klpa_create_get_status_thread() { static bool __cdecl ac_io_klpa_create_get_status_thread() {
return 1; return 1;
} }
static char __cdecl ac_io_klpa_current_coinstock(int a1, DWORD *a2) { static char __cdecl ac_io_klpa_current_coinstock(int a1, DWORD *a2) {
// check bounds // check bounds
if (a1 < 0 || a1 >= 2) { if (a1 < 0 || a1 >= 2) {
return 0; return 0;
} }
*a2 = (DWORD) eamuse_coin_get_stock(); *a2 = (DWORD) eamuse_coin_get_stock();
// return success // return success
return 1; return 1;
} }
static bool __cdecl ac_io_klpa_destroy_get_status_thread() { static bool __cdecl ac_io_klpa_destroy_get_status_thread() {
return 1; return 1;
} }
static void* __cdecl ac_io_klpa_get_control_status_buffer(void *a1) { static void* __cdecl ac_io_klpa_get_control_status_buffer(void *a1) {
// copy buffer // copy buffer
return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER)); return memcpy(a1, STATUS_BUFFER, sizeof(STATUS_BUFFER));
} }
static void __cdecl ac_io_klpa_get_io_command_mode(void *a1) { static void __cdecl ac_io_klpa_get_io_command_mode(void *a1) {
memset(a1, 0, 4); memset(a1, 0, 4);
} }
static int __cdecl ac_io_klpa_led_reset() { static int __cdecl ac_io_klpa_led_reset() {
if (avs::game::is_model("KLP")) { if (avs::game::is_model("KLP")) {
// get lights // get lights
auto &lights = games::loveplus::get_lights(); auto &lights = games::loveplus::get_lights();
for (const auto &mapping : LOVEPLUS_LIGHTS_MAPPING) { for (const auto &mapping : LOVEPLUS_LIGHTS_MAPPING) {
if (mapping != SIZE_MAX) { if (mapping != SIZE_MAX) {
Lights::writeLight(RI_MGR, lights.at(mapping), 0.f); Lights::writeLight(RI_MGR, lights.at(mapping), 0.f);
} }
} }
} }
return 1; return 1;
} }
static int __cdecl ac_io_klpa_lock_coincounter(int a1) { static int __cdecl ac_io_klpa_lock_coincounter(int a1) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return 1; return 1;
} }
static bool __cdecl ac_io_klpa_set_io_command_mode(int a1) { static bool __cdecl ac_io_klpa_set_io_command_mode(int a1) {
return true; return true;
} }
static bool __cdecl ac_io_klpa_set_io_command_mode_is_finished(uint8_t *a1) { static bool __cdecl ac_io_klpa_set_io_command_mode_is_finished(uint8_t *a1) {
*a1 = 0; *a1 = 0;
return true; return true;
} }
static int __cdecl ac_io_klpa_set_led_bright(size_t index, uint8_t brightness) { static int __cdecl ac_io_klpa_set_led_bright(size_t index, uint8_t brightness) {
// LovePlus // LovePlus
if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) { if (avs::game::is_model("KLP") && index < std::size(LOVEPLUS_LIGHTS_MAPPING)) {
// get lights // get lights
auto &lights = games::loveplus::get_lights(); auto &lights = games::loveplus::get_lights();
if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) { if (LOVEPLUS_LIGHTS_MAPPING[index] != SIZE_MAX) {
Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), brightness / 127.f); Lights::writeLight(RI_MGR, lights.at(LOVEPLUS_LIGHTS_MAPPING[index]), brightness / 127.f);
} }
} }
return 1; return 1;
} }
static bool __cdecl ac_io_klpa_set_sound_mute(int a1) { static bool __cdecl ac_io_klpa_set_sound_mute(int a1) {
return true; return true;
} }
static bool __cdecl ac_io_klpa_set_sound_mute_is_finished(int a1) { static bool __cdecl ac_io_klpa_set_sound_mute_is_finished(int a1) {
return true; return true;
} }
static bool __cdecl ac_io_klpa_set_watchdog_time(short a1) { static bool __cdecl ac_io_klpa_set_watchdog_time(short a1) {
return true; return true;
} }
static char __cdecl ac_io_klpa_unlock_coincounter(int a1) { static char __cdecl ac_io_klpa_unlock_coincounter(int a1) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return 1; return 1;
} }
static bool __cdecl ac_io_klpa_update_control_status_buffer() { static bool __cdecl ac_io_klpa_update_control_status_buffer() {
// check freeze // check freeze
if (STATUS_BUFFER_FREEZE) { if (STATUS_BUFFER_FREEZE) {
return true; return true;
} }
// reset buffer // reset buffer
memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER));
// LovePlus // LovePlus
if (avs::game::is_model("KLP")) { if (avs::game::is_model("KLP")) {
// get buttons // get buttons
auto &buttons = games::loveplus::get_buttons(); auto &buttons = games::loveplus::get_buttons();
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Test)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[5] |= 1 << 5; STATUS_BUFFER[5] |= 1 << 5;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Service)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[5] |= 1 << 4; STATUS_BUFFER[5] |= 1 << 4;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Left)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Left)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[12] |= 1 << 6; STATUS_BUFFER[12] |= 1 << 6;
} }
if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Right)) == Buttons::State::BUTTON_PRESSED) { if (Buttons::getState(RI_MGR, buttons.at(games::loveplus::Buttons::Right)) == Buttons::State::BUTTON_PRESSED) {
STATUS_BUFFER[12] |= 1 << 7; STATUS_BUFFER[12] |= 1 << 7;
} }
// x[9] & 0x3F) = volume output level? // x[9] & 0x3F) = volume output level?
// x[11] & 0x3F) = volume output level? // x[11] & 0x3F) = volume output level?
// x[12] |= (1 << 4) = headphone jack // x[12] |= (1 << 4) = headphone jack
} }
// success // success
return true; return true;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::KLPAModule::KLPAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KLPA", module, hookMode) { acio::KLPAModule::KLPAModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("KLPA", module, hookMode) {
this->status_buffer = STATUS_BUFFER; this->status_buffer = STATUS_BUFFER;
this->status_buffer_size = sizeof(STATUS_BUFFER); this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
} }
void acio::KLPAModule::attach() { void acio::KLPAModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_klpa_consume_coinstock); ACIO_MODULE_HOOK(ac_io_klpa_consume_coinstock);
ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_close); ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_close);
ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_open); ACIO_MODULE_HOOK(ac_io_klpa_control_coin_blocker_open);
ACIO_MODULE_HOOK(ac_io_klpa_control_led_off); ACIO_MODULE_HOOK(ac_io_klpa_control_led_off);
ACIO_MODULE_HOOK(ac_io_klpa_control_led_on); ACIO_MODULE_HOOK(ac_io_klpa_control_led_on);
ACIO_MODULE_HOOK(ac_io_klpa_create_get_status_thread); ACIO_MODULE_HOOK(ac_io_klpa_create_get_status_thread);
ACIO_MODULE_HOOK(ac_io_klpa_current_coinstock); ACIO_MODULE_HOOK(ac_io_klpa_current_coinstock);
ACIO_MODULE_HOOK(ac_io_klpa_destroy_get_status_thread); ACIO_MODULE_HOOK(ac_io_klpa_destroy_get_status_thread);
ACIO_MODULE_HOOK(ac_io_klpa_get_control_status_buffer); ACIO_MODULE_HOOK(ac_io_klpa_get_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_klpa_get_io_command_mode); ACIO_MODULE_HOOK(ac_io_klpa_get_io_command_mode);
ACIO_MODULE_HOOK(ac_io_klpa_led_reset); ACIO_MODULE_HOOK(ac_io_klpa_led_reset);
ACIO_MODULE_HOOK(ac_io_klpa_lock_coincounter); ACIO_MODULE_HOOK(ac_io_klpa_lock_coincounter);
ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode); ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode);
ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode_is_finished); ACIO_MODULE_HOOK(ac_io_klpa_set_io_command_mode_is_finished);
ACIO_MODULE_HOOK(ac_io_klpa_set_led_bright); ACIO_MODULE_HOOK(ac_io_klpa_set_led_bright);
ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute); ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute);
ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute_is_finished); ACIO_MODULE_HOOK(ac_io_klpa_set_sound_mute_is_finished);
ACIO_MODULE_HOOK(ac_io_klpa_set_watchdog_time); ACIO_MODULE_HOOK(ac_io_klpa_set_watchdog_time);
ACIO_MODULE_HOOK(ac_io_klpa_unlock_coincounter); ACIO_MODULE_HOOK(ac_io_klpa_unlock_coincounter);
ACIO_MODULE_HOOK(ac_io_klpa_update_control_status_buffer); ACIO_MODULE_HOOK(ac_io_klpa_update_control_status_buffer);
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class KLPAModule : public ACIOModule { class KLPAModule : public ACIOModule {
public: public:
KLPAModule(HMODULE module, HookMode hookMode); KLPAModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class MDXFModule : public ACIOModule { class MDXFModule : public ACIOModule {
public: public:
MDXFModule(HMODULE module, HookMode hookMode); MDXFModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+55 -55
View File
@@ -1,55 +1,55 @@
#pragma once #pragma once
#include <string> #include <string>
#include <windows.h> #include <windows.h>
// macro for lazy typing of hooks // macro for lazy typing of hooks
#define ACIO_MODULE_HOOK(f) this->hook(reinterpret_cast<void *>(f), #f) #define ACIO_MODULE_HOOK(f) this->hook(reinterpret_cast<void *>(f), #f)
namespace acio { namespace acio {
/* /*
* Hook Modes * Hook Modes
* Since some versions can't handle inline hooking * Since some versions can't handle inline hooking
*/ */
enum class HookMode { enum class HookMode {
INLINE, INLINE,
IAT IAT
}; };
// this makes logging easier // this makes logging easier
const char *hook_mode_str(HookMode hook_mode); const char *hook_mode_str(HookMode hook_mode);
/* /*
* The ACIO module itself * The ACIO module itself
* Inherit this for extending our libacio implementation * Inherit this for extending our libacio implementation
*/ */
class ACIOModule { class ACIOModule {
protected: protected:
// the magic // the magic
void hook(void* func, const char *func_name); void hook(void* func, const char *func_name);
public: public:
ACIOModule(std::string name, HMODULE module, HookMode hook_mode) : ACIOModule(std::string name, HMODULE module, HookMode hook_mode) :
name(std::move(name)), name(std::move(name)),
module(module), module(module),
hook_mode(hook_mode) {}; hook_mode(hook_mode) {};
virtual ~ACIOModule() = default; virtual ~ACIOModule() = default;
virtual void attach(); virtual void attach();
// settings // settings
std::string name; std::string name;
HMODULE module; HMODULE module;
HookMode hook_mode; HookMode hook_mode;
bool attached = false; bool attached = false;
// buffer state (optional) // buffer state (optional)
uint8_t *status_buffer = nullptr; uint8_t *status_buffer = nullptr;
size_t status_buffer_size = 0; size_t status_buffer_size = 0;
bool *status_buffer_freeze = nullptr; bool *status_buffer_freeze = nullptr;
}; };
} }
+64 -64
View File
@@ -1,64 +1,64 @@
#include "nddb.h" #include "nddb.h"
#include "avs/game.h" #include "avs/game.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "util/utils.h" #include "util/utils.h"
// static stuff // static stuff
static uint8_t STATUS_BUFFER[4] {}; static uint8_t STATUS_BUFFER[4] {};
static bool STATUS_BUFFER_FREEZE = false; static bool STATUS_BUFFER_FREEZE = false;
/* /*
* Implementations * Implementations
*/ */
static void __cdecl ac_io_nddb_control_pwm(int a1, int a2) { static void __cdecl ac_io_nddb_control_pwm(int a1, int a2) {
log_misc("acio::nddb", "ac_io_nddb_control_pwm({}, {})", a1, a2); log_misc("acio::nddb", "ac_io_nddb_control_pwm({}, {})", a1, a2);
} }
static void __cdecl ac_io_nddb_control_solenoide(int a1, int a2) { static void __cdecl ac_io_nddb_control_solenoide(int a1, int a2) {
log_misc("acio::nddb", "ac_io_nddb_control_solenoide({}, {})", a1, a2); log_misc("acio::nddb", "ac_io_nddb_control_solenoide({}, {})", a1, a2);
} }
static bool __cdecl ac_io_nddb_create_get_status_thread() { static bool __cdecl ac_io_nddb_create_get_status_thread() {
return true; return true;
} }
static bool __cdecl ac_io_nddb_destroy_get_status_thread() { static bool __cdecl ac_io_nddb_destroy_get_status_thread() {
return true; return true;
} }
static void __cdecl ac_io_nddb_get_control_status_buffer(void *buffer) { static void __cdecl ac_io_nddb_get_control_status_buffer(void *buffer) {
} }
static bool __cdecl ac_io_nddb_req_solenoide_control(uint8_t *buffer) { static bool __cdecl ac_io_nddb_req_solenoide_control(uint8_t *buffer) {
log_misc("acio::nddb", "ac_io_nddb_req_solenoide_control"); log_misc("acio::nddb", "ac_io_nddb_req_solenoide_control");
return true; return true;
} }
static bool __cdecl ac_io_nddb_update_control_status_buffer() { static bool __cdecl ac_io_nddb_update_control_status_buffer() {
return true; return true;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::NDDBModule::NDDBModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("NDDB", module, hookMode) { acio::NDDBModule::NDDBModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("NDDB", module, hookMode) {
this->status_buffer = STATUS_BUFFER; this->status_buffer = STATUS_BUFFER;
this->status_buffer_size = sizeof(STATUS_BUFFER); this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
} }
void acio::NDDBModule::attach() { void acio::NDDBModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
ACIO_MODULE_HOOK(ac_io_nddb_control_pwm); ACIO_MODULE_HOOK(ac_io_nddb_control_pwm);
ACIO_MODULE_HOOK(ac_io_nddb_control_solenoide); ACIO_MODULE_HOOK(ac_io_nddb_control_solenoide);
ACIO_MODULE_HOOK(ac_io_nddb_create_get_status_thread); ACIO_MODULE_HOOK(ac_io_nddb_create_get_status_thread);
ACIO_MODULE_HOOK(ac_io_nddb_destroy_get_status_thread); ACIO_MODULE_HOOK(ac_io_nddb_destroy_get_status_thread);
ACIO_MODULE_HOOK(ac_io_nddb_get_control_status_buffer); ACIO_MODULE_HOOK(ac_io_nddb_get_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_nddb_req_solenoide_control); ACIO_MODULE_HOOK(ac_io_nddb_req_solenoide_control);
ACIO_MODULE_HOOK(ac_io_nddb_update_control_status_buffer); ACIO_MODULE_HOOK(ac_io_nddb_update_control_status_buffer);
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class NDDBModule : public ACIOModule { class NDDBModule : public ACIOModule {
public: public:
NDDBModule(HMODULE module, HookMode hookMode); NDDBModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class PANBModule : public ACIOModule { class PANBModule : public ACIOModule {
public: public:
PANBModule(HMODULE module, HookMode hookMode); PANBModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+520 -520
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class PIXModule : public ACIOModule { class PIXModule : public ACIOModule {
public: public:
PIXModule(HMODULE module, HookMode hookMode); PIXModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class PJECModule : public ACIOModule { class PJECModule : public ACIOModule {
public: public:
PJECModule(HMODULE module, HookMode hookMode); PJECModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+223 -223
View File
@@ -1,223 +1,223 @@
#include "pjei.h" #include "pjei.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
#include "rawinput/rawinput.h" #include "rawinput/rawinput.h"
#include "util/utils.h" #include "util/utils.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "games/we/io.h" #include "games/we/io.h"
#include "avs/game.h" #include "avs/game.h"
//using namespace GameAPI; //using namespace GameAPI;
// static stuff // static stuff
static uint8_t STATUS_BUFFER[40]; static uint8_t STATUS_BUFFER[40];
static bool STATUS_BUFFER_FREEZE = false; static bool STATUS_BUFFER_FREEZE = false;
/* /*
* Implementations * Implementations
*/ */
static bool __cdecl ac_io_pjei_current_coinstock(int a1, uint32_t *coinstock) { static bool __cdecl ac_io_pjei_current_coinstock(int a1, uint32_t *coinstock) {
*coinstock = eamuse_coin_get_stock(); *coinstock = eamuse_coin_get_stock();
return true; return true;
} }
static bool __cdecl ac_io_pjei_consume_coinstock(int a1, uint32_t amount) { static bool __cdecl ac_io_pjei_consume_coinstock(int a1, uint32_t amount) {
return eamuse_coin_consume(amount); return eamuse_coin_consume(amount);
} }
static bool __cdecl ac_io_pjei_get_softwareid(char *dst) { static bool __cdecl ac_io_pjei_get_softwareid(char *dst) {
static char DATA[] = "0140FFFFFFFFFFFFFFFF"; static char DATA[] = "0140FFFFFFFFFFFFFFFF";
memcpy(dst, DATA, sizeof(DATA)); memcpy(dst, DATA, sizeof(DATA));
return true; return true;
} }
static bool __cdecl ac_io_pjei_get_systemid(char *dst) { static bool __cdecl ac_io_pjei_get_systemid(char *dst) {
static char DATA[] = "0140FFFFFFFFFFFFFFFF"; static char DATA[] = "0140FFFFFFFFFFFFFFFF";
memcpy(dst, DATA, sizeof(DATA)); memcpy(dst, DATA, sizeof(DATA));
return true; return true;
} }
static bool __cdecl ac_io_pjei_update_control_status_buffer() { static bool __cdecl ac_io_pjei_update_control_status_buffer() {
// check freeze // check freeze
if (STATUS_BUFFER_FREEZE) { if (STATUS_BUFFER_FREEZE) {
return true; return true;
} }
// clear buffer // clear buffer
memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER)); memset(STATUS_BUFFER, 0, sizeof(STATUS_BUFFER));
// Winning Eleven // Winning Eleven
if (avs::game::is_model({ "KCK", "NCK" })) { if (avs::game::is_model({ "KCK", "NCK" })) {
// get buttons // get buttons
auto &buttons = games::we::get_buttons(); auto &buttons = games::we::get_buttons();
// apply buttons // apply buttons
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Service])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Service])) {
STATUS_BUFFER[16] |= 0x10; STATUS_BUFFER[16] |= 0x10;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Test])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Test])) {
STATUS_BUFFER[16] |= 0x20; STATUS_BUFFER[16] |= 0x20;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::CoinMech])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::CoinMech])) {
STATUS_BUFFER[16] |= 0x04; STATUS_BUFFER[16] |= 0x04;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Start])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Start])) {
STATUS_BUFFER[4] |= 0x80; STATUS_BUFFER[4] |= 0x80;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Up])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Up])) {
STATUS_BUFFER[4] |= 0x40; STATUS_BUFFER[4] |= 0x40;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Down])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Down])) {
STATUS_BUFFER[4] |= 0x20; STATUS_BUFFER[4] |= 0x20;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Left])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Left])) {
STATUS_BUFFER[4] |= 0x10; STATUS_BUFFER[4] |= 0x10;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Right])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::Right])) {
STATUS_BUFFER[4] |= 0x08; STATUS_BUFFER[4] |= 0x08;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonA])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonA])) {
STATUS_BUFFER[4] |= 0x04; STATUS_BUFFER[4] |= 0x04;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonB])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonB])) {
STATUS_BUFFER[4] |= 0x02; STATUS_BUFFER[4] |= 0x02;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonC])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonC])) {
STATUS_BUFFER[4] |= 0x01; STATUS_BUFFER[4] |= 0x01;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonD])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonD])) {
STATUS_BUFFER[6] |= 0x80; STATUS_BUFFER[6] |= 0x80;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonE])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonE])) {
STATUS_BUFFER[6] |= 0x40; STATUS_BUFFER[6] |= 0x40;
} }
if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonF])) { if (GameAPI::Buttons::getState(RI_MGR, buttons[games::we::Buttons::ButtonF])) {
STATUS_BUFFER[6] |= 0x20; STATUS_BUFFER[6] |= 0x20;
} }
} }
// success // success
return true; return true;
} }
static bool ac_io_pjei_get_control_status_buffer(uint8_t *buffer) { static bool ac_io_pjei_get_control_status_buffer(uint8_t *buffer) {
memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER)); memcpy(buffer, STATUS_BUFFER, sizeof(STATUS_BUFFER));
return true; return true;
} }
static bool __cdecl ac_io_pjei_req_secplug_check() { static bool __cdecl ac_io_pjei_req_secplug_check() {
return true; return true;
} }
static bool __cdecl ac_io_pjei_req_secplug_check_isfinished() { static bool __cdecl ac_io_pjei_req_secplug_check_isfinished() {
return true; return true;
} }
static bool __cdecl ac_io_pjei_req_secplug_missing_check() { static bool __cdecl ac_io_pjei_req_secplug_missing_check() {
return true; return true;
} }
static bool __cdecl ac_io_pjei_req_secplug_missing_check_isfinished() { static bool __cdecl ac_io_pjei_req_secplug_missing_check_isfinished() {
return true; return true;
} }
static bool __cdecl ac_io_pjei_lock_coincounter(int a1) { static bool __cdecl ac_io_pjei_lock_coincounter(int a1) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return true; return true;
} }
static bool __cdecl ac_io_pjei_unlock_coincounter(int a1) { static bool __cdecl ac_io_pjei_unlock_coincounter(int a1) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return true; return true;
} }
static bool __cdecl ac_io_pjei_control_coin_blocker_on(bool a1) { static bool __cdecl ac_io_pjei_control_coin_blocker_on(bool a1) {
eamuse_coin_set_block(true); eamuse_coin_set_block(true);
return true; return true;
} }
static bool __cdecl ac_io_pjei_control_coin_blocker_off(bool a1) { static bool __cdecl ac_io_pjei_control_coin_blocker_off(bool a1) {
eamuse_coin_set_block(false); eamuse_coin_set_block(false);
return true; return true;
} }
/* /*
* Helper method for easily setting the light values * Helper method for easily setting the light values
*/ */
static void ac_io_pjei_control_lamp_set(uint8_t lamp_bits, uint8_t brightness) { static void ac_io_pjei_control_lamp_set(uint8_t lamp_bits, uint8_t brightness) {
auto &lights = games::we::get_lights(); auto &lights = games::we::get_lights();
float value = CLAMP(brightness / 31.f, 0.f, 1.f); float value = CLAMP(brightness / 31.f, 0.f, 1.f);
if (lamp_bits & 0x20) { if (lamp_bits & 0x20) {
GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftRed], value); GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftRed], value);
} }
if (lamp_bits & 0x10) { if (lamp_bits & 0x10) {
GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftGreen], value); GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftGreen], value);
} }
if (lamp_bits & 0x08) { if (lamp_bits & 0x08) {
GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftBlue], value); GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::LeftBlue], value);
} }
if (lamp_bits & 0x04) { if (lamp_bits & 0x04) {
GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightRed], value); GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightRed], value);
} }
if (lamp_bits & 0x02) { if (lamp_bits & 0x02) {
GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightGreen], value); GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightGreen], value);
} }
if (lamp_bits & 0x01) { if (lamp_bits & 0x01) {
GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightBlue], value); GameAPI::Lights::writeLight(RI_MGR, lights[games::we::Lights::RightBlue], value);
} }
} }
static bool __cdecl ac_io_pjei_control_lamp_on(uint8_t lamp_bits) { static bool __cdecl ac_io_pjei_control_lamp_on(uint8_t lamp_bits) {
ac_io_pjei_control_lamp_set(lamp_bits, 31); ac_io_pjei_control_lamp_set(lamp_bits, 31);
return true; return true;
} }
static bool __cdecl ac_io_pjei_control_lamp_off(uint8_t lamp_bits) { static bool __cdecl ac_io_pjei_control_lamp_off(uint8_t lamp_bits) {
ac_io_pjei_control_lamp_set(lamp_bits, 0); ac_io_pjei_control_lamp_set(lamp_bits, 0);
return true; return true;
} }
static bool __cdecl ac_io_pjei_control_lamp_bright(uint8_t lamp_bit, uint8_t brightness) { static bool __cdecl ac_io_pjei_control_lamp_bright(uint8_t lamp_bit, uint8_t brightness) {
ac_io_pjei_control_lamp_set(lamp_bit, brightness); ac_io_pjei_control_lamp_set(lamp_bit, brightness);
return true; return true;
} }
static bool __cdecl ac_io_pjei_control_lamp_mode(int mode) { static bool __cdecl ac_io_pjei_control_lamp_mode(int mode) {
// mode -> [0,1] (0 is static, 1 is brightness?) // mode -> [0,1] (0 is static, 1 is brightness?)
return true; return true;
} }
/* /*
* Module stuff * Module stuff
*/ */
acio::PJEIModule::PJEIModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PJEI", module, hookMode) { acio::PJEIModule::PJEIModule(HMODULE module, acio::HookMode hookMode) : ACIOModule("PJEI", module, hookMode) {
this->status_buffer = STATUS_BUFFER; this->status_buffer = STATUS_BUFFER;
this->status_buffer_size = sizeof(STATUS_BUFFER); this->status_buffer_size = sizeof(STATUS_BUFFER);
this->status_buffer_freeze = &STATUS_BUFFER_FREEZE; this->status_buffer_freeze = &STATUS_BUFFER_FREEZE;
} }
void acio::PJEIModule::attach() { void acio::PJEIModule::attach() {
ACIOModule::attach(); ACIOModule::attach();
// hooks // hooks
ACIO_MODULE_HOOK(ac_io_pjei_current_coinstock); ACIO_MODULE_HOOK(ac_io_pjei_current_coinstock);
ACIO_MODULE_HOOK(ac_io_pjei_consume_coinstock); ACIO_MODULE_HOOK(ac_io_pjei_consume_coinstock);
ACIO_MODULE_HOOK(ac_io_pjei_get_softwareid); ACIO_MODULE_HOOK(ac_io_pjei_get_softwareid);
ACIO_MODULE_HOOK(ac_io_pjei_get_systemid); ACIO_MODULE_HOOK(ac_io_pjei_get_systemid);
ACIO_MODULE_HOOK(ac_io_pjei_update_control_status_buffer); ACIO_MODULE_HOOK(ac_io_pjei_update_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_pjei_get_control_status_buffer); ACIO_MODULE_HOOK(ac_io_pjei_get_control_status_buffer);
ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check); ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check);
ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check_isfinished); ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_check_isfinished);
ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check); ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check);
ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check_isfinished); ACIO_MODULE_HOOK(ac_io_pjei_req_secplug_missing_check_isfinished);
ACIO_MODULE_HOOK(ac_io_pjei_lock_coincounter); ACIO_MODULE_HOOK(ac_io_pjei_lock_coincounter);
ACIO_MODULE_HOOK(ac_io_pjei_unlock_coincounter); ACIO_MODULE_HOOK(ac_io_pjei_unlock_coincounter);
ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_on); ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_on);
ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_off); ACIO_MODULE_HOOK(ac_io_pjei_control_coin_blocker_off);
ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_on); ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_on);
ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_off); ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_off);
ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_bright); ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_bright);
ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_mode); ACIO_MODULE_HOOK(ac_io_pjei_control_lamp_mode);
} }
+13 -13
View File
@@ -1,13 +1,13 @@
#pragma once #pragma once
#include "../module.h" #include "../module.h"
namespace acio { namespace acio {
class PJEIModule : public ACIOModule { class PJEIModule : public ACIOModule {
public: public:
PJEIModule(HMODULE module, HookMode hookMode); PJEIModule(HMODULE module, HookMode hookMode);
virtual void attach() override; virtual void attach() override;
}; };
} }
+205 -205
View File
@@ -1,205 +1,205 @@
#include "acioemu.h" #include "acioemu.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/utils.h" #include "util/utils.h"
using namespace acioemu; using namespace acioemu;
ACIOEmu::ACIOEmu() { ACIOEmu::ACIOEmu() {
this->devices = new std::vector<ACIODeviceEmu *>(); this->devices = new std::vector<ACIODeviceEmu *>();
this->response_buffer = new circular_buffer<uint8_t>(4096); this->response_buffer = new circular_buffer<uint8_t>(4096);
this->read_buffer = new circular_buffer<uint8_t>(1024); this->read_buffer = new circular_buffer<uint8_t>(1024);
} }
ACIOEmu::~ACIOEmu() { ACIOEmu::~ACIOEmu() {
// delete devices // delete devices
for (auto device : *this->devices) { for (auto device : *this->devices) {
delete device; delete device;
} }
delete this->devices; delete this->devices;
// delete buffers // delete buffers
delete this->response_buffer; delete this->response_buffer;
delete this->read_buffer; delete this->read_buffer;
} }
void ACIOEmu::add_device(ACIODeviceEmu *device) { void ACIOEmu::add_device(ACIODeviceEmu *device) {
this->devices->push_back(device); this->devices->push_back(device);
} }
void ACIOEmu::write(uint8_t byte) { void ACIOEmu::write(uint8_t byte) {
// insert into buffer // insert into buffer
if (!invert) { if (!invert) {
if (byte == ACIO_ESCAPE) { if (byte == ACIO_ESCAPE) {
invert = true; invert = true;
} else { } else {
this->read_buffer->put(byte); this->read_buffer->put(byte);
} }
} else { } else {
byte = ~byte; byte = ~byte;
invert = false; invert = false;
this->read_buffer->put(byte); this->read_buffer->put(byte);
} }
// clean garbage // clean garbage
while (!this->read_buffer->empty() && this->read_buffer->peek() != 0xAA) { while (!this->read_buffer->empty() && this->read_buffer->peek() != 0xAA) {
this->read_buffer->get(); this->read_buffer->get();
} }
while (this->read_buffer->size() > 1 && this->read_buffer->peek(1) == 0xAA) { while (this->read_buffer->size() > 1 && this->read_buffer->peek(1) == 0xAA) {
this->read_buffer->get(); this->read_buffer->get();
} }
// handshake counter // handshake counter
static unsigned int handshake_counter = 0; static unsigned int handshake_counter = 0;
if (byte == 0xAA) { if (byte == 0xAA) {
handshake_counter++; handshake_counter++;
} else { } else {
handshake_counter = 0; handshake_counter = 0;
} }
// check for handshake // check for handshake
if (handshake_counter > 1) { if (handshake_counter > 1) {
/* /*
* small hack - BIO2 seems to expect more bytes here - sending two bytes each time fixes it * small hack - BIO2 seems to expect more bytes here - sending two bytes each time fixes it
* TODO replace this handshake code with something better * TODO replace this handshake code with something better
*/ */
this->response_buffer->put(ACIO_SOF); this->response_buffer->put(ACIO_SOF);
this->response_buffer->put(ACIO_SOF); this->response_buffer->put(ACIO_SOF);
handshake_counter--; handshake_counter--;
return; return;
} }
// parse // parse
if (!this->read_buffer->empty() && this->read_buffer->size() >= 6) { if (!this->read_buffer->empty() && this->read_buffer->size() >= 6) {
bool is_complete = false; bool is_complete = false;
// check if broadcast // check if broadcast
if (this->read_buffer->peek(1) == ACIO_BROADCAST) { if (this->read_buffer->peek(1) == ACIO_BROADCAST) {
// check msg data size // check msg data size
auto data_size = this->read_buffer->peek(2); auto data_size = this->read_buffer->peek(2);
// check if msg is complete (SOF + checksum + broadcast header + data_size) // check if msg is complete (SOF + checksum + broadcast header + data_size)
is_complete = this->read_buffer->size() >= 2u + 2u + data_size; is_complete = this->read_buffer->size() >= 2u + 2u + data_size;
} else { } else {
// check msg data size // check msg data size
auto data_size = this->read_buffer->peek(5); auto data_size = this->read_buffer->peek(5);
// check if msg is complete (SOF + checksum + command header + data_size) // check if msg is complete (SOF + checksum + command header + data_size)
is_complete = this->read_buffer->size() >= 2u + MSG_HEADER_SIZE + data_size; is_complete = this->read_buffer->size() >= 2u + MSG_HEADER_SIZE + data_size;
} }
// parse message if complete // parse message if complete
if (is_complete) { if (is_complete) {
this->msg_parse(); this->msg_parse();
this->read_buffer->reset(); this->read_buffer->reset();
} }
} }
} }
std::optional<uint8_t> ACIOEmu::read() { std::optional<uint8_t> ACIOEmu::read() {
if (this->response_buffer->empty()) { if (this->response_buffer->empty()) {
return std::nullopt; return std::nullopt;
} }
return this->response_buffer->get(); return this->response_buffer->get();
} }
void ACIOEmu::msg_parse() { void ACIOEmu::msg_parse() {
#ifdef ACIOEMU_LOG #ifdef ACIOEMU_LOG
log_info("acioemu", "MSG RECV: {}", bin2hex(*this->read_buffer)); log_info("acioemu", "MSG RECV: {}", bin2hex(*this->read_buffer));
#endif #endif
// calculate checksum // calculate checksum
uint8_t chk = 0; uint8_t chk = 0;
size_t max = this->read_buffer->size() - 1; size_t max = this->read_buffer->size() - 1;
for (size_t i = 1; i < max; i++) { for (size_t i = 1; i < max; i++) {
chk += this->read_buffer->peek(i); chk += this->read_buffer->peek(i);
} }
// check checksum // check checksum
uint8_t chk_receive = this->read_buffer->peek(this->read_buffer->size() - 1); uint8_t chk_receive = this->read_buffer->peek(this->read_buffer->size() - 1);
if (chk != chk_receive) { if (chk != chk_receive) {
#ifdef ACIOEMU_LOG #ifdef ACIOEMU_LOG
log_info("acioemu", "detected wrong checksum: {}/{}", chk, chk_receive); log_info("acioemu", "detected wrong checksum: {}/{}", chk, chk_receive);
#endif #endif
return; return;
} }
// get message data // get message data
auto msg_data = this->read_buffer->peek_all(); auto msg_data = this->read_buffer->peek_all();
auto msg_in = (MessageData *) &msg_data[1]; auto msg_in = (MessageData *) &msg_data[1];
// correct cmd code endianness if this is not a broadcast // correct cmd code endianness if this is not a broadcast
if (msg_in->addr != ACIO_BROADCAST) { if (msg_in->addr != ACIO_BROADCAST) {
msg_in->cmd.code = acio_u16(msg_in->cmd.code); msg_in->cmd.code = acio_u16(msg_in->cmd.code);
} }
// pass to applicable device // pass to applicable device
uint8_t node_offset = 0; uint8_t node_offset = 0;
for (auto device : *this->devices) { for (auto device : *this->devices) {
if (device->is_applicable(node_offset, msg_in->addr)) { if (device->is_applicable(node_offset, msg_in->addr)) {
auto cur_offset = msg_in->addr - node_offset - 1; auto cur_offset = msg_in->addr - node_offset - 1;
if (cur_offset < 0) { if (cur_offset < 0) {
break; break;
} }
if (device->parse_msg(msg_in, this->response_buffer)) { if (device->parse_msg(msg_in, this->response_buffer)) {
return; return;
} else { } else {
break; break;
} }
} }
node_offset += device->node_count; node_offset += device->node_count;
} }
// ignore broadcast messages by default // ignore broadcast messages by default
if (msg_in->addr == ACIO_BROADCAST) { if (msg_in->addr == ACIO_BROADCAST) {
return; return;
} }
/* /*
* Default Behavior * Default Behavior
* If you want to do anything different, just handle the * If you want to do anything different, just handle the
* commands in your own device implementation. * commands in your own device implementation.
*/ */
switch (msg_in->cmd.code) { switch (msg_in->cmd.code) {
// node count report // node count report
case ACIO_CMD_ASSIGN_ADDRS: { case ACIO_CMD_ASSIGN_ADDRS: {
if (msg_in->addr == 0x00 && node_offset > 0) { if (msg_in->addr == 0x00 && node_offset > 0) {
auto msg = ACIODeviceEmu::create_msg(msg_in, 1, &node_offset); auto msg = ACIODeviceEmu::create_msg(msg_in, 1, &node_offset);
ACIODeviceEmu::write_msg(msg, this->response_buffer); ACIODeviceEmu::write_msg(msg, this->response_buffer);
delete msg; delete msg;
return; return;
} }
break; break;
} }
// status 0 defaults // status 0 defaults
case ACIO_CMD_CLEAR: case ACIO_CMD_CLEAR:
case ACIO_CMD_STARTUP: case ACIO_CMD_STARTUP:
case 0x80: // KEEPALIVE case 0x80: // KEEPALIVE
case 0xFF: // BROADCAST case 0xFF: // BROADCAST
{ {
// send status 0 // send status 0
auto msg = ACIODeviceEmu::create_msg_status(msg_in, 0); auto msg = ACIODeviceEmu::create_msg_status(msg_in, 0);
ACIODeviceEmu::write_msg(msg, response_buffer); ACIODeviceEmu::write_msg(msg, response_buffer);
delete msg; delete msg;
return; return;
} }
default: default:
break; break;
} }
#ifdef ACIOEMU_LOG #ifdef ACIOEMU_LOG
log_info("acioemu", "UNHANDLED MSG FOR ADDR: {}, CMD: 0x{:x}), DATA: {}", log_info("acioemu", "UNHANDLED MSG FOR ADDR: {}, CMD: 0x{:x}), DATA: {}",
msg_in->addr, msg_in->addr,
msg_in->cmd.code, msg_in->cmd.code,
bin2hex(*this->read_buffer)); bin2hex(*this->read_buffer));
#endif #endif
} }
+32 -32
View File
@@ -1,32 +1,32 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <vector> #include <vector>
#include "util/circular_buffer.h" #include "util/circular_buffer.h"
#include "device.h" #include "device.h"
#include "icca.h" #include "icca.h"
namespace acioemu { namespace acioemu {
class ACIOEmu { class ACIOEmu {
private: private:
std::vector<ACIODeviceEmu *> *devices; std::vector<ACIODeviceEmu *> *devices;
circular_buffer<uint8_t> *response_buffer; circular_buffer<uint8_t> *response_buffer;
circular_buffer<uint8_t> *read_buffer; circular_buffer<uint8_t> *read_buffer;
bool invert = false; bool invert = false;
void msg_parse(); void msg_parse();
public: public:
explicit ACIOEmu(); explicit ACIOEmu();
~ACIOEmu(); ~ACIOEmu();
void add_device(ACIODeviceEmu *device); void add_device(ACIODeviceEmu *device);
void write(uint8_t byte); void write(uint8_t byte);
std::optional<uint8_t> read(); std::optional<uint8_t> read();
}; };
} }
+80 -80
View File
@@ -1,80 +1,80 @@
#pragma once #pragma once
#include <ctime> #include <ctime>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <cstring> #include <cstring>
#include "device.h" #include "device.h"
#include "hooks/sleephook.h" #include "hooks/sleephook.h"
namespace acioemu { namespace acioemu {
#pragma pack(push, 1) #pragma pack(push, 1)
struct bio2_bi2a_state_in { struct bio2_bi2a_state_in {
uint8_t pad0[3]; uint8_t pad0[3];
uint8_t panel[4]; uint8_t panel[4];
uint8_t deck_switch[14]; uint8_t deck_switch[14];
uint8_t pad21[2]; uint8_t pad21[2];
uint8_t led_ticker[9]; uint8_t led_ticker[9];
uint8_t spot_light_1[4]; uint8_t spot_light_1[4];
uint8_t neon_light; uint8_t neon_light;
uint8_t spot_light_2[4]; uint8_t spot_light_2[4];
uint8_t pad41[7]; uint8_t pad41[7];
}; };
struct bio2_bi2a_status { struct bio2_bi2a_status {
uint8_t slider_1; uint8_t slider_1;
uint8_t system; uint8_t system;
uint8_t slider_2; uint8_t slider_2;
uint8_t pad3; uint8_t pad3;
uint8_t slider_3; uint8_t slider_3;
uint8_t pad5; uint8_t pad5;
uint8_t slider_4; uint8_t slider_4;
uint8_t slider_5; uint8_t slider_5;
uint8_t pad8; uint8_t pad8;
uint8_t panel; uint8_t panel;
uint8_t pad10[6]; uint8_t pad10[6];
uint8_t tt_p1; uint8_t tt_p1;
uint8_t tt_p2; uint8_t tt_p2;
uint8_t p1_s1; uint8_t p1_s1;
uint8_t pad20; uint8_t pad20;
uint8_t p1_s2; uint8_t p1_s2;
uint8_t pad22; uint8_t pad22;
uint8_t p1_s3; uint8_t p1_s3;
uint8_t pad24; uint8_t pad24;
uint8_t p1_s4; uint8_t p1_s4;
uint8_t pad26; uint8_t pad26;
uint8_t p1_s5; uint8_t p1_s5;
uint8_t pad28; uint8_t pad28;
uint8_t p1_s6; uint8_t p1_s6;
uint8_t pad30; uint8_t pad30;
uint8_t p1_s7; uint8_t p1_s7;
uint8_t pad32; uint8_t pad32;
uint8_t p2_s1; uint8_t p2_s1;
uint8_t pad34; uint8_t pad34;
uint8_t p2_s2; uint8_t p2_s2;
uint8_t pad36; uint8_t pad36;
uint8_t p2_s3; uint8_t p2_s3;
uint8_t pad38; uint8_t pad38;
uint8_t p2_s4; uint8_t p2_s4;
uint8_t pad40; uint8_t pad40;
}; };
#pragma pack(pop) #pragma pack(pop)
class BI2A : public ACIODeviceEmu { class BI2A : public ACIODeviceEmu {
private: private:
uint8_t coin_counter = 0; uint8_t coin_counter = 0;
public: public:
explicit BI2A(bool type_new, bool flip_order, bool keypad_thread, uint8_t node_count); explicit BI2A(bool type_new, bool flip_order, bool keypad_thread, uint8_t node_count);
~BI2A() override; ~BI2A() override;
bool parse_msg(unsigned int node_offset, bool parse_msg(unsigned int node_offset,
MessageData *msg_in, MessageData *msg_in,
circular_buffer<uint8_t> *response_buffer) override; circular_buffer<uint8_t> *response_buffer) override;
void update_card(int unit); void update_card(int unit);
void update_keypad(int unit, bool update_edge); void update_keypad(int unit, bool update_edge);
void update_status(int unit); void update_status(int unit);
}; };
} }
+118 -118
View File
@@ -1,118 +1,118 @@
#include "device.h" #include "device.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/utils.h" #include "util/utils.h"
using namespace acioemu; using namespace acioemu;
void ACIODeviceEmu::set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, void ACIODeviceEmu::set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid,
uint8_t data_size) uint8_t data_size)
{ {
// flag as response // flag as response
if (addr != 0) { if (addr != 0) {
addr |= ACIO_RESPONSE_FLAG; addr |= ACIO_RESPONSE_FLAG;
} }
// set header data // set header data
data->addr = addr; data->addr = addr;
data->cmd.code = acio_u16(code); data->cmd.code = acio_u16(code);
data->cmd.pid = pid; data->cmd.pid = pid;
data->cmd.data_size = data_size; data->cmd.data_size = data_size;
} }
void ACIODeviceEmu::set_version(MessageData* data, uint32_t type, uint8_t flag, void ACIODeviceEmu::set_version(MessageData* data, uint32_t type, uint8_t flag,
uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, std::string code) uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, std::string code)
{ {
// set version data // set version data
auto data_version = &data->cmd.data_version; auto data_version = &data->cmd.data_version;
data_version->type = type; data_version->type = type;
data_version->flag = flag; data_version->flag = flag;
data_version->ver_major = ver_major; data_version->ver_major = ver_major;
data_version->ver_minor = ver_minor; data_version->ver_minor = ver_minor;
data_version->ver_rev = ver_rev; data_version->ver_rev = ver_rev;
strncpy(data_version->code, code.c_str(), sizeof(data_version->code)); strncpy(data_version->code, code.c_str(), sizeof(data_version->code));
strncpy(data_version->date, __DATE__, sizeof(data_version->date)); strncpy(data_version->date, __DATE__, sizeof(data_version->date));
strncpy(data_version->time, __TIME__, sizeof(data_version->time)); strncpy(data_version->time, __TIME__, sizeof(data_version->time));
} }
MessageData *ACIODeviceEmu::create_msg(uint8_t addr, uint16_t code, uint8_t pid, size_t data_size, MessageData *ACIODeviceEmu::create_msg(uint8_t addr, uint16_t code, uint8_t pid, size_t data_size,
uint8_t *data) uint8_t *data)
{ {
// check data size // check data size
if (data_size > 0xFF) { if (data_size > 0xFF) {
log_warning("acio", "data size > 255: {}", data_size); log_warning("acio", "data size > 255: {}", data_size);
data_size = 0xFF; data_size = 0xFF;
} }
// allocate data // allocate data
auto data_raw = new uint8_t[MSG_HEADER_SIZE + data_size]; auto data_raw = new uint8_t[MSG_HEADER_SIZE + data_size];
// set header // set header
auto msg = (MessageData *) &data_raw[0]; auto msg = (MessageData *) &data_raw[0];
set_header(msg, addr, code, pid, (uint8_t) data_size); set_header(msg, addr, code, pid, (uint8_t) data_size);
// set data // set data
if (data) { if (data) {
memcpy(data_raw + MSG_HEADER_SIZE, data, data_size); memcpy(data_raw + MSG_HEADER_SIZE, data, data_size);
} else { } else {
memset(data_raw + MSG_HEADER_SIZE, 0, data_size); memset(data_raw + MSG_HEADER_SIZE, 0, data_size);
} }
// return prepared message // return prepared message
return msg; return msg;
} }
MessageData *ACIODeviceEmu::create_msg(MessageData *msg_in, size_t data_size, uint8_t *data) { MessageData *ACIODeviceEmu::create_msg(MessageData *msg_in, size_t data_size, uint8_t *data) {
return create_msg(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, data_size, data); return create_msg(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, data_size, data);
} }
MessageData *ACIODeviceEmu::create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status) { MessageData *ACIODeviceEmu::create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status) {
return create_msg(addr, code, pid, 1, &status); return create_msg(addr, code, pid, 1, &status);
} }
MessageData *ACIODeviceEmu::create_msg_status(MessageData *msg_in, uint8_t status) { MessageData *ACIODeviceEmu::create_msg_status(MessageData *msg_in, uint8_t status) {
return create_msg_status(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, status); return create_msg_status(msg_in->addr, msg_in->cmd.code, msg_in->cmd.pid, status);
} }
bool ACIODeviceEmu::is_applicable(uint8_t node_offset, uint8_t node) { bool ACIODeviceEmu::is_applicable(uint8_t node_offset, uint8_t node) {
return node > node_offset && node <= node_offset + this->node_count; return node > node_offset && node <= node_offset + this->node_count;
} }
void ACIODeviceEmu::write_msg(const uint8_t *data, size_t size, circular_buffer<uint8_t> *response_buffer) { void ACIODeviceEmu::write_msg(const uint8_t *data, size_t size, circular_buffer<uint8_t> *response_buffer) {
// header // header
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
response_buffer->put(ACIO_SOF); response_buffer->put(ACIO_SOF);
} }
// msg data and checksum // msg data and checksum
uint8_t b, chk = 0; uint8_t b, chk = 0;
for (size_t i = 0; i <= size; i++) { for (size_t i = 0; i <= size; i++) {
// set byte to data or checksum // set byte to data or checksum
if (i < size) { if (i < size) {
b = data[i]; b = data[i];
chk += b; chk += b;
} else { } else {
b = chk; b = chk;
} }
// check for escape // check for escape
if (b == ACIO_SOF || b == ACIO_ESCAPE) { if (b == ACIO_SOF || b == ACIO_ESCAPE) {
response_buffer->put(ACIO_ESCAPE); response_buffer->put(ACIO_ESCAPE);
response_buffer->put(~b); response_buffer->put(~b);
} else { } else {
response_buffer->put(b); response_buffer->put(b);
} }
} }
#ifdef ACIOEMU_LOG #ifdef ACIOEMU_LOG
log_info("acioemu", "ACIO MSG OUT: AA{}{:02X}", bin2hex(data, size), chk); log_info("acioemu", "ACIO MSG OUT: AA{}{:02X}", bin2hex(data, size), chk);
#endif #endif
} }
void ACIODeviceEmu::write_msg(MessageData *msg, circular_buffer<uint8_t> *response_buffer) { void ACIODeviceEmu::write_msg(MessageData *msg, circular_buffer<uint8_t> *response_buffer) {
auto data = reinterpret_cast<const uint8_t *>(msg); auto data = reinterpret_cast<const uint8_t *>(msg);
write_msg(data, MSG_HEADER_SIZE + msg->cmd.data_size, response_buffer); write_msg(data, MSG_HEADER_SIZE + msg->cmd.data_size, response_buffer);
} }
+103 -103
View File
@@ -1,103 +1,103 @@
#pragma once #pragma once
#include <string> #include <string>
#include "util/circular_buffer.h" #include "util/circular_buffer.h"
// convert big-endian to little-endian // convert big-endian to little-endian
#define acio_u16 _byteswap_ushort #define acio_u16 _byteswap_ushort
#define acio_u32 _byteswap_ulong #define acio_u32 _byteswap_ulong
namespace acioemu { namespace acioemu {
constexpr uint8_t ACIO_SOF = 0xAA; constexpr uint8_t ACIO_SOF = 0xAA;
constexpr uint8_t ACIO_ESCAPE = 0xFF; constexpr uint8_t ACIO_ESCAPE = 0xFF;
constexpr uint8_t ACIO_BROADCAST = 0x70; constexpr uint8_t ACIO_BROADCAST = 0x70;
constexpr uint8_t ACIO_RESPONSE_FLAG = 0x80; constexpr uint8_t ACIO_RESPONSE_FLAG = 0x80;
// general command codes // general command codes
enum acio_cmd_codes { enum acio_cmd_codes {
ACIO_CMD_ASSIGN_ADDRS = 0x0001, ACIO_CMD_ASSIGN_ADDRS = 0x0001,
ACIO_CMD_GET_VERSION = 0x0002, ACIO_CMD_GET_VERSION = 0x0002,
ACIO_CMD_STARTUP = 0x0003, ACIO_CMD_STARTUP = 0x0003,
ACIO_CMD_KEEPALIVE = 0x0080, ACIO_CMD_KEEPALIVE = 0x0080,
ACIO_CMD_CLEAR = 0x0100, ACIO_CMD_CLEAR = 0x0100,
}; };
// message structs // message structs
#pragma pack(push, 1) #pragma pack(push, 1)
struct VersionData { struct VersionData {
uint32_t type; uint32_t type;
uint8_t flag; uint8_t flag;
uint8_t ver_major; uint8_t ver_major;
uint8_t ver_minor; uint8_t ver_minor;
uint8_t ver_rev; uint8_t ver_rev;
char code[4]; char code[4];
char date[16]; char date[16];
char time[16]; char time[16];
}; };
struct MessageData { struct MessageData {
uint8_t addr; uint8_t addr;
union { union {
struct { struct {
uint16_t code; uint16_t code;
uint8_t pid; uint8_t pid;
uint8_t data_size; uint8_t data_size;
union { union {
uint8_t raw[0xFF]; uint8_t raw[0xFF];
uint8_t status; uint8_t status;
VersionData data_version; VersionData data_version;
}; };
} cmd; } cmd;
struct { struct {
uint8_t data_size; uint8_t data_size;
uint8_t raw[0xFF]; uint8_t raw[0xFF];
} broadcast; } broadcast;
}; };
}; };
#pragma pack(pop) #pragma pack(pop)
// message sizes // message sizes
constexpr size_t MSG_HEADER_SIZE = 5; constexpr size_t MSG_HEADER_SIZE = 5;
constexpr size_t MSG_VERSION_SIZE = sizeof(VersionData); constexpr size_t MSG_VERSION_SIZE = sizeof(VersionData);
class ACIODeviceEmu { class ACIODeviceEmu {
public: public:
// attributes // attributes
uint8_t node_count = 0; uint8_t node_count = 0;
/* /*
* Helper functions for getting/setting the message contents * Helper functions for getting/setting the message contents
*/ */
static void set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, uint8_t data_size); static void set_header(MessageData* data, uint8_t addr, uint16_t code, uint8_t pid, uint8_t data_size);
static void set_version(MessageData* data, uint32_t type, uint8_t flag, static void set_version(MessageData* data, uint32_t type, uint8_t flag,
uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev, uint8_t ver_major, uint8_t ver_minor, uint8_t ver_rev,
std::string code); std::string code);
/* /*
* This function creates a basic message with optional parameter data. * This function creates a basic message with optional parameter data.
* If data is set to null, the parameter data will be initialized with 0x00 * If data is set to null, the parameter data will be initialized with 0x00
*/ */
static MessageData* create_msg(uint8_t addr, uint16_t cmd, uint8_t pid, static MessageData* create_msg(uint8_t addr, uint16_t cmd, uint8_t pid,
size_t data_size, uint8_t *data = nullptr); size_t data_size, uint8_t *data = nullptr);
static MessageData* create_msg(MessageData* msg_in, size_t data_size, uint8_t *data = nullptr); static MessageData* create_msg(MessageData* msg_in, size_t data_size, uint8_t *data = nullptr);
/* /*
* Helper functions for generating messages * Helper functions for generating messages
*/ */
static MessageData* create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status); static MessageData* create_msg_status(uint8_t addr, uint16_t code, uint8_t pid, uint8_t status);
static MessageData* create_msg_status(MessageData* msg_in, uint8_t status); static MessageData* create_msg_status(MessageData* msg_in, uint8_t status);
virtual ~ACIODeviceEmu() = default; virtual ~ACIODeviceEmu() = default;
virtual bool is_applicable(uint8_t node_offset, uint8_t node); virtual bool is_applicable(uint8_t node_offset, uint8_t node);
virtual bool parse_msg(MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) = 0; virtual bool parse_msg(MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) = 0;
static void write_msg(const uint8_t *data, size_t size, circular_buffer<uint8_t> *response_buffer); static void write_msg(const uint8_t *data, size_t size, circular_buffer<uint8_t> *response_buffer);
static void write_msg(MessageData *msg, circular_buffer<uint8_t> *response_buffer); static void write_msg(MessageData *msg, circular_buffer<uint8_t> *response_buffer);
}; };
} }
+69 -69
View File
@@ -1,69 +1,69 @@
#include "handle.h" #include "handle.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "rawinput/rawinput.h" #include "rawinput/rawinput.h"
#include "util/utils.h" #include "util/utils.h"
acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort) { acioemu::ACIOHandle::ACIOHandle(LPCWSTR lpCOMPort) {
this->com_port = lpCOMPort; this->com_port = lpCOMPort;
} }
bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) { bool acioemu::ACIOHandle::open(LPCWSTR lpFileName) {
if (wcscmp(lpFileName, com_port) != 0) { if (wcscmp(lpFileName, com_port) != 0) {
return false; return false;
} }
log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port)); log_info("acioemu", "Opened {} (ACIO)", ws2s(com_port));
// ACIO device // ACIO device
acio_emu.add_device(new acioemu::ICCADevice(false, true, 2)); acio_emu.add_device(new acioemu::ICCADevice(false, true, 2));
return true; return true;
} }
int acioemu::ACIOHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) { int acioemu::ACIOHandle::read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) {
auto buffer = reinterpret_cast<uint8_t *>(lpBuffer); auto buffer = reinterpret_cast<uint8_t *>(lpBuffer);
// read from emu // read from emu
DWORD bytes_read = 0; DWORD bytes_read = 0;
while (bytes_read < nNumberOfBytesToRead) { while (bytes_read < nNumberOfBytesToRead) {
auto cur_byte = acio_emu.read(); auto cur_byte = acio_emu.read();
if (cur_byte.has_value()) { if (cur_byte.has_value()) {
buffer[bytes_read++] = cur_byte.value(); buffer[bytes_read++] = cur_byte.value();
} else { } else {
break; break;
} }
} }
// return amount of bytes read // return amount of bytes read
return (int) bytes_read; return (int) bytes_read;
} }
int acioemu::ACIOHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) { int acioemu::ACIOHandle::write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) {
auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer); auto buffer = reinterpret_cast<const uint8_t *>(lpBuffer);
// write to emu // write to emu
for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) { for (DWORD i = 0; i < nNumberOfBytesToWrite; i++) {
acio_emu.write(buffer[i]); acio_emu.write(buffer[i]);
} }
// return all data written // return all data written
return (int) nNumberOfBytesToWrite; return (int) nNumberOfBytesToWrite;
} }
int acioemu::ACIOHandle::device_io( int acioemu::ACIOHandle::device_io(
DWORD dwIoControlCode, DWORD dwIoControlCode,
LPVOID lpInBuffer, LPVOID lpInBuffer,
DWORD nInBufferSize, DWORD nInBufferSize,
LPVOID lpOutBuffer, LPVOID lpOutBuffer,
DWORD nOutBufferSize DWORD nOutBufferSize
) { ) {
return -1; return -1;
} }
bool acioemu::ACIOHandle::close() { bool acioemu::ACIOHandle::close() {
log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port)); log_info("acioemu", "Closed {} (ACIO)", ws2s(com_port));
return true; return true;
} }
+28 -28
View File
@@ -1,28 +1,28 @@
#pragma once #pragma once
#include "acioemu/acioemu.h" #include "acioemu/acioemu.h"
#include "hooks/devicehook.h" #include "hooks/devicehook.h"
namespace acioemu { namespace acioemu {
class ACIOHandle : public CustomHandle { class ACIOHandle : public CustomHandle {
private: private:
LPCWSTR com_port; LPCWSTR com_port;
acioemu::ACIOEmu acio_emu; acioemu::ACIOEmu acio_emu;
public: public:
ACIOHandle(LPCWSTR lpCOMPort); ACIOHandle(LPCWSTR lpCOMPort);
bool open(LPCWSTR lpFileName) override; bool open(LPCWSTR lpFileName) override;
int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override; int read(LPVOID lpBuffer, DWORD nNumberOfBytesToRead) override;
int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override; int write(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite) override;
int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, int device_io(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
DWORD nOutBufferSize) override; DWORD nOutBufferSize) override;
bool close() override; bool close() override;
}; };
} }
+42 -42
View File
@@ -1,42 +1,42 @@
#pragma once #pragma once
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <thread> #include <thread>
#include "device.h" #include "device.h"
#include "hooks/sleephook.h" #include "hooks/sleephook.h"
#include "reader/crypt.h" #include "reader/crypt.h"
namespace acioemu { namespace acioemu {
class ICCADevice : public ACIODeviceEmu { class ICCADevice : public ACIODeviceEmu {
private: private:
bool type_new; bool type_new;
bool flip_order; bool flip_order;
std::thread *keypad_thread; std::thread *keypad_thread;
std::mutex keypad_mutex; std::mutex keypad_mutex;
uint8_t **cards; uint8_t **cards;
time_t *cards_time; time_t *cards_time;
uint8_t *status; uint8_t *status;
bool *accept; bool *accept;
bool *hold; bool *hold;
uint8_t *keydown; uint8_t *keydown;
uint16_t *keypad; uint16_t *keypad;
bool **keypad_last; bool **keypad_last;
uint8_t *keypad_capture; uint8_t *keypad_capture;
std::optional<Crypt> *crypt; std::optional<Crypt> *crypt;
uint8_t *counter; uint8_t *counter;
public: public:
explicit ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count); explicit ICCADevice(bool flip_order, bool keypad_thread, uint8_t node_count);
~ICCADevice() override; ~ICCADevice() override;
bool parse_msg(MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override; bool parse_msg(MessageData *msg_in, circular_buffer<uint8_t> *response_buffer) override;
void update_card(int unit); void update_card(int unit);
void update_keypad(int unit, bool update_edge); void update_keypad(int unit, bool update_edge);
void update_status(int unit); void update_status(int unit);
}; };
} }
+82 -82
View File
@@ -1,82 +1,82 @@
#pragma once #pragma once
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <winsock2.h> #include <winsock2.h>
#include "util/rc4.h" #include "util/rc4.h"
#include "module.h" #include "module.h"
#include "websocket.h" #include "websocket.h"
#include "serial.h" #include "serial.h"
namespace api { namespace api {
struct ClientState { struct ClientState {
SOCKADDR_IN address; SOCKADDR_IN address;
SOCKET socket; SOCKET socket;
bool close = false; bool close = false;
std::vector<Module*> modules; std::vector<Module*> modules;
std::string password; std::string password;
bool password_change = false; bool password_change = false;
util::RC4 *cipher = nullptr; util::RC4 *cipher = nullptr;
}; };
class Controller { class Controller {
private: private:
// configuration // configuration
const static int server_backlog = 16; const static int server_backlog = 16;
const static int server_receive_buffer_size = 64 * 1024; const static int server_receive_buffer_size = 64 * 1024;
const static int server_message_buffer_max_size = 64 * 1024; const static int server_message_buffer_max_size = 64 * 1024;
const static int server_worker_count = 2; const static int server_worker_count = 2;
const static int server_connection_limit = 4096; const static int server_connection_limit = 4096;
// settings // settings
unsigned short port; unsigned short port;
std::string password; std::string password;
bool pretty; bool pretty;
// server // server
WebSocketController *websocket; WebSocketController *websocket;
std::vector<SerialController *> serial; std::vector<SerialController *> serial;
std::vector<std::thread> server_workers; std::vector<std::thread> server_workers;
std::vector<std::thread> server_handlers; std::vector<std::thread> server_handlers;
std::mutex server_handlers_m; std::mutex server_handlers_m;
std::vector<api::ClientState *> client_states; std::vector<api::ClientState *> client_states;
std::mutex client_states_m; std::mutex client_states_m;
SOCKET server; SOCKET server;
void server_worker(); void server_worker();
void connection_handler(ClientState client_state); void connection_handler(ClientState client_state);
public: public:
// state // state
bool server_running; bool server_running;
// constructor / destructor // constructor / destructor
Controller(unsigned short port, std::string password, bool pretty); Controller(unsigned short port, std::string password, bool pretty);
~Controller(); ~Controller();
void listen_serial(std::string port, DWORD baud); void listen_serial(std::string port, DWORD baud);
bool process_request(ClientState *state, std::vector<char> *in, std::vector<char> *out); bool process_request(ClientState *state, std::vector<char> *in, std::vector<char> *out);
bool process_request(ClientState *state, const char *in, size_t in_size, std::vector<char> *out); bool process_request(ClientState *state, const char *in, size_t in_size, std::vector<char> *out);
static void process_password_change(ClientState *state); static void process_password_change(ClientState *state);
void init_state(ClientState *state); void init_state(ClientState *state);
static void free_state(ClientState *state); static void free_state(ClientState *state);
void free_socket(); void free_socket();
void obtain_client_states(std::vector<ClientState> *output); void obtain_client_states(std::vector<ClientState> *output);
std::string get_ip_address(sockaddr_in addr); std::string get_ip_address(sockaddr_in addr);
inline const std::string &get_password() const { inline const std::string &get_password() const {
return this->password; return this->password;
} }
}; };
} }
+43 -43
View File
@@ -1,43 +1,43 @@
#include <utility> #include <utility>
#include "util/logging.h" #include "util/logging.h"
#include "module.h" #include "module.h"
using namespace rapidjson; using namespace rapidjson;
namespace api { namespace api {
// logging setting // logging setting
bool LOGGING = false; bool LOGGING = false;
Module::Module(std::string name, bool password_force) { Module::Module(std::string name, bool password_force) {
this->name = std::move(name); this->name = std::move(name);
this->password_force = password_force; this->password_force = password_force;
} }
void Module::handle(Request &req, Response &res) { void Module::handle(Request &req, Response &res) {
// log module access // log module access
if (LOGGING) if (LOGGING)
log_info("api::" + this->name, "handling request"); log_info("api::" + this->name, "handling request");
// find function // find function
auto pos = functions.find(req.function); auto pos = functions.find(req.function);
if (pos == functions.end()) if (pos == functions.end())
return error_function_unknown(res); return error_function_unknown(res);
// call function // call function
pos->second(req, res); pos->second(req, res);
} }
void Module::error(Response &res, std::string err) { void Module::error(Response &res, std::string err) {
// log the warning // log the warning
log_warning("api::" + this->name, "error: {}", err); log_warning("api::" + this->name, "error: {}", err);
// add error to response // add error to response
Value val(err.c_str(), res.doc()->GetAllocator()); Value val(err.c_str(), res.doc()->GetAllocator());
res.add_error(val); res.add_error(val);
} }
} }
+67 -67
View File
@@ -1,67 +1,67 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <map> #include <map>
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <external/robin_hood.h> #include <external/robin_hood.h>
#include "response.h" #include "response.h"
#include "request.h" #include "request.h"
namespace api { namespace api {
// logging setting // logging setting
extern bool LOGGING; extern bool LOGGING;
// callback // callback
typedef std::function<void(Request &, Response &)> ModuleFunctionCallback; typedef std::function<void(Request &, Response &)> ModuleFunctionCallback;
class Module { class Module {
protected: protected:
// map of available functions // map of available functions
robin_hood::unordered_map<std::string, ModuleFunctionCallback> functions; robin_hood::unordered_map<std::string, ModuleFunctionCallback> functions;
// default constructor // default constructor
explicit Module(std::string name, bool password_force=false); explicit Module(std::string name, bool password_force=false);
public: public:
// virtual deconstructor // virtual deconstructor
virtual ~Module() = default; virtual ~Module() = default;
// name of the module (should match namespace) // name of the module (should match namespace)
std::string name; std::string name;
bool password_force; bool password_force;
// the magic // the magic
void handle(Request &req, Response &res); void handle(Request &req, Response &res);
/* /*
* Error definitions. * Error definitions.
*/ */
void error(Response &res, std::string err); void error(Response &res, std::string err);
void error_type(Response &res, const std::string &field, const std::string &type) { void error_type(Response &res, const std::string &field, const std::string &type) {
std::ostringstream s; std::ostringstream s;
s << field << " must be a " << type; s << field << " must be a " << type;
error(res, s.str()); error(res, s.str());
}; };
void error_size(Response &res, const std::string &field, size_t size) { void error_size(Response &res, const std::string &field, size_t size) {
std::ostringstream s; std::ostringstream s;
s << field << " must be of size " << size; s << field << " must be of size " << size;
error(res, s.str()); error(res, s.str());
} }
void error_unknown(Response &res, const std::string &field, const std::string &name) { void error_unknown(Response &res, const std::string &field, const std::string &name) {
std::ostringstream s; std::ostringstream s;
s << "Unknown " << field << ": " << name; s << "Unknown " << field << ": " << name;
error(res, s.str()); error(res, s.str());
} }
#define ERR(name, err) void error_##name(Response &res) { error(res, err); } #define ERR(name, err) void error_##name(Response &res) { error(res, err); }
ERR(function_unknown, "Unknown function."); ERR(function_unknown, "Unknown function.");
ERR(params_insufficient, "Insufficient number of parameters."); ERR(params_insufficient, "Insufficient number of parameters.");
#undef ERR #undef ERR
}; };
} }
+177 -177
View File
@@ -1,177 +1,177 @@
#include "analogs.h" #include "analogs.h"
#include <functional> #include <functional>
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "cfg/analog.h" #include "cfg/analog.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
#include "games/io.h" #include "games/io.h"
#include "util/utils.h" #include "util/utils.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
Analogs::Analogs() : Module("analogs") { Analogs::Analogs() : Module("analogs") {
functions["read"] = std::bind(&Analogs::read, this, _1, _2); functions["read"] = std::bind(&Analogs::read, this, _1, _2);
functions["write"] = std::bind(&Analogs::write, this, _1, _2); functions["write"] = std::bind(&Analogs::write, this, _1, _2);
functions["write_reset"] = std::bind(&Analogs::write_reset, this, _1, _2); functions["write_reset"] = std::bind(&Analogs::write_reset, this, _1, _2);
analogs = games::get_analogs(eamuse_get_game()); analogs = games::get_analogs(eamuse_get_game());
} }
/** /**
* read() * read()
*/ */
void Analogs::read(api::Request &req, Response &res) { void Analogs::read(api::Request &req, Response &res) {
// check analog cache // check analog cache
if (!analogs) { if (!analogs) {
return; return;
} }
// add state for each analog // add state for each analog
for (auto &analog : *this->analogs) { for (auto &analog : *this->analogs) {
Value state(kArrayType); Value state(kArrayType);
Value analog_name(analog.getName().c_str(), res.doc()->GetAllocator()); Value analog_name(analog.getName().c_str(), res.doc()->GetAllocator());
Value analog_state(GameAPI::Analogs::getState(RI_MGR, analog)); Value analog_state(GameAPI::Analogs::getState(RI_MGR, analog));
Value analog_enabled(analog.override_enabled); Value analog_enabled(analog.override_enabled);
state.PushBack(analog_name, res.doc()->GetAllocator()); state.PushBack(analog_name, res.doc()->GetAllocator());
state.PushBack(analog_state, res.doc()->GetAllocator()); state.PushBack(analog_state, res.doc()->GetAllocator());
state.PushBack(analog_enabled, res.doc()->GetAllocator()); state.PushBack(analog_enabled, res.doc()->GetAllocator());
res.add_data(state); res.add_data(state);
} }
} }
/** /**
* write([name: str, state: float], ...) * write([name: str, state: float], ...)
*/ */
void Analogs::write(Request &req, Response &res) { void Analogs::write(Request &req, Response &res) {
// check analog cache // check analog cache
if (!analogs) if (!analogs)
return; return;
// loop parameters // loop parameters
for (Value &param : req.params.GetArray()) { for (Value &param : req.params.GetArray()) {
// check params // check params
if (!param.IsArray()) { if (!param.IsArray()) {
error(res, "parameters must be arrays"); error(res, "parameters must be arrays");
return; return;
} }
if (param.Size() < 2) { if (param.Size() < 2) {
error_params_insufficient(res); error_params_insufficient(res);
continue; continue;
} }
if (!param[0].IsString()) { if (!param[0].IsString()) {
error_type(res, "name", "string"); error_type(res, "name", "string");
continue; continue;
} }
if (!param[1].IsFloat() && !param[1].IsInt()) { if (!param[1].IsFloat() && !param[1].IsInt()) {
error_type(res, "state", "float"); error_type(res, "state", "float");
continue; continue;
} }
// get params // get params
auto analog_name = param[0].GetString(); auto analog_name = param[0].GetString();
auto analog_state = param[1].GetFloat(); auto analog_state = param[1].GetFloat();
// write analog state // write analog state
if (!this->write_analog(analog_name, analog_state)) { if (!this->write_analog(analog_name, analog_state)) {
error_unknown(res, "analog", analog_name); error_unknown(res, "analog", analog_name);
continue; continue;
} }
} }
} }
/** /**
* write_reset() * write_reset()
* write_reset([name: str], ...) * write_reset([name: str], ...)
*/ */
void Analogs::write_reset(Request &req, Response &res) { void Analogs::write_reset(Request &req, Response &res) {
// check analog cache // check analog cache
if (!analogs) if (!analogs)
return; return;
// get params // get params
auto params = req.params.GetArray(); auto params = req.params.GetArray();
// write_reset() // write_reset()
if (params.Size() == 0) { if (params.Size() == 0) {
if (analogs != nullptr) { if (analogs != nullptr) {
for (auto &analog : *this->analogs) { for (auto &analog : *this->analogs) {
analog.override_enabled = false; analog.override_enabled = false;
} }
} }
return; return;
} }
// loop parameters // loop parameters
for (Value &param : req.params.GetArray()) { for (Value &param : req.params.GetArray()) {
// check params // check params
if (!param.IsArray()) { if (!param.IsArray()) {
error(res, "parameters must be arrays"); error(res, "parameters must be arrays");
return; return;
} }
if (param.Size() < 1) { if (param.Size() < 1) {
error_params_insufficient(res); error_params_insufficient(res);
continue; continue;
} }
if (!param[0].IsString()) { if (!param[0].IsString()) {
error_type(res, "name", "string"); error_type(res, "name", "string");
continue; continue;
} }
// get params // get params
auto analog_name = param[0].GetString(); auto analog_name = param[0].GetString();
// write analog state // write analog state
if (!this->write_analog_reset(analog_name)) { if (!this->write_analog_reset(analog_name)) {
error_unknown(res, "analog", analog_name); error_unknown(res, "analog", analog_name);
continue; continue;
} }
} }
} }
bool Analogs::write_analog(std::string name, float state) { bool Analogs::write_analog(std::string name, float state) {
// check analog cache // check analog cache
if (!this->analogs) { if (!this->analogs) {
return false; return false;
} }
// find analog // find analog
for (auto &analog : *this->analogs) { for (auto &analog : *this->analogs) {
if (analog.getName() == name) { if (analog.getName() == name) {
analog.override_state = CLAMP(state, 0.f, 1.f); analog.override_state = CLAMP(state, 0.f, 1.f);
analog.override_enabled = true; analog.override_enabled = true;
return true; return true;
} }
} }
// unknown analog // unknown analog
return false; return false;
} }
bool Analogs::write_analog_reset(std::string name) { bool Analogs::write_analog_reset(std::string name) {
// check analog cache // check analog cache
if (!analogs) { if (!analogs) {
return false; return false;
} }
// find analog // find analog
for (auto &analog : *this->analogs) { for (auto &analog : *this->analogs) {
if (analog.getName() == name) { if (analog.getName() == name) {
analog.override_enabled = false; analog.override_enabled = false;
return true; return true;
} }
} }
// unknown analog // unknown analog
return false; return false;
} }
} }
+28 -28
View File
@@ -1,28 +1,28 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
#include "cfg/api.h" #include "cfg/api.h"
namespace api::modules { namespace api::modules {
class Analogs : public Module { class Analogs : public Module {
public: public:
Analogs(); Analogs();
private: private:
// state // state
std::vector<Analog> *analogs; std::vector<Analog> *analogs;
// function definitions // function definitions
void read(Request &req, Response &res); void read(Request &req, Response &res);
void write(Request &req, Response &res); void write(Request &req, Response &res);
void write_reset(Request &req, Response &res); void write_reset(Request &req, Response &res);
// helper // helper
bool write_analog(std::string name, float state); bool write_analog(std::string name, float state);
bool write_analog_reset(std::string name); bool write_analog_reset(std::string name);
}; };
} }
+28 -28
View File
@@ -1,28 +1,28 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
#include "cfg/api.h" #include "cfg/api.h"
namespace api::modules { namespace api::modules {
class Buttons : public Module { class Buttons : public Module {
public: public:
Buttons(); Buttons();
private: private:
// state // state
std::vector<Button> *buttons; std::vector<Button> *buttons;
// function definitions // function definitions
void read(Request &req, Response &res); void read(Request &req, Response &res);
void write(Request &req, Response &res); void write(Request &req, Response &res);
void write_reset(Request &req, Response &res); void write_reset(Request &req, Response &res);
// helper // helper
bool write_button(std::string name, float state); bool write_button(std::string name, float state);
bool write_button_reset(std::string name); bool write_button_reset(std::string name);
}; };
} }
+82 -82
View File
@@ -1,82 +1,82 @@
#include "capture.h" #include "capture.h"
#include <functional> #include <functional>
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "hooks/graphics/graphics.h" #include "hooks/graphics/graphics.h"
#include "util/crypt.h" #include "util/crypt.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
static thread_local std::vector<uint8_t> CAPTURE_BUFFER; static thread_local std::vector<uint8_t> CAPTURE_BUFFER;
Capture::Capture() : Module("capture") { Capture::Capture() : Module("capture") {
functions["get_screens"] = std::bind(&Capture::get_screens, this, _1, _2); functions["get_screens"] = std::bind(&Capture::get_screens, this, _1, _2);
functions["get_jpg"] = std::bind(&Capture::get_jpg, this, _1, _2); functions["get_jpg"] = std::bind(&Capture::get_jpg, this, _1, _2);
} }
/** /**
* get_screens() * get_screens()
*/ */
void Capture::get_screens(Request &req, Response &res) { void Capture::get_screens(Request &req, Response &res) {
// aquire screens // aquire screens
std::vector<int> screens; std::vector<int> screens;
graphics_screens_get(screens); graphics_screens_get(screens);
// add screens to response // add screens to response
for (auto &screen : screens) { for (auto &screen : screens) {
res.add_data(screen); res.add_data(screen);
} }
} }
/** /**
* get_jpg([screen=0, quality=70, downscale=0, divide=1]) * get_jpg([screen=0, quality=70, downscale=0, divide=1])
* screen: uint specifying the window * screen: uint specifying the window
* quality: uint in range [0, 100] * quality: uint in range [0, 100]
* reduce: uint for dividing image size * reduce: uint for dividing image size
*/ */
void Capture::get_jpg(Request &req, Response &res) { void Capture::get_jpg(Request &req, Response &res) {
CAPTURE_BUFFER.reserve(1024 * 128); CAPTURE_BUFFER.reserve(1024 * 128);
// settings // settings
int screen = 0; int screen = 0;
int quality = 70; int quality = 70;
int divide = 1; int divide = 1;
if (req.params.Size() > 0 && req.params[0].IsUint()) if (req.params.Size() > 0 && req.params[0].IsUint())
screen = req.params[0].GetUint(); screen = req.params[0].GetUint();
if (req.params.Size() > 1 && req.params[1].IsUint()) if (req.params.Size() > 1 && req.params[1].IsUint())
quality = req.params[1].GetUint(); quality = req.params[1].GetUint();
if (req.params.Size() > 2 && req.params[2].IsUint()) if (req.params.Size() > 2 && req.params[2].IsUint())
divide = req.params[2].GetUint(); divide = req.params[2].GetUint();
// receive JPEG data // receive JPEG data
uint64_t timestamp = 0; uint64_t timestamp = 0;
int width = 0; int width = 0;
int height = 0; int height = 0;
graphics_capture_trigger(screen); graphics_capture_trigger(screen);
bool success = graphics_capture_receive_jpeg(screen, [] (uint8_t byte) { bool success = graphics_capture_receive_jpeg(screen, [] (uint8_t byte) {
CAPTURE_BUFFER.push_back(byte); CAPTURE_BUFFER.push_back(byte);
}, true, quality, true, divide, &timestamp, &width, &height); }, true, quality, true, divide, &timestamp, &width, &height);
if (!success) { if (!success) {
return; return;
} }
// encode to base64 // encode to base64
auto encoded = crypt::base64_encode( auto encoded = crypt::base64_encode(
CAPTURE_BUFFER.data(), CAPTURE_BUFFER.data(),
CAPTURE_BUFFER.size()); CAPTURE_BUFFER.size());
// clear buffer // clear buffer
CAPTURE_BUFFER.clear(); CAPTURE_BUFFER.clear();
// add data to response // add data to response
Value data; Value data;
data.SetString(encoded.c_str(), encoded.length(), res.doc()->GetAllocator()); data.SetString(encoded.c_str(), encoded.length(), res.doc()->GetAllocator());
res.add_data(timestamp); res.add_data(timestamp);
res.add_data(width); res.add_data(width);
res.add_data(height); res.add_data(height);
res.add_data(data); res.add_data(data);
} }
} }
+18 -18
View File
@@ -1,18 +1,18 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Capture : public Module { class Capture : public Module {
public: public:
Capture(); Capture();
private: private:
// function definitions // function definitions
void get_screens(Request &req, Response &res); void get_screens(Request &req, Response &res);
void get_jpg(Request &req, Response &res); void get_jpg(Request &req, Response &res);
}; };
} }
+17 -17
View File
@@ -1,17 +1,17 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Card : public Module { class Card : public Module {
public: public:
Card(); Card();
private: private:
// function definitions // function definitions
void insert(Request &req, Response &res); void insert(Request &req, Response &res);
}; };
} }
+20 -20
View File
@@ -1,20 +1,20 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Coin : public Module { class Coin : public Module {
public: public:
Coin(); Coin();
private: private:
// function definitions // function definitions
void get(Request &req, Response &res); void get(Request &req, Response &res);
void set(Request &req, Response &res); void set(Request &req, Response &res);
void insert(Request &req, Response &res); void insert(Request &req, Response &res);
void blocker_get(Request &req, Response &res); void blocker_get(Request &req, Response &res);
}; };
} }
+180 -180
View File
@@ -1,180 +1,180 @@
#include "control.h" #include "control.h"
#include <csignal> #include <csignal>
#include <functional> #include <functional>
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "launcher/shutdown.h" #include "launcher/shutdown.h"
#include "util/logging.h" #include "util/logging.h"
#include "util/crypt.h" #include "util/crypt.h"
#include "util/utils.h" #include "util/utils.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
struct SignalMapping { struct SignalMapping {
int signum; int signum;
const char* name; const char* name;
}; };
static SignalMapping SIGNAL_MAPPINGS[] = { static SignalMapping SIGNAL_MAPPINGS[] = {
{ SIGABRT, "SIGABRT" }, { SIGABRT, "SIGABRT" },
{ SIGFPE, "SIGFPE" }, { SIGFPE, "SIGFPE" },
{ SIGILL, "SIGILL" }, { SIGILL, "SIGILL" },
{ SIGINT, "SIGINT" }, { SIGINT, "SIGINT" },
{ SIGSEGV, "SIGSEGV" }, { SIGSEGV, "SIGSEGV" },
{ SIGTERM, "SIGTERM" }, { SIGTERM, "SIGTERM" },
}; };
static inline bool acquire_shutdown_privs() { static inline bool acquire_shutdown_privs() {
// check if already acquired // check if already acquired
static bool acquired = false; static bool acquired = false;
if (acquired) if (acquired)
return true; return true;
// get process token // get process token
HANDLE hToken; HANDLE hToken;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
return false; return false;
// get the LUID for the shutdown privilege // get the LUID for the shutdown privilege
TOKEN_PRIVILEGES tkp; TOKEN_PRIVILEGES tkp;
LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid); LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &tkp.Privileges[0].Luid);
tkp.PrivilegeCount = 1; tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
// get the shutdown privilege for this process // get the shutdown privilege for this process
AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0); AdjustTokenPrivileges(hToken, FALSE, &tkp, 0, (PTOKEN_PRIVILEGES) NULL, 0);
// check for error // check for error
bool success = GetLastError() == ERROR_SUCCESS; bool success = GetLastError() == ERROR_SUCCESS;
if (success) if (success)
acquired = true; acquired = true;
return success; return success;
} }
Control::Control() : Module("control", true) { Control::Control() : Module("control", true) {
functions["raise"] = std::bind(&Control::raise, this, _1, _2); functions["raise"] = std::bind(&Control::raise, this, _1, _2);
functions["exit"] = std::bind(&Control::exit, this, _1, _2); functions["exit"] = std::bind(&Control::exit, this, _1, _2);
functions["restart"] = std::bind(&Control::restart, this, _1, _2); functions["restart"] = std::bind(&Control::restart, this, _1, _2);
functions["session_refresh"] = std::bind(&Control::session_refresh, this, _1, _2); functions["session_refresh"] = std::bind(&Control::session_refresh, this, _1, _2);
functions["shutdown"] = std::bind(&Control::shutdown, this, _1, _2); functions["shutdown"] = std::bind(&Control::shutdown, this, _1, _2);
functions["reboot"] = std::bind(&Control::reboot, this, _1, _2); functions["reboot"] = std::bind(&Control::reboot, this, _1, _2);
} }
/** /**
* raise(signal: str) * raise(signal: str)
*/ */
void Control::raise(Request &req, Response &res) { void Control::raise(Request &req, Response &res) {
// check args // check args
if (req.params.Size() < 1) if (req.params.Size() < 1)
return error_params_insufficient(res); return error_params_insufficient(res);
if (!req.params[0].IsString()) if (!req.params[0].IsString())
return error_type(res, "signal", "string"); return error_type(res, "signal", "string");
// get signal // get signal
auto signal_str = req.params[0].GetString(); auto signal_str = req.params[0].GetString();
int signal_val = -1; int signal_val = -1;
for (auto mapping : SIGNAL_MAPPINGS) { for (auto mapping : SIGNAL_MAPPINGS) {
if (_stricmp(mapping.name, signal_str) == 0) { if (_stricmp(mapping.name, signal_str) == 0) {
signal_val = mapping.signum; signal_val = mapping.signum;
break; break;
} }
} }
// check if not found // check if not found
if (signal_val < 0) if (signal_val < 0)
return error_unknown(res, "signal", signal_str); return error_unknown(res, "signal", signal_str);
// raise signal // raise signal
if (::raise(signal_val)) if (::raise(signal_val))
return error(res, "Failed to raise signo " + to_string(signal_val)); return error(res, "Failed to raise signo " + to_string(signal_val));
} }
/** /**
* exit() * exit()
* exit(code: int) * exit(code: int)
*/ */
void Control::exit(Request &req, Response &res) { void Control::exit(Request &req, Response &res) {
// exit() // exit()
if (req.params.Size() == 0) { if (req.params.Size() == 0) {
launcher::shutdown(); launcher::shutdown();
} }
// check code // check code
if (!req.params[0].IsInt()) if (!req.params[0].IsInt())
return error_type(res, "code", "int"); return error_type(res, "code", "int");
// exit // exit
launcher::shutdown(req.params[0].GetInt()); launcher::shutdown(req.params[0].GetInt());
} }
/** /**
* restart() * restart()
*/ */
void Control::restart(Request &req, Response &res) { void Control::restart(Request &req, Response &res) {
// restart launcher // restart launcher
launcher::restart(); launcher::restart();
} }
/** /**
* session_refresh() * session_refresh()
*/ */
void Control::session_refresh(Request &req, Response &res) { void Control::session_refresh(Request &req, Response &res) {
// generate new password // generate new password
uint8_t password_bin[128]; uint8_t password_bin[128];
crypt::random_bytes(password_bin, std::size(password_bin)); crypt::random_bytes(password_bin, std::size(password_bin));
std::string password = bin2hex(&password_bin[0], std::size(password_bin)); std::string password = bin2hex(&password_bin[0], std::size(password_bin));
// add to response // add to response
Value password_val(password.c_str(), res.doc()->GetAllocator()); Value password_val(password.c_str(), res.doc()->GetAllocator());
res.add_data(password_val); res.add_data(password_val);
// change password // change password
res.password_change(password); res.password_change(password);
} }
/** /**
* shutdown() * shutdown()
*/ */
void Control::shutdown(Request &req, Response &res) { void Control::shutdown(Request &req, Response &res) {
// acquire privileges // acquire privileges
if (!acquire_shutdown_privs()) if (!acquire_shutdown_privs())
return error(res, "Unable to acquire shutdown privileges"); return error(res, "Unable to acquire shutdown privileges");
// exit windows // exit windows
if (!ExitWindowsEx(EWX_POWEROFF | EWX_FORCE, if (!ExitWindowsEx(EWX_POWEROFF | EWX_FORCE,
SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MAJOR_APPLICATION |
SHTDN_REASON_MINOR_MAINTENANCE)) SHTDN_REASON_MINOR_MAINTENANCE))
return error(res, "Unable to shutdown system"); return error(res, "Unable to shutdown system");
// terminate this process // terminate this process
launcher::shutdown(0); launcher::shutdown(0);
} }
/** /**
* reboot() * reboot()
*/ */
void Control::reboot(Request &req, Response &res) { void Control::reboot(Request &req, Response &res) {
// acquire privileges // acquire privileges
if (!acquire_shutdown_privs()) if (!acquire_shutdown_privs())
return error(res, "Unable to acquire shutdown privileges"); return error(res, "Unable to acquire shutdown privileges");
// exit windows // exit windows
if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCE, if (!ExitWindowsEx(EWX_REBOOT | EWX_FORCE,
SHTDN_REASON_MAJOR_APPLICATION | SHTDN_REASON_MAJOR_APPLICATION |
SHTDN_REASON_MINOR_MAINTENANCE)) SHTDN_REASON_MINOR_MAINTENANCE))
return error(res, "Unable to reboot system"); return error(res, "Unable to reboot system");
// terminate this process // terminate this process
launcher::shutdown(0); launcher::shutdown(0);
} }
} }
+22 -22
View File
@@ -1,22 +1,22 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Control : public Module { class Control : public Module {
public: public:
Control(); Control();
private: private:
// function definitions // function definitions
void raise(Request &req, Response &res); void raise(Request &req, Response &res);
void exit(Request &req, Response &res); void exit(Request &req, Response &res);
void restart(Request &req, Response &res); void restart(Request &req, Response &res);
void session_refresh(Request &req, Response &res); void session_refresh(Request &req, Response &res);
void shutdown(Request &req, Response &res); void shutdown(Request &req, Response &res);
void reboot(Request &req, Response &res); void reboot(Request &req, Response &res);
}; };
} }
+19 -19
View File
@@ -1,19 +1,19 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Info : public Module { class Info : public Module {
public: public:
Info(); Info();
private: private:
// function definitions // function definitions
void avs(Request &req, Response &res); void avs(Request &req, Response &res);
void launcher(Request &req, Response &res); void launcher(Request &req, Response &res);
void memory(Request &req, Response &res); void memory(Request &req, Response &res);
}; };
} }
+176 -176
View File
@@ -1,176 +1,176 @@
#include "keypads.h" #include "keypads.h"
#include <functional> #include <functional>
#include <windows.h> #include <windows.h>
#include "avs/game.h" #include "avs/game.h"
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
struct KeypadMapping { struct KeypadMapping {
char character; char character;
uint16_t state; uint16_t state;
}; };
static KeypadMapping KEYPAD_MAPPINGS[] = { static KeypadMapping KEYPAD_MAPPINGS[] = {
{ '0', 1 << EAM_IO_KEYPAD_0 }, { '0', 1 << EAM_IO_KEYPAD_0 },
{ '1', 1 << EAM_IO_KEYPAD_1 }, { '1', 1 << EAM_IO_KEYPAD_1 },
{ '2', 1 << EAM_IO_KEYPAD_2 }, { '2', 1 << EAM_IO_KEYPAD_2 },
{ '3', 1 << EAM_IO_KEYPAD_3 }, { '3', 1 << EAM_IO_KEYPAD_3 },
{ '4', 1 << EAM_IO_KEYPAD_4 }, { '4', 1 << EAM_IO_KEYPAD_4 },
{ '5', 1 << EAM_IO_KEYPAD_5 }, { '5', 1 << EAM_IO_KEYPAD_5 },
{ '6', 1 << EAM_IO_KEYPAD_6 }, { '6', 1 << EAM_IO_KEYPAD_6 },
{ '7', 1 << EAM_IO_KEYPAD_7 }, { '7', 1 << EAM_IO_KEYPAD_7 },
{ '8', 1 << EAM_IO_KEYPAD_8 }, { '8', 1 << EAM_IO_KEYPAD_8 },
{ '9', 1 << EAM_IO_KEYPAD_9 }, { '9', 1 << EAM_IO_KEYPAD_9 },
{ 'A', 1 << EAM_IO_KEYPAD_00 }, { 'A', 1 << EAM_IO_KEYPAD_00 },
{ 'D', 1 << EAM_IO_KEYPAD_DECIMAL }, { 'D', 1 << EAM_IO_KEYPAD_DECIMAL },
}; };
Keypads::Keypads() : Module("keypads") { Keypads::Keypads() : Module("keypads") {
functions["write"] = std::bind(&Keypads::write, this, _1, _2); functions["write"] = std::bind(&Keypads::write, this, _1, _2);
functions["set"] = std::bind(&Keypads::set, this, _1, _2); functions["set"] = std::bind(&Keypads::set, this, _1, _2);
functions["get"] = std::bind(&Keypads::get, this, _1, _2); functions["get"] = std::bind(&Keypads::get, this, _1, _2);
} }
/** /**
* write(keypad: uint, input: str) * write(keypad: uint, input: str)
*/ */
void Keypads::write(Request &req, Response &res) { void Keypads::write(Request &req, Response &res) {
// check params // check params
if (req.params.Size() < 2) { if (req.params.Size() < 2) {
return error_params_insufficient(res); return error_params_insufficient(res);
} }
if (!req.params[0].IsUint()) { if (!req.params[0].IsUint()) {
return error_type(res, "keypad", "uint"); return error_type(res, "keypad", "uint");
} }
if (!req.params[1].IsString()) { if (!req.params[1].IsString()) {
return error_type(res, "input", "string"); return error_type(res, "input", "string");
} }
// get params // get params
auto keypad = req.params[0].GetUint(); auto keypad = req.params[0].GetUint();
auto input = std::string(req.params[1].GetString()); auto input = std::string(req.params[1].GetString());
// process all chars // process all chars
for (auto c : input) { for (auto c : input) {
uint16_t state = 0; uint16_t state = 0;
// find mapping // find mapping
bool mapping_found = false; bool mapping_found = false;
for (auto &mapping : KEYPAD_MAPPINGS) { for (auto &mapping : KEYPAD_MAPPINGS) {
if (_strnicmp(&mapping.character, &c, 1) == 0) { if (_strnicmp(&mapping.character, &c, 1) == 0) {
state |= mapping.state; state |= mapping.state;
mapping_found = true; mapping_found = true;
break; break;
} }
} }
// check for error // check for error
if (!mapping_found) { if (!mapping_found) {
return error_unknown(res, "char", std::string("") + c); return error_unknown(res, "char", std::string("") + c);
} }
/* /*
* Write input to keypad. * Write input to keypad.
* We try to make sure it was accepted by waiting a bit more than two frames. * We try to make sure it was accepted by waiting a bit more than two frames.
*/ */
DWORD sleep_time = 70; DWORD sleep_time = 70;
if (avs::game::is_model("MDX")) { if (avs::game::is_model("MDX")) {
// cuz fuck DDR // cuz fuck DDR
sleep_time = 150; sleep_time = 150;
} }
// set // set
eamuse_set_keypad_overrides(keypad, state); eamuse_set_keypad_overrides(keypad, state);
Sleep(sleep_time); Sleep(sleep_time);
// unset // unset
eamuse_set_keypad_overrides(keypad, 0); eamuse_set_keypad_overrides(keypad, 0);
Sleep(sleep_time); Sleep(sleep_time);
} }
} }
/** /**
* set(keypad: uint, key: char, ...) * set(keypad: uint, key: char, ...)
*/ */
void Keypads::set(Request &req, Response &res) { void Keypads::set(Request &req, Response &res) {
// check keypad // check keypad
if (req.params.Size() < 1) { if (req.params.Size() < 1) {
return error_params_insufficient(res); return error_params_insufficient(res);
} }
if (!req.params[0].IsUint()) { if (!req.params[0].IsUint()) {
return error_type(res, "keypad", "uint"); return error_type(res, "keypad", "uint");
} }
auto keypad = req.params[0].GetUint(); auto keypad = req.params[0].GetUint();
// iterate params // iterate params
uint16_t state = 0; uint16_t state = 0;
auto params = req.params.GetArray(); auto params = req.params.GetArray();
for (size_t i = 1; i < params.Size(); i++) { for (size_t i = 1; i < params.Size(); i++) {
auto &param = params[i]; auto &param = params[i];
// check key // check key
if (!param.IsString()) { if (!param.IsString()) {
error_type(res, "key", "char"); error_type(res, "key", "char");
} }
if (param.GetStringLength() < 1) { if (param.GetStringLength() < 1) {
error_size(res, "key", 1); error_size(res, "key", 1);
} }
// find mapping // find mapping
auto key = param.GetString(); auto key = param.GetString();
bool mapping_found = false; bool mapping_found = false;
for (auto &mapping : KEYPAD_MAPPINGS) { for (auto &mapping : KEYPAD_MAPPINGS) {
if (_strnicmp(&mapping.character, key, 1) == 0) { if (_strnicmp(&mapping.character, key, 1) == 0) {
state |= mapping.state; state |= mapping.state;
mapping_found = true; mapping_found = true;
break; break;
} }
} }
// check for error // check for error
if (!mapping_found) { if (!mapping_found) {
return error_unknown(res, "key", key); return error_unknown(res, "key", key);
} }
} }
// set keypad state // set keypad state
eamuse_set_keypad_overrides(keypad, state); eamuse_set_keypad_overrides(keypad, state);
} }
/** /**
* get(keypad: uint) * get(keypad: uint)
*/ */
void Keypads::get(Request &req, Response &res) { void Keypads::get(Request &req, Response &res) {
// check keypad // check keypad
if (req.params.Size() < 1) { if (req.params.Size() < 1) {
return error_params_insufficient(res); return error_params_insufficient(res);
} }
if (!req.params[0].IsUint()) { if (!req.params[0].IsUint()) {
return error_type(res, "keypad", "uint"); return error_type(res, "keypad", "uint");
} }
auto keypad = req.params[0].GetUint(); auto keypad = req.params[0].GetUint();
// get keypad state // get keypad state
auto state = eamuse_get_keypad_state(keypad); auto state = eamuse_get_keypad_state(keypad);
// add keys to response // add keys to response
for (auto &mapping : KEYPAD_MAPPINGS) { for (auto &mapping : KEYPAD_MAPPINGS) {
if (state & mapping.state) { if (state & mapping.state) {
Value val(&mapping.character, 1); Value val(&mapping.character, 1);
res.add_data(val); res.add_data(val);
} }
} }
} }
} }
+19 -19
View File
@@ -1,19 +1,19 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Keypads : public Module { class Keypads : public Module {
public: public:
Keypads(); Keypads();
private: private:
// function definitions // function definitions
void write(Request &req, Response &res); void write(Request &req, Response &res);
void set(Request &req, Response &res); void set(Request &req, Response &res);
void get(Request &req, Response &res); void get(Request &req, Response &res);
}; };
} }
+36 -36
View File
@@ -1,36 +1,36 @@
#include "lcd.h" #include "lcd.h"
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "games/shared/lcdhandle.h" #include "games/shared/lcdhandle.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
LCD::LCD() : Module("lcd") { LCD::LCD() : Module("lcd") {
functions["info"] = std::bind(&LCD::info, this, _1, _2); functions["info"] = std::bind(&LCD::info, this, _1, _2);
} }
/* /*
* info() * info()
*/ */
void LCD::info(Request &req, Response &res) { void LCD::info(Request &req, Response &res) {
// get allocator // get allocator
auto &alloc = res.doc()->GetAllocator(); auto &alloc = res.doc()->GetAllocator();
// build info object // build info object
Value info(kObjectType); Value info(kObjectType);
info.AddMember("enabled", games::shared::LCD_ENABLED, alloc); info.AddMember("enabled", games::shared::LCD_ENABLED, alloc);
info.AddMember("csm", StringRef(games::shared::LCD_CSM.c_str()), alloc); info.AddMember("csm", StringRef(games::shared::LCD_CSM.c_str()), alloc);
info.AddMember("bri", games::shared::LCD_BRI, alloc); info.AddMember("bri", games::shared::LCD_BRI, alloc);
info.AddMember("con", games::shared::LCD_CON, alloc); info.AddMember("con", games::shared::LCD_CON, alloc);
info.AddMember("bl", games::shared::LCD_BL, alloc); info.AddMember("bl", games::shared::LCD_BL, alloc);
info.AddMember("red", games::shared::LCD_RED, alloc); info.AddMember("red", games::shared::LCD_RED, alloc);
info.AddMember("green", games::shared::LCD_GREEN, alloc); info.AddMember("green", games::shared::LCD_GREEN, alloc);
info.AddMember("blue", games::shared::LCD_BLUE, alloc); info.AddMember("blue", games::shared::LCD_BLUE, alloc);
// add info object // add info object
res.add_data(info); res.add_data(info);
} }
} }
+17 -17
View File
@@ -1,17 +1,17 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class LCD : public Module { class LCD : public Module {
public: public:
LCD(); LCD();
private: private:
// function definitions // function definitions
void info(Request &req, Response &res); void info(Request &req, Response &res);
}; };
} }
+179 -179
View File
@@ -1,179 +1,179 @@
#include "lights.h" #include "lights.h"
#include <functional> #include <functional>
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "misc/eamuse.h" #include "misc/eamuse.h"
#include "cfg/light.h" #include "cfg/light.h"
#include "launcher/launcher.h" #include "launcher/launcher.h"
#include "games/io.h" #include "games/io.h"
#include "util/utils.h" #include "util/utils.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
Lights::Lights() : Module("lights") { Lights::Lights() : Module("lights") {
functions["read"] = std::bind(&Lights::read, this, _1, _2); functions["read"] = std::bind(&Lights::read, this, _1, _2);
functions["write"] = std::bind(&Lights::write, this, _1, _2); functions["write"] = std::bind(&Lights::write, this, _1, _2);
functions["write_reset"] = std::bind(&Lights::write_reset, this, _1, _2); functions["write_reset"] = std::bind(&Lights::write_reset, this, _1, _2);
lights = games::get_lights(eamuse_get_game()); lights = games::get_lights(eamuse_get_game());
} }
/** /**
* read() * read()
*/ */
void Lights::read(api::Request &req, Response &res) { void Lights::read(api::Request &req, Response &res) {
// check light cache // check light cache
if (!this->lights) { if (!this->lights) {
return; return;
} }
// add state for each light // add state for each light
for (auto &light : *this->lights) { for (auto &light : *this->lights) {
Value state(kArrayType); Value state(kArrayType);
Value light_name(light.getName().c_str(), res.doc()->GetAllocator()); Value light_name(light.getName().c_str(), res.doc()->GetAllocator());
Value light_state(GameAPI::Lights::readLight(RI_MGR, light)); Value light_state(GameAPI::Lights::readLight(RI_MGR, light));
Value light_enabled(light.override_enabled); Value light_enabled(light.override_enabled);
state.PushBack(light_name, res.doc()->GetAllocator()); state.PushBack(light_name, res.doc()->GetAllocator());
state.PushBack(light_state, res.doc()->GetAllocator()); state.PushBack(light_state, res.doc()->GetAllocator());
state.PushBack(light_enabled, res.doc()->GetAllocator()); state.PushBack(light_enabled, res.doc()->GetAllocator());
res.add_data(state); res.add_data(state);
} }
} }
/** /**
* write([name: str, state: float], ...) * write([name: str, state: float], ...)
*/ */
void Lights::write(Request &req, Response &res) { void Lights::write(Request &req, Response &res) {
// check light cache // check light cache
if (!this->lights) { if (!this->lights) {
return; return;
} }
// loop parameters // loop parameters
for (Value &param : req.params.GetArray()) { for (Value &param : req.params.GetArray()) {
// check params // check params
if (!param.IsArray()) { if (!param.IsArray()) {
error(res, "parameters must be arrays"); error(res, "parameters must be arrays");
return; return;
} }
if (param.Size() < 2) { if (param.Size() < 2) {
error_params_insufficient(res); error_params_insufficient(res);
continue; continue;
} }
if (!param[0].IsString()) { if (!param[0].IsString()) {
error_type(res, "name", "string"); error_type(res, "name", "string");
continue; continue;
} }
if (!param[1].IsFloat() && !param[1].IsInt()) { if (!param[1].IsFloat() && !param[1].IsInt()) {
error_type(res, "state", "float"); error_type(res, "state", "float");
continue; continue;
} }
// get params // get params
auto light_name = param[0].GetString(); auto light_name = param[0].GetString();
auto light_state = param[1].GetFloat(); auto light_state = param[1].GetFloat();
// write light state // write light state
if (!this->write_light(light_name, light_state)) { if (!this->write_light(light_name, light_state)) {
error_unknown(res, "light", light_name); error_unknown(res, "light", light_name);
continue; continue;
} }
} }
} }
/** /**
* write_reset() * write_reset()
* write_reset([name: str], ...) * write_reset([name: str], ...)
*/ */
void Lights::write_reset(Request &req, Response &res) { void Lights::write_reset(Request &req, Response &res) {
// check light cache // check light cache
if (!this->lights) { if (!this->lights) {
return; return;
} }
// get params // get params
auto params = req.params.GetArray(); auto params = req.params.GetArray();
// write_reset() // write_reset()
if (params.Size() == 0) { if (params.Size() == 0) {
if (lights != nullptr) { if (lights != nullptr) {
for (auto &light : *this->lights) { for (auto &light : *this->lights) {
light.override_enabled = false; light.override_enabled = false;
} }
} }
return; return;
} }
// loop parameters // loop parameters
for (Value &param : req.params.GetArray()) { for (Value &param : req.params.GetArray()) {
// check params // check params
if (!param.IsArray()) { if (!param.IsArray()) {
error(res, "parameters must be arrays"); error(res, "parameters must be arrays");
return; return;
} }
if (param.Size() < 1) { if (param.Size() < 1) {
error_params_insufficient(res); error_params_insufficient(res);
continue; continue;
} }
if (!param[0].IsString()) { if (!param[0].IsString()) {
error_type(res, "name", "string"); error_type(res, "name", "string");
continue; continue;
} }
// get params // get params
auto light_name = param[0].GetString(); auto light_name = param[0].GetString();
// write analog state // write analog state
if (!this->write_light_reset(light_name)) { if (!this->write_light_reset(light_name)) {
error_unknown(res, "analog", light_name); error_unknown(res, "analog", light_name);
continue; continue;
} }
} }
} }
bool Lights::write_light(std::string name, float state) { bool Lights::write_light(std::string name, float state) {
// check light cache // check light cache
if (!this->lights) { if (!this->lights) {
return false; return false;
} }
// find light // find light
for (auto &light : *this->lights) { for (auto &light : *this->lights) {
if (light.getName() == name) { if (light.getName() == name) {
light.override_state = CLAMP(state, 0.f, 1.f); light.override_state = CLAMP(state, 0.f, 1.f);
light.override_enabled = true; light.override_enabled = true;
return true; return true;
} }
} }
// unknown light // unknown light
return false; return false;
} }
bool Lights::write_light_reset(std::string name) { bool Lights::write_light_reset(std::string name) {
// check light cache // check light cache
if (!this->lights) { if (!this->lights) {
return false; return false;
} }
// find light // find light
for (auto &light : *this->lights) { for (auto &light : *this->lights) {
if (light.getName() == name) { if (light.getName() == name) {
light.override_enabled = false; light.override_enabled = false;
return true; return true;
} }
} }
// unknown light // unknown light
return false; return false;
} }
} }
+28 -28
View File
@@ -1,28 +1,28 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
#include "cfg/api.h" #include "cfg/api.h"
namespace api::modules { namespace api::modules {
class Lights : public Module { class Lights : public Module {
public: public:
Lights(); Lights();
private: private:
// state // state
std::vector<Light> *lights; std::vector<Light> *lights;
// function definitions // function definitions
void read(Request &req, Response &res); void read(Request &req, Response &res);
void write(Request &req, Response &res); void write(Request &req, Response &res);
void write_reset(Request &req, Response &res); void write_reset(Request &req, Response &res);
// helper // helper
bool write_light(std::string name, float state); bool write_light(std::string name, float state);
bool write_light_reset(std::string name); bool write_light_reset(std::string name);
}; };
} }
+233 -233
View File
@@ -1,233 +1,233 @@
#include "memory.h" #include "memory.h"
#include <functional> #include <functional>
#include <mutex> #include <mutex>
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
#include "util/fileutils.h" #include "util/fileutils.h"
#include "util/libutils.h" #include "util/libutils.h"
#include "util/memutils.h" #include "util/memutils.h"
#include "util/sigscan.h" #include "util/sigscan.h"
#include "util/utils.h" #include "util/utils.h"
using namespace std::placeholders; using namespace std::placeholders;
using namespace rapidjson; using namespace rapidjson;
namespace api::modules { namespace api::modules {
// global lock to prevent simultaneous access to memory // global lock to prevent simultaneous access to memory
static std::mutex MEMORY_LOCK; static std::mutex MEMORY_LOCK;
Memory::Memory() : Module("memory", true) { Memory::Memory() : Module("memory", true) {
functions["write"] = std::bind(&Memory::write, this, _1, _2); functions["write"] = std::bind(&Memory::write, this, _1, _2);
functions["read"] = std::bind(&Memory::read, this, _1, _2); functions["read"] = std::bind(&Memory::read, this, _1, _2);
functions["signature"] = std::bind(&Memory::signature, this, _1, _2); functions["signature"] = std::bind(&Memory::signature, this, _1, _2);
} }
/** /**
* write(dll_name: str, data: hex, offset: uint) * write(dll_name: str, data: hex, offset: uint)
*/ */
void Memory::write(Request &req, Response &res) { void Memory::write(Request &req, Response &res) {
std::lock_guard<std::mutex> lock(MEMORY_LOCK); std::lock_guard<std::mutex> lock(MEMORY_LOCK);
// check params // check params
if (req.params.Size() < 3) { if (req.params.Size() < 3) {
return error_params_insufficient(res); return error_params_insufficient(res);
} }
if (!req.params[0].IsString()) { if (!req.params[0].IsString()) {
return error_type(res, "dll_name", "str"); return error_type(res, "dll_name", "str");
} }
if (!req.params[1].IsString() || (req.params[1].GetStringLength() & 1)) { if (!req.params[1].IsString() || (req.params[1].GetStringLength() & 1)) {
return error_type(res, "data", "hex string"); return error_type(res, "data", "hex string");
} }
if (!req.params[2].IsUint()) { if (!req.params[2].IsUint()) {
return error_type(res, "offset", "uint"); return error_type(res, "offset", "uint");
} }
// get params // get params
auto dll_name = req.params[0].GetString(); auto dll_name = req.params[0].GetString();
auto dll_path = MODULE_PATH / dll_name; auto dll_path = MODULE_PATH / dll_name;
auto data = req.params[1].GetString(); auto data = req.params[1].GetString();
intptr_t offset = req.params[2].GetUint(); intptr_t offset = req.params[2].GetUint();
// convert data to bin // convert data to bin
size_t data_bin_size = strlen(data) / 2; size_t data_bin_size = strlen(data) / 2;
auto data_bin = std::make_unique<uint8_t[]>(data_bin_size); auto data_bin = std::make_unique<uint8_t[]>(data_bin_size);
hex2bin(data, data_bin.get()); hex2bin(data, data_bin.get());
// check if file exists in modules // check if file exists in modules
if (!fileutils::file_exists(dll_path)) { if (!fileutils::file_exists(dll_path)) {
return error(res, "Couldn't find " + dll_path.string()); return error(res, "Couldn't find " + dll_path.string());
} }
// get module // get module
auto module = libutils::try_module(dll_name); auto module = libutils::try_module(dll_name);
if (!module) { if (!module) {
return error(res, "Couldn't find module."); return error(res, "Couldn't find module.");
} }
// convert offset to RVA // convert offset to RVA
offset = libutils::offset2rva(dll_path, offset); offset = libutils::offset2rva(dll_path, offset);
if (offset == ~0) { if (offset == ~0) {
return error(res, "Couldn't convert offset to RVA."); return error(res, "Couldn't convert offset to RVA.");
} }
// get module information // get module information
MODULEINFO module_info {}; MODULEINFO module_info {};
if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(MODULEINFO))) { if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(MODULEINFO))) {
return error(res, "Couldn't get module information."); return error(res, "Couldn't get module information.");
} }
// check bounds // check bounds
if (offset + data_bin_size >= (size_t) module_info.lpBaseOfDll + module_info.SizeOfImage) { if (offset + data_bin_size >= (size_t) module_info.lpBaseOfDll + module_info.SizeOfImage) {
return error(res, "Data out of bounds."); return error(res, "Data out of bounds.");
} }
auto data_pos = reinterpret_cast<uint8_t *>(module_info.lpBaseOfDll) + offset; auto data_pos = reinterpret_cast<uint8_t *>(module_info.lpBaseOfDll) + offset;
// replace data // replace data
memutils::VProtectGuard guard(data_pos, data_bin_size); memutils::VProtectGuard guard(data_pos, data_bin_size);
memcpy(data_pos, data_bin.get(), data_bin_size); memcpy(data_pos, data_bin.get(), data_bin_size);
} }
/** /**
* read(dll_name: str, offset: uint, size: uint) * read(dll_name: str, offset: uint, size: uint)
*/ */
void Memory::read(Request &req, Response &res) { void Memory::read(Request &req, Response &res) {
std::lock_guard<std::mutex> lock(MEMORY_LOCK); std::lock_guard<std::mutex> lock(MEMORY_LOCK);
// check params // check params
if (req.params.Size() < 3) { if (req.params.Size() < 3) {
return error_params_insufficient(res); return error_params_insufficient(res);
} }
if (!req.params[0].IsString()) { if (!req.params[0].IsString()) {
return error_type(res, "dll_name", "str"); return error_type(res, "dll_name", "str");
} }
if (!req.params[1].IsUint()) { if (!req.params[1].IsUint()) {
return error_type(res, "offset", "uint"); return error_type(res, "offset", "uint");
} }
if (!req.params[2].IsUint()) { if (!req.params[2].IsUint()) {
return error_type(res, "size", "uint"); return error_type(res, "size", "uint");
} }
// get params // get params
auto dll_name = req.params[0].GetString(); auto dll_name = req.params[0].GetString();
auto dll_path = MODULE_PATH / dll_name; auto dll_path = MODULE_PATH / dll_name;
intptr_t offset = req.params[1].GetUint(); intptr_t offset = req.params[1].GetUint();
auto size = req.params[2].GetUint(); auto size = req.params[2].GetUint();
// check if file exists in modules // check if file exists in modules
if (!fileutils::file_exists(dll_path)) { if (!fileutils::file_exists(dll_path)) {
return error(res, "Couldn't find " + dll_path.string()); return error(res, "Couldn't find " + dll_path.string());
} }
// get module // get module
auto module = libutils::try_module(dll_name); auto module = libutils::try_module(dll_name);
if (!module) { if (!module) {
return error(res, "Couldn't find module."); return error(res, "Couldn't find module.");
} }
// convert offset to RVA // convert offset to RVA
offset = libutils::offset2rva(dll_path, offset); offset = libutils::offset2rva(dll_path, offset);
if (offset == ~0) { if (offset == ~0) {
return error(res, "Couldn't convert offset to RVA."); return error(res, "Couldn't convert offset to RVA.");
} }
// get module information // get module information
MODULEINFO module_info {}; MODULEINFO module_info {};
if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(MODULEINFO))) { if (!GetModuleInformation(GetCurrentProcess(), module, &module_info, sizeof(MODULEINFO))) {
return error(res, "Couldn't get module information."); return error(res, "Couldn't get module information.");
} }
// check bounds // check bounds
auto max = offset + size; auto max = offset + size;
if ((size_t) max >= (size_t) module_info.lpBaseOfDll + module_info.SizeOfImage) { if ((size_t) max >= (size_t) module_info.lpBaseOfDll + module_info.SizeOfImage) {
return error(res, "Data out of bounds."); return error(res, "Data out of bounds.");
} }
// read memory to hex (without virtual protect) // read memory to hex (without virtual protect)
std::string hex = bin2hex((uint8_t*) module_info.lpBaseOfDll + offset, size); std::string hex = bin2hex((uint8_t*) module_info.lpBaseOfDll + offset, size);
Value hex_val(hex.c_str(), res.doc()->GetAllocator()); Value hex_val(hex.c_str(), res.doc()->GetAllocator());
res.add_data(hex_val); res.add_data(hex_val);
} }
/** /**
* signature( * signature(
* dll_name: str, * dll_name: str,
* signature: hex, * signature: hex,
* replacement: hex, * replacement: hex,
* offset: uint, * offset: uint,
* usage: uint) * usage: uint)
* *
* Both signature and replacement will ignore bytes specified as "??" in the hex string. * Both signature and replacement will ignore bytes specified as "??" in the hex string.
* The offset specifies the offset between the found signature and the position to write the replacement to. * The offset specifies the offset between the found signature and the position to write the replacement to.
* The resulting integer is the file offset where the replacement was written to. * The resulting integer is the file offset where the replacement was written to.
*/ */
void Memory::signature(Request &req, Response &res) { void Memory::signature(Request &req, Response &res) {
std::lock_guard<std::mutex> lock(MEMORY_LOCK); std::lock_guard<std::mutex> lock(MEMORY_LOCK);
// check params // check params
if (req.params.Size() < 5) { if (req.params.Size() < 5) {
return error_params_insufficient(res); return error_params_insufficient(res);
} }
if (!req.params[0].IsString()) { if (!req.params[0].IsString()) {
return error_type(res, "dll_name", "string"); return error_type(res, "dll_name", "string");
} }
if (!req.params[1].IsString() || (req.params[1].GetStringLength() & 1)) { if (!req.params[1].IsString() || (req.params[1].GetStringLength() & 1)) {
return error_type(res, "signature", "hex string"); return error_type(res, "signature", "hex string");
} }
if (!req.params[2].IsString() || (req.params[2].GetStringLength() & 1)) { if (!req.params[2].IsString() || (req.params[2].GetStringLength() & 1)) {
return error_type(res, "replacement", "hex string"); return error_type(res, "replacement", "hex string");
} }
if (!req.params[3].IsUint()) { if (!req.params[3].IsUint()) {
return error_type(res, "offset", "uint"); return error_type(res, "offset", "uint");
} }
if (!req.params[4].IsUint()) { if (!req.params[4].IsUint()) {
return error_type(res, "usage", "uint"); return error_type(res, "usage", "uint");
} }
// get params // get params
auto dll_name = req.params[0].GetString(); auto dll_name = req.params[0].GetString();
auto dll_path = MODULE_PATH / dll_name; auto dll_path = MODULE_PATH / dll_name;
auto signature = req.params[1].GetString(); auto signature = req.params[1].GetString();
auto replacement = req.params[2].GetString(); auto replacement = req.params[2].GetString();
auto offset = req.params[3].GetUint(); auto offset = req.params[3].GetUint();
auto usage = req.params[4].GetUint(); auto usage = req.params[4].GetUint();
// check if file exists in modules // check if file exists in modules
if (!fileutils::file_exists(dll_path)) { if (!fileutils::file_exists(dll_path)) {
return error(res, "Couldn't find " + dll_path.string()); return error(res, "Couldn't find " + dll_path.string());
} }
// get module // get module
auto module = libutils::try_module(dll_name); auto module = libutils::try_module(dll_name);
if (!module) { if (!module) {
return error(res, "Couldn't find module."); return error(res, "Couldn't find module.");
} }
// execute // execute
auto result = replace_pattern( auto result = replace_pattern(
module, module,
signature, signature,
replacement, replacement,
offset, offset,
usage usage
); );
// check result // check result
if (!result) { if (!result) {
return error(res, std::string("Pattern not found in memory of ") + dll_name); return error(res, std::string("Pattern not found in memory of ") + dll_name);
} }
// convert to offset // convert to offset
auto rva = result - reinterpret_cast<intptr_t>(module); auto rva = result - reinterpret_cast<intptr_t>(module);
result = libutils::rva2offset(dll_path, rva); result = libutils::rva2offset(dll_path, rva);
if (result == -1) { if (result == -1) {
return error(res, "Couldn't convert RVA to file offset."); return error(res, "Couldn't convert RVA to file offset.");
} }
// add result // add result
Value result_val(result); Value result_val(result);
res.add_data(result_val); res.add_data(result_val);
} }
} }
+19 -19
View File
@@ -1,19 +1,19 @@
#pragma once #pragma once
#include "api/module.h" #include "api/module.h"
#include "api/request.h" #include "api/request.h"
namespace api::modules { namespace api::modules {
class Memory : public Module { class Memory : public Module {
public: public:
Memory(); Memory();
private: private:
// function definitions // function definitions
void write(Request &req, Response &res); void write(Request &req, Response &res);
void read(Request &req, Response &res); void read(Request &req, Response &res);
void signature(Request &req, Response &res); void signature(Request &req, Response &res);
}; };
} }
+55 -55
View File
@@ -1,55 +1,55 @@
#include "request.h" #include "request.h"
#include "../util/logging.h" #include "../util/logging.h"
#include "module.h" #include "module.h"
using namespace rapidjson; using namespace rapidjson;
namespace api { namespace api {
Request::Request(rapidjson::Document &document) { Request::Request(rapidjson::Document &document) {
Value::MemberIterator it; Value::MemberIterator it;
this->parse_error = false; this->parse_error = false;
// get ID // get ID
it = document.FindMember("id"); it = document.FindMember("id");
if (it == document.MemberEnd() || !(*it).value.IsUint64()) { if (it == document.MemberEnd() || !(*it).value.IsUint64()) {
log_warning("api", "Request ID is invalid"); log_warning("api", "Request ID is invalid");
this->parse_error = true; this->parse_error = true;
return; return;
} }
this->id = (*it).value.GetUint64(); this->id = (*it).value.GetUint64();
// get module // get module
it = document.FindMember("module"); it = document.FindMember("module");
if (it == document.MemberEnd() || !(*it).value.IsString()) { if (it == document.MemberEnd() || !(*it).value.IsString()) {
log_warning("api", "Request module is invalid"); log_warning("api", "Request module is invalid");
this->parse_error = true; this->parse_error = true;
return; return;
} }
this->module = (*it).value.GetString(); this->module = (*it).value.GetString();
// get function // get function
it = document.FindMember("function"); it = document.FindMember("function");
if (it == document.MemberEnd() || !(*it).value.IsString()) { if (it == document.MemberEnd() || !(*it).value.IsString()) {
log_warning("api", "Request function is invalid"); log_warning("api", "Request function is invalid");
this->parse_error = true; this->parse_error = true;
return; return;
} }
this->function = (*it).value.GetString(); this->function = (*it).value.GetString();
// get params // get params
it = document.FindMember("params"); it = document.FindMember("params");
if (it == document.MemberEnd() || !(*it).value.IsArray()) { if (it == document.MemberEnd() || !(*it).value.IsArray()) {
log_warning("api", "Request params is invalid"); log_warning("api", "Request params is invalid");
this->parse_error = true; this->parse_error = true;
return; return;
} }
this->params = document["params"]; this->params = document["params"];
// log request // log request
if (LOGGING) { if (LOGGING) {
log_info("api", "new request > id: {}, module: {}, function: {}", log_info("api", "new request > id: {}, module: {}, function: {}",
this->id, this->module, this->function); this->id, this->module, this->function);
} }
} }
} }
+21 -21
View File
@@ -1,21 +1,21 @@
#pragma once #pragma once
#include <string> #include <string>
#include <stdint.h> #include <stdint.h>
#include "external/rapidjson/document.h" #include "external/rapidjson/document.h"
namespace api { namespace api {
class Request { class Request {
public: public:
uint64_t id; uint64_t id;
std::string module; std::string module;
std::string function; std::string function;
rapidjson::Value params; rapidjson::Value params;
bool parse_error; bool parse_error;
Request(rapidjson::Document &document); Request(rapidjson::Document &document);
}; };
} }
+4 -4
View File
@@ -1,4 +1,4 @@
# SpiceAPI Arduino Library # SpiceAPI Arduino Library
This library is still a bit experimental and might contain bugs. This library is still a bit experimental and might contain bugs.
To use this library, it's recommended to just copy the Arduino project and start from that. To use this library, it's recommended to just copy the Arduino project and start from that.
+65 -65
View File
@@ -1,65 +1,65 @@
#ifndef SPICEAPI_RC4_H #ifndef SPICEAPI_RC4_H
#define SPICEAPI_RC4_H #define SPICEAPI_RC4_H
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
namespace spiceapi { namespace spiceapi {
class RC4 { class RC4 {
private: private:
uint8_t s_box[256]; uint8_t s_box[256];
size_t a = 0, b = 0; size_t a = 0, b = 0;
public: public:
RC4(uint8_t *key, size_t key_size); RC4(uint8_t *key, size_t key_size);
void crypt(uint8_t *data, size_t size); void crypt(uint8_t *data, size_t size);
}; };
} }
spiceapi::RC4::RC4(uint8_t *key, size_t key_size) { spiceapi::RC4::RC4(uint8_t *key, size_t key_size) {
// initialize S-BOX // initialize S-BOX
for (size_t i = 0; i < sizeof(s_box); i++) for (size_t i = 0; i < sizeof(s_box); i++)
s_box[i] = (uint8_t) i; s_box[i] = (uint8_t) i;
// check key size // check key size
if (!key_size) if (!key_size)
return; return;
// KSA // KSA
size_t j = 0; size_t j = 0;
for (size_t i = 0; i < sizeof(s_box); i++) { for (size_t i = 0; i < sizeof(s_box); i++) {
// update // update
j = (j + s_box[i] + key[i % key_size]) % sizeof(s_box); j = (j + s_box[i] + key[i % key_size]) % sizeof(s_box);
// swap // swap
auto tmp = s_box[i]; auto tmp = s_box[i];
s_box[i] = s_box[j]; s_box[i] = s_box[j];
s_box[j] = tmp; s_box[j] = tmp;
} }
} }
void spiceapi::RC4::crypt(uint8_t *data, size_t size) { void spiceapi::RC4::crypt(uint8_t *data, size_t size) {
// iterate all bytes // iterate all bytes
for (size_t pos = 0; pos < size; pos++) { for (size_t pos = 0; pos < size; pos++) {
// update // update
a = (a + 1) % sizeof(s_box); a = (a + 1) % sizeof(s_box);
b = (b + s_box[a]) % sizeof(s_box); b = (b + s_box[a]) % sizeof(s_box);
// swap // swap
auto tmp = s_box[a]; auto tmp = s_box[a];
s_box[a] = s_box[b]; s_box[a] = s_box[b];
s_box[b] = tmp; s_box[b] = tmp;
// crypt // crypt
data[pos] ^= s_box[(s_box[a] + s_box[b]) % sizeof(s_box)]; data[pos] ^= s_box[(s_box[a] + s_box[b]) % sizeof(s_box)];
} }
} }
#endif //SPICEAPI_RC4_H #endif //SPICEAPI_RC4_H
+172 -172
View File
@@ -1,172 +1,172 @@
/* /*
* SpiceAPI Arduino Example Project * SpiceAPI Arduino Example Project
* *
* To enable it in SpiceTools, use "-api 1337 -apipass changeme -apiserial COM1" or similar. * To enable it in SpiceTools, use "-api 1337 -apipass changeme -apiserial COM1" or similar.
*/ */
/* /*
* SpiceAPI Wrapper Buffer Sizes * SpiceAPI Wrapper Buffer Sizes
* *
* They should be as big as possible to be able to create/parse * They should be as big as possible to be able to create/parse
* some of the bigger requests/responses. Due to dynamic memory * some of the bigger requests/responses. Due to dynamic memory
* limitations of some weaker devices, if you set them too high * limitations of some weaker devices, if you set them too high
* you will probably experience crashes/bugs/problems, one * you will probably experience crashes/bugs/problems, one
* example would be "Request ID is invalid" in the log. * example would be "Request ID is invalid" in the log.
*/ */
#define SPICEAPI_WRAPPER_BUFFER_SIZE 256 #define SPICEAPI_WRAPPER_BUFFER_SIZE 256
#define SPICEAPI_WRAPPER_BUFFER_SIZE_STR 256 #define SPICEAPI_WRAPPER_BUFFER_SIZE_STR 256
/* /*
* WiFi Support * WiFi Support
* Uncomment to enable the wireless API interface. * Uncomment to enable the wireless API interface.
*/ */
//#define ENABLE_WIFI //#define ENABLE_WIFI
/* /*
* WiFi Settings * WiFi Settings
* You can ignore these if you don't plan on using WiFi * You can ignore these if you don't plan on using WiFi
*/ */
#ifdef ENABLE_WIFI #ifdef ENABLE_WIFI
#include <ESP8266WiFi.h> #include <ESP8266WiFi.h>
WiFiClient client; WiFiClient client;
#define SPICEAPI_INTERFACE client #define SPICEAPI_INTERFACE client
#define SPICEAPI_INTERFACE_WIFICLIENT #define SPICEAPI_INTERFACE_WIFICLIENT
#define SPICEAPI_INTERFACE_WIFICLIENT_HOST "192.168.178.143" #define SPICEAPI_INTERFACE_WIFICLIENT_HOST "192.168.178.143"
#define SPICEAPI_INTERFACE_WIFICLIENT_PORT 1337 #define SPICEAPI_INTERFACE_WIFICLIENT_PORT 1337
#define WIFI_SSID "MySSID" #define WIFI_SSID "MySSID"
#define WIFI_PASS "MyWifiPassword" #define WIFI_PASS "MyWifiPassword"
#endif #endif
/* /*
* This is the interface a serial connection will use. * This is the interface a serial connection will use.
* You can change this to another Serial port, e.g. with an * You can change this to another Serial port, e.g. with an
* Arduino Mega you can use Serial1/Serial2/Serial3. * Arduino Mega you can use Serial1/Serial2/Serial3.
*/ */
#ifndef ENABLE_WIFI #ifndef ENABLE_WIFI
#define SPICEAPI_INTERFACE Serial #define SPICEAPI_INTERFACE Serial
#endif #endif
/* /*
* SpiceAPI Includes * SpiceAPI Includes
* *
* If you have the JSON strings beforehands or want to craft them * If you have the JSON strings beforehands or want to craft them
* manually, you don't have to import the wrappers at all and can * manually, you don't have to import the wrappers at all and can
* use Connection::request to send and receive raw JSON strings. * use Connection::request to send and receive raw JSON strings.
*/ */
#include "connection.h" #include "connection.h"
#include "wrappers.h" #include "wrappers.h"
/* /*
* This global object represents the API connection. * This global object represents the API connection.
* The first parameter is the buffer size of the JSON string * The first parameter is the buffer size of the JSON string
* we're receiving. So a size of 512 will only be able to * we're receiving. So a size of 512 will only be able to
* hold a JSON of 512 characters maximum. * hold a JSON of 512 characters maximum.
* *
* An empty password string means no password is being used. * An empty password string means no password is being used.
* This is the recommended when using Serial only. * This is the recommended when using Serial only.
*/ */
spiceapi::Connection CON(512, "changeme"); spiceapi::Connection CON(512, "changeme");
void setup() { void setup() {
#ifdef ENABLE_WIFI #ifdef ENABLE_WIFI
/* /*
* When using WiFi, we can use the Serial interface for debugging. * When using WiFi, we can use the Serial interface for debugging.
* You can open Serial Monitor and see what IP it gets assigned to. * You can open Serial Monitor and see what IP it gets assigned to.
*/ */
Serial.begin(57600); Serial.begin(57600);
// set WiFi mode to station (disables integrated AP) // set WiFi mode to station (disables integrated AP)
WiFi.mode(WIFI_STA); WiFi.mode(WIFI_STA);
// now try connecting to our Router/AP // now try connecting to our Router/AP
Serial.print("Connecting"); Serial.print("Connecting");
WiFi.begin(WIFI_SSID, WIFI_PASS); WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) { while (WiFi.status() != WL_CONNECTED) {
delay(500); delay(500);
Serial.print("."); Serial.print(".");
} }
// print debug info over serial // print debug info over serial
Serial.print("\nLocal IP: "); Serial.print("\nLocal IP: ");
Serial.println(WiFi.localIP()); Serial.println(WiFi.localIP());
#else #else
/* /*
* Since the API makes use of the Serial module, we need to * Since the API makes use of the Serial module, we need to
* set it up using our preferred baud rate manually. * set it up using our preferred baud rate manually.
*/ */
SPICEAPI_INTERFACE.begin(57600); SPICEAPI_INTERFACE.begin(57600);
while (!SPICEAPI_INTERFACE); while (!SPICEAPI_INTERFACE);
#endif #endif
} }
void loop() { void loop() {
/* /*
* Here's a few tests/examples on how to make use of the wrappers. * Here's a few tests/examples on how to make use of the wrappers.
*/ */
// insert cards for P1/P2 // insert cards for P1/P2
spiceapi::card_insert(CON, 0, "E004012345678901"); spiceapi::card_insert(CON, 0, "E004012345678901");
spiceapi::card_insert(CON, 1, "E004012345678902"); spiceapi::card_insert(CON, 1, "E004012345678902");
// insert a single coin / multiple coins // insert a single coin / multiple coins
spiceapi::coin_insert(CON); spiceapi::coin_insert(CON);
spiceapi::coin_insert(CON, 3); spiceapi::coin_insert(CON, 3);
// get the IIDX led ticker text // get the IIDX led ticker text
char ticker[9]; char ticker[9];
if (spiceapi::iidx_ticker_get(CON, ticker)) { if (spiceapi::iidx_ticker_get(CON, ticker)) {
// if a function returns true, that means success // if a function returns true, that means success
// now we can do something with the ticker as if it was a string // now we can do something with the ticker as if it was a string
//Serial1.println(ticker); //Serial1.println(ticker);
} }
// get AVS info // get AVS info
spiceapi::InfoAvs avs_info {}; spiceapi::InfoAvs avs_info {};
if (spiceapi::info_avs(CON, avs_info)) { if (spiceapi::info_avs(CON, avs_info)) {
//Serial1.println(avs_info.model); //Serial1.println(avs_info.model);
} }
// enter some keys on P1 keypad (blocks until sequence is entered fully) // enter some keys on P1 keypad (blocks until sequence is entered fully)
spiceapi::keypads_write(CON, 0, "1234"); spiceapi::keypads_write(CON, 0, "1234");
// get light states // get light states
spiceapi::LightState lights[8]; spiceapi::LightState lights[8];
size_t lights_size = spiceapi::lights_read(CON, lights, 8); size_t lights_size = spiceapi::lights_read(CON, lights, 8);
for (size_t i = 0; i < lights_size; i++) { for (size_t i = 0; i < lights_size; i++) {
auto &light = lights[i]; auto &light = lights[i];
//Serial1.println(light.name); //Serial1.println(light.name);
//Serial1.println(light.value); //Serial1.println(light.value);
// modify value to full bright // modify value to full bright
light.value = 1.f; light.value = 1.f;
} }
// send back modified light states // send back modified light states
spiceapi::lights_write(CON, lights, lights_size); spiceapi::lights_write(CON, lights, lights_size);
// refresh session (generates new crypt key, not that important for serial) // refresh session (generates new crypt key, not that important for serial)
spiceapi::control_session_refresh(CON); spiceapi::control_session_refresh(CON);
// you can also manually send requests without the wrappers // you can also manually send requests without the wrappers
// this avoids json generation, but you still need to parse it in some way // this avoids json generation, but you still need to parse it in some way
const char *answer_json = CON.request( const char *answer_json = CON.request(
"{" "{"
"\"id\": 0," "\"id\": 0,"
"\"module\":\"coin\"," "\"module\":\"coin\","
"\"function\":\"insert\"," "\"function\":\"insert\","
"\"params\":[]" "\"params\":[]"
"}" "}"
); );
/* /*
* For more functions/information, just check out wrappers.h yourself. * For more functions/information, just check out wrappers.h yourself.
* Have fun :) * Have fun :)
*/ */
delay(5000); delay(5000);
} }
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -1,8 +1,8 @@
# SpiceAPI C++ Library # SpiceAPI C++ Library
This library is still a bit experimental and might contain bugs. This library is still a bit experimental and might contain bugs.
To include it into your project, it's recommended to just copy the To include it into your project, it's recommended to just copy the
files into your source directory. files into your source directory.
To use the wrappers, RapidJSON is required and you might need to To use the wrappers, RapidJSON is required and you might need to
adjust the include paths for your project's build. adjust the include paths for your project's build.
+24 -24
View File
@@ -1,24 +1,24 @@
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any binary, for any purpose, commercial or non-commercial, and by any
means. means.
In jurisdictions that recognize copyright laws, the author or authors In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this relinquishment in perpetuity of all present and future rights to this
software under copyright law. software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
+181 -181
View File
@@ -1,181 +1,181 @@
#include <iostream> #include <iostream>
#include <ws2tcpip.h> #include <ws2tcpip.h>
#include "connection.h" #include "connection.h"
namespace spiceapi { namespace spiceapi {
// settings // settings
static const size_t RECEIVE_BUFFER_SIZE = 64 * 1024; static const size_t RECEIVE_BUFFER_SIZE = 64 * 1024;
static const int RECEIVE_TIMEOUT = 1000; static const int RECEIVE_TIMEOUT = 1000;
} }
spiceapi::Connection::Connection(std::string host, uint16_t port, std::string password) { spiceapi::Connection::Connection(std::string host, uint16_t port, std::string password) {
this->host = host; this->host = host;
this->port = port; this->port = port;
this->password = password; this->password = password;
this->socket = INVALID_SOCKET; this->socket = INVALID_SOCKET;
this->cipher = nullptr; this->cipher = nullptr;
// WSA startup // WSA startup
WSADATA wsa_data; WSADATA wsa_data;
int error = WSAStartup(MAKEWORD(2, 2), &wsa_data); int error = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (error) { if (error) {
std::cerr << "Failed to start WSA: " << error << std::endl; std::cerr << "Failed to start WSA: " << error << std::endl;
exit(1); exit(1);
} }
} }
spiceapi::Connection::~Connection() { spiceapi::Connection::~Connection() {
// clean up // clean up
if (this->cipher != nullptr) if (this->cipher != nullptr)
delete this->cipher; delete this->cipher;
// cleanup WSA // cleanup WSA
WSACleanup(); WSACleanup();
} }
void spiceapi::Connection::cipher_alloc() { void spiceapi::Connection::cipher_alloc() {
// delete old cipher // delete old cipher
if (this->cipher != nullptr) { if (this->cipher != nullptr) {
delete this->cipher; delete this->cipher;
this->cipher = nullptr; this->cipher = nullptr;
} }
// create new cipher if password is set // create new cipher if password is set
if (this->password.length() > 0) { if (this->password.length() > 0) {
this->cipher = new RC4( this->cipher = new RC4(
(uint8_t *) this->password.c_str(), (uint8_t *) this->password.c_str(),
strlen(this->password.c_str())); strlen(this->password.c_str()));
} }
} }
bool spiceapi::Connection::check() { bool spiceapi::Connection::check() {
int result = 0; int result = 0;
// check if socket is invalid // check if socket is invalid
if (this->socket == INVALID_SOCKET) { if (this->socket == INVALID_SOCKET) {
// get all addresses // get all addresses
addrinfo *addr_list; addrinfo *addr_list;
addrinfo hints{}; addrinfo hints{};
hints.ai_family = AF_UNSPEC; hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP; hints.ai_protocol = IPPROTO_TCP;
if ((result = getaddrinfo( if ((result = getaddrinfo(
this->host.c_str(), this->host.c_str(),
std::to_string(this->port).c_str(), std::to_string(this->port).c_str(),
&hints, &hints,
&addr_list))) { &addr_list))) {
std::cerr << "getaddrinfo failed: " << result << std::endl; std::cerr << "getaddrinfo failed: " << result << std::endl;
return false; return false;
} }
// check all addresses // check all addresses
for (addrinfo *addr = addr_list; addr != NULL; addr = addr->ai_next) { for (addrinfo *addr = addr_list; addr != NULL; addr = addr->ai_next) {
// try open socket // try open socket
this->socket = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); this->socket = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
if (this->socket == INVALID_SOCKET) { if (this->socket == INVALID_SOCKET) {
std::cerr << "socket failed: " << WSAGetLastError() << std::endl; std::cerr << "socket failed: " << WSAGetLastError() << std::endl;
freeaddrinfo(addr_list); freeaddrinfo(addr_list);
return false; return false;
} }
// try connect // try connect
result = connect(this->socket, addr->ai_addr, (int) addr->ai_addrlen); result = connect(this->socket, addr->ai_addr, (int) addr->ai_addrlen);
if (result == SOCKET_ERROR) { if (result == SOCKET_ERROR) {
closesocket(this->socket); closesocket(this->socket);
this->socket = INVALID_SOCKET; this->socket = INVALID_SOCKET;
continue; continue;
} }
// configure socket // configure socket
int opt_val; int opt_val;
opt_val = 1; opt_val = 1;
setsockopt(this->socket, IPPROTO_TCP, TCP_NODELAY, (const char*) &opt_val, sizeof(opt_val)); setsockopt(this->socket, IPPROTO_TCP, TCP_NODELAY, (const char*) &opt_val, sizeof(opt_val));
opt_val = RECEIVE_TIMEOUT; opt_val = RECEIVE_TIMEOUT;
setsockopt(this->socket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &opt_val, sizeof(opt_val)); setsockopt(this->socket, SOL_SOCKET, SO_RCVTIMEO, (const char*) &opt_val, sizeof(opt_val));
// connection successful // connection successful
this->cipher_alloc(); this->cipher_alloc();
break; break;
} }
// check if successful // check if successful
freeaddrinfo(addr_list); freeaddrinfo(addr_list);
if (this->socket == INVALID_SOCKET) { if (this->socket == INVALID_SOCKET) {
return false; return false;
} }
} }
// socket probably still valid // socket probably still valid
return true; return true;
} }
void spiceapi::Connection::change_pass(std::string password) { void spiceapi::Connection::change_pass(std::string password) {
this->password = password; this->password = password;
this->cipher_alloc(); this->cipher_alloc();
} }
std::string spiceapi::Connection::request(std::string json) { std::string spiceapi::Connection::request(std::string json) {
// check connection // check connection
if (!this->check()) if (!this->check())
return ""; return "";
// crypt // crypt
auto json_len = strlen(json.c_str()) + 1; auto json_len = strlen(json.c_str()) + 1;
uint8_t* json_data = new uint8_t[json_len]; uint8_t* json_data = new uint8_t[json_len];
memcpy(json_data, json.c_str(), json_len); memcpy(json_data, json.c_str(), json_len);
if (this->cipher != nullptr) if (this->cipher != nullptr)
this->cipher->crypt(json_data, json_len); this->cipher->crypt(json_data, json_len);
// send // send
auto send_result = send(this->socket, (const char*) json_data, (int) json_len, 0); auto send_result = send(this->socket, (const char*) json_data, (int) json_len, 0);
delete[] json_data; delete[] json_data;
if (send_result == SOCKET_ERROR || send_result < (int) json_len) { if (send_result == SOCKET_ERROR || send_result < (int) json_len) {
closesocket(this->socket); closesocket(this->socket);
this->socket = INVALID_SOCKET; this->socket = INVALID_SOCKET;
return ""; return "";
} }
// receive // receive
uint8_t receive_data[RECEIVE_BUFFER_SIZE]; uint8_t receive_data[RECEIVE_BUFFER_SIZE];
size_t receive_data_len = 0; size_t receive_data_len = 0;
int receive_result; int receive_result;
while ((receive_result = recv( while ((receive_result = recv(
this->socket, this->socket,
(char*) &receive_data[receive_data_len], (char*) &receive_data[receive_data_len],
sizeof(receive_data) - receive_data_len, 0)) > 0) { sizeof(receive_data) - receive_data_len, 0)) > 0) {
// check for buffer overflow // check for buffer overflow
if (receive_data_len + receive_result >= sizeof(receive_data)) { if (receive_data_len + receive_result >= sizeof(receive_data)) {
closesocket(this->socket); closesocket(this->socket);
this->socket = INVALID_SOCKET; this->socket = INVALID_SOCKET;
return ""; return "";
} }
// crypt // crypt
if (this->cipher != nullptr) if (this->cipher != nullptr)
this->cipher->crypt(&receive_data[receive_data_len], (size_t) receive_result); this->cipher->crypt(&receive_data[receive_data_len], (size_t) receive_result);
// increase received data length // increase received data length
receive_data_len += receive_result; receive_data_len += receive_result;
// check for message end // check for message end
if (receive_data[receive_data_len - 1] == 0) if (receive_data[receive_data_len - 1] == 0)
break; break;
} }
// return resulting json // return resulting json
if (receive_data_len > 0) { if (receive_data_len > 0) {
return std::string((const char *) &receive_data[0], receive_data_len - 1); return std::string((const char *) &receive_data[0], receive_data_len - 1);
} else { } else {
// receive error // receive error
this->socket = INVALID_SOCKET; this->socket = INVALID_SOCKET;
return ""; return "";
} }
} }
+31 -31
View File
@@ -1,31 +1,31 @@
#ifndef SPICEAPI_CONNECTION_H #ifndef SPICEAPI_CONNECTION_H
#define SPICEAPI_CONNECTION_H #define SPICEAPI_CONNECTION_H
#include <string> #include <string>
#include <winsock2.h> #include <winsock2.h>
#include "rc4.h" #include "rc4.h"
namespace spiceapi { namespace spiceapi {
class Connection { class Connection {
private: private:
std::string host; std::string host;
uint16_t port; uint16_t port;
std::string password; std::string password;
SOCKET socket; SOCKET socket;
RC4* cipher; RC4* cipher;
void cipher_alloc(); void cipher_alloc();
public: public:
Connection(std::string host, uint16_t port, std::string password = ""); Connection(std::string host, uint16_t port, std::string password = "");
~Connection(); ~Connection();
bool check(); bool check();
void change_pass(std::string password); void change_pass(std::string password);
std::string request(std::string json); std::string request(std::string json);
}; };
} }
#endif //SPICEAPI_CONNECTION_H #endif //SPICEAPI_CONNECTION_H
+45 -45
View File
@@ -1,45 +1,45 @@
#include "rc4.h" #include "rc4.h"
#include <iterator> #include <iterator>
spiceapi::RC4::RC4(uint8_t *key, size_t key_size) { spiceapi::RC4::RC4(uint8_t *key, size_t key_size) {
// initialize S-BOX // initialize S-BOX
for (size_t i = 0; i < std::size(s_box); i++) for (size_t i = 0; i < std::size(s_box); i++)
s_box[i] = (uint8_t) i; s_box[i] = (uint8_t) i;
// check key size // check key size
if (!key_size) if (!key_size)
return; return;
// KSA // KSA
size_t j = 0; size_t j = 0;
for (size_t i = 0; i < std::size(s_box); i++) { for (size_t i = 0; i < std::size(s_box); i++) {
// update // update
j = (j + s_box[i] + key[i % key_size]) % std::size(s_box); j = (j + s_box[i] + key[i % key_size]) % std::size(s_box);
// swap // swap
auto tmp = s_box[i]; auto tmp = s_box[i];
s_box[i] = s_box[j]; s_box[i] = s_box[j];
s_box[j] = tmp; s_box[j] = tmp;
} }
} }
void spiceapi::RC4::crypt(uint8_t *data, size_t size) { void spiceapi::RC4::crypt(uint8_t *data, size_t size) {
// iterate all bytes // iterate all bytes
for (size_t pos = 0; pos < size; pos++) { for (size_t pos = 0; pos < size; pos++) {
// update // update
a = (a + 1) % std::size(s_box); a = (a + 1) % std::size(s_box);
b = (b + s_box[a]) % std::size(s_box); b = (b + s_box[a]) % std::size(s_box);
// swap // swap
auto tmp = s_box[a]; auto tmp = s_box[a];
s_box[a] = s_box[b]; s_box[a] = s_box[b];
s_box[b] = tmp; s_box[b] = tmp;
// crypt // crypt
data[pos] ^= s_box[(s_box[a] + s_box[b]) % std::size(s_box)]; data[pos] ^= s_box[(s_box[a] + s_box[b]) % std::size(s_box)];
} }
} }
+21 -21
View File
@@ -1,21 +1,21 @@
#ifndef SPICEAPI_RC4_H #ifndef SPICEAPI_RC4_H
#define SPICEAPI_RC4_H #define SPICEAPI_RC4_H
#include <cstdint> #include <cstdint>
namespace spiceapi { namespace spiceapi {
class RC4 { class RC4 {
private: private:
uint8_t s_box[256]; uint8_t s_box[256];
size_t a = 0, b = 0; size_t a = 0, b = 0;
public: public:
RC4(uint8_t *key, size_t key_size); RC4(uint8_t *key, size_t key_size);
void crypt(uint8_t *data, size_t size); void crypt(uint8_t *data, size_t size);
}; };
} }
#endif //SPICEAPI_RC4_H #endif //SPICEAPI_RC4_H
File diff suppressed because it is too large Load Diff
+104 -104
View File
@@ -1,104 +1,104 @@
#ifndef SPICEAPI_WRAPPERS_H #ifndef SPICEAPI_WRAPPERS_H
#define SPICEAPI_WRAPPERS_H #define SPICEAPI_WRAPPERS_H
#include <vector> #include <vector>
#include <string> #include <string>
#include "connection.h" #include "connection.h"
namespace spiceapi { namespace spiceapi {
struct AnalogState { struct AnalogState {
std::string name; std::string name;
float value; float value;
}; };
struct ButtonState { struct ButtonState {
std::string name; std::string name;
float value; float value;
}; };
struct LightState { struct LightState {
std::string name; std::string name;
float value; float value;
}; };
struct InfoAvs { struct InfoAvs {
std::string model, dest, spec, rev, ext; std::string model, dest, spec, rev, ext;
}; };
struct InfoLauncher { struct InfoLauncher {
std::string version; std::string version;
std::string compile_date, compile_time, system_time; std::string compile_date, compile_time, system_time;
std::vector<std::string> args; std::vector<std::string> args;
}; };
struct InfoMemory { struct InfoMemory {
uint64_t mem_total, mem_total_used, mem_used; uint64_t mem_total, mem_total_used, mem_used;
uint64_t vmem_total, vmem_total_used, vmem_used; uint64_t vmem_total, vmem_total_used, vmem_used;
}; };
struct TouchState { struct TouchState {
uint64_t id; uint64_t id;
int64_t x, y; int64_t x, y;
}; };
struct LCDInfo { struct LCDInfo {
bool enabled; bool enabled;
std::string csm; std::string csm;
uint8_t bri, con, bl, red, green, blue; uint8_t bri, con, bl, red, green, blue;
}; };
uint64_t msg_gen_id(); uint64_t msg_gen_id();
bool analogs_read(Connection &con, std::vector<AnalogState> &states); bool analogs_read(Connection &con, std::vector<AnalogState> &states);
bool analogs_write(Connection &con, std::vector<AnalogState> &states); bool analogs_write(Connection &con, std::vector<AnalogState> &states);
bool analogs_write_reset(Connection &con, std::vector<AnalogState> &states); bool analogs_write_reset(Connection &con, std::vector<AnalogState> &states);
bool buttons_read(Connection &con, std::vector<ButtonState> &states); bool buttons_read(Connection &con, std::vector<ButtonState> &states);
bool buttons_write(Connection &con, std::vector<ButtonState> &states); bool buttons_write(Connection &con, std::vector<ButtonState> &states);
bool buttons_write_reset(Connection &con, std::vector<ButtonState> &states); bool buttons_write_reset(Connection &con, std::vector<ButtonState> &states);
bool card_insert(Connection &con, size_t index, const char *card_id); bool card_insert(Connection &con, size_t index, const char *card_id);
bool coin_get(Connection &con, int &coins); bool coin_get(Connection &con, int &coins);
bool coin_set(Connection &con, int coins); bool coin_set(Connection &con, int coins);
bool coin_insert(Connection &con, int coins=1); bool coin_insert(Connection &con, int coins=1);
bool coin_blocker_get(Connection &con, bool &closed); bool coin_blocker_get(Connection &con, bool &closed);
bool control_raise(Connection &con, const char *signal); bool control_raise(Connection &con, const char *signal);
bool control_exit(Connection &con); bool control_exit(Connection &con);
bool control_exit(Connection &con, int exit_code); bool control_exit(Connection &con, int exit_code);
bool control_restart(Connection &con); bool control_restart(Connection &con);
bool control_session_refresh(Connection &con); bool control_session_refresh(Connection &con);
bool control_shutdown(Connection &con); bool control_shutdown(Connection &con);
bool control_reboot(Connection &con); bool control_reboot(Connection &con);
bool iidx_ticker_get(Connection &con, char *ticker); bool iidx_ticker_get(Connection &con, char *ticker);
bool iidx_ticker_set(Connection &con, const char *ticker); bool iidx_ticker_set(Connection &con, const char *ticker);
bool iidx_ticker_reset(Connection &con); bool iidx_ticker_reset(Connection &con);
bool info_avs(Connection &con, InfoAvs &info); bool info_avs(Connection &con, InfoAvs &info);
bool info_launcher(Connection &con, InfoLauncher &info); bool info_launcher(Connection &con, InfoLauncher &info);
bool info_memory(Connection &con, InfoMemory &info); bool info_memory(Connection &con, InfoMemory &info);
bool keypads_write(Connection &con, unsigned int keypad, const char *input); bool keypads_write(Connection &con, unsigned int keypad, const char *input);
bool keypads_set(Connection &con, unsigned int keypad, std::vector<char> &keys); bool keypads_set(Connection &con, unsigned int keypad, std::vector<char> &keys);
bool keypads_get(Connection &con, unsigned int keypad, std::vector<char> &keys); bool keypads_get(Connection &con, unsigned int keypad, std::vector<char> &keys);
bool lights_read(Connection &con, std::vector<LightState> &states); bool lights_read(Connection &con, std::vector<LightState> &states);
bool lights_write(Connection &con, std::vector<LightState> &states); bool lights_write(Connection &con, std::vector<LightState> &states);
bool lights_write_reset(Connection &con, std::vector<LightState> &states); bool lights_write_reset(Connection &con, std::vector<LightState> &states);
bool memory_write(Connection &con, const char *dll_name, const char *hex, uint32_t offset); bool memory_write(Connection &con, const char *dll_name, const char *hex, uint32_t offset);
bool memory_read(Connection &con, const char *dll_name, uint32_t offset, uint32_t size, std::string &hex); bool memory_read(Connection &con, const char *dll_name, uint32_t offset, uint32_t size, std::string &hex);
bool memory_signature(Connection &con, const char *dll_name, const char *signature, const char *replacement, bool memory_signature(Connection &con, const char *dll_name, const char *signature, const char *replacement,
uint32_t offset, uint32_t usage, uint32_t &file_offset); uint32_t offset, uint32_t usage, uint32_t &file_offset);
bool touch_read(Connection &con, std::vector<TouchState> &states); bool touch_read(Connection &con, std::vector<TouchState> &states);
bool touch_write(Connection &con, std::vector<TouchState> &states); bool touch_write(Connection &con, std::vector<TouchState> &states);
bool touch_write_reset(Connection &con, std::vector<TouchState> &states); bool touch_write_reset(Connection &con, std::vector<TouchState> &states);
bool lcd_info(Connection &con, LCDInfo &info); bool lcd_info(Connection &con, LCDInfo &info);
} }
#endif //SPICEAPI_WRAPPERS_H #endif //SPICEAPI_WRAPPERS_H
+24 -24
View File
@@ -1,24 +1,24 @@
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any binary, for any purpose, commercial or non-commercial, and by any
means. means.
In jurisdictions that recognize copyright laws, the author or authors In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this relinquishment in perpetuity of all present and future rights to this
software under copyright law. software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
@@ -1,22 +1,22 @@
library spiceapi; library spiceapi;
import 'dart:convert'; import 'dart:convert';
import 'dart:async'; import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'dart:html'; import 'dart:html';
import 'dart:typed_data'; import 'dart:typed_data';
part "src/connection.dart"; part "src/connection.dart";
part "src/request.dart"; part "src/request.dart";
part "src/response.dart"; part "src/response.dart";
part "src/exceptions.dart"; part "src/exceptions.dart";
part "src/rc4.dart"; part "src/rc4.dart";
part "src/wrappers/analogs.dart"; part "src/wrappers/analogs.dart";
part "src/wrappers/buttons.dart"; part "src/wrappers/buttons.dart";
part "src/wrappers/card.dart"; part "src/wrappers/card.dart";
part "src/wrappers/coin.dart"; part "src/wrappers/coin.dart";
part "src/wrappers/control.dart"; part "src/wrappers/control.dart";
part "src/wrappers/info.dart"; part "src/wrappers/info.dart";
part "src/wrappers/keypads.dart"; part "src/wrappers/keypads.dart";
part "src/wrappers/lights.dart"; part "src/wrappers/lights.dart";
part "src/wrappers/memory.dart"; part "src/wrappers/memory.dart";
part "src/wrappers/iidx.dart"; part "src/wrappers/iidx.dart";
part "src/wrappers/touch.dart"; part "src/wrappers/touch.dart";
@@ -1,193 +1,193 @@
part of spiceapi; part of spiceapi;
class Connection { class Connection {
// settings // settings
static const _TIMEOUT = Duration(seconds: 2); static const _TIMEOUT = Duration(seconds: 2);
static const _BUFFER_SIZE = 1024 * 8; static const _BUFFER_SIZE = 1024 * 8;
// state // state
final String host, pass; final String host, pass;
final int port; final int port;
var resource; var resource;
List<int> _dataBuffer; List<int> _dataBuffer;
StreamController<Response> _responses; StreamController<Response> _responses;
StreamController<Connection> _connections; StreamController<Connection> _connections;
WebSocket _socket; WebSocket _socket;
RC4 _cipher; RC4 _cipher;
bool _disposed = false; bool _disposed = false;
Connection(this.host, this.port, this.pass, Connection(this.host, this.port, this.pass,
{this.resource, bool refreshSession=true}) { {this.resource, bool refreshSession=true}) {
// initialize // initialize
_dataBuffer = List<int>(); _dataBuffer = List<int>();
_responses = StreamController<Response>.broadcast(); _responses = StreamController<Response>.broadcast();
_connections = StreamController<Connection>.broadcast(); _connections = StreamController<Connection>.broadcast();
if (pass.length > 0) if (pass.length > 0)
_cipher = RC4(utf8.encode(pass)); _cipher = RC4(utf8.encode(pass));
// initialize socket // initialize socket
this._socket = WebSocket("ws://$host:${port + 1}"); this._socket = WebSocket("ws://$host:${port + 1}");
this._socket.binaryType = "arraybuffer"; this._socket.binaryType = "arraybuffer";
// listen to events // listen to events
this._socket.onOpen.listen((e) async { this._socket.onOpen.listen((e) async {
// refresh session // refresh session
bool error = false; bool error = false;
if (refreshSession) { if (refreshSession) {
try { try {
await controlRefreshSession(this); await controlRefreshSession(this);
} on Error { } on Error {
error = true; error = true;
} on TimeoutException { } on TimeoutException {
error = true; error = true;
} }
} }
// mark as connected // mark as connected
if (!this._connections.isClosed) if (!this._connections.isClosed)
this._connections.add(this); this._connections.add(this);
if (error) if (error)
this.dispose(); this.dispose();
}); });
this._socket.onMessage.listen((e) { this._socket.onMessage.listen((e) {
// get data // get data
var data = e.data; var data = e.data;
if (data is ByteBuffer) if (data is ByteBuffer)
data = data.asUint8List(); data = data.asUint8List();
// check type // check type
if (data is List<int>) { if (data is List<int>) {
// cipher // cipher
if (_cipher != null) if (_cipher != null)
_cipher.crypt(data); _cipher.crypt(data);
// add data to buffer // add data to buffer
_dataBuffer.addAll(data); _dataBuffer.addAll(data);
// check buffer size // check buffer size
if (_dataBuffer.length > _BUFFER_SIZE) { if (_dataBuffer.length > _BUFFER_SIZE) {
this.dispose(); this.dispose();
return; return;
} }
// check for completed message // check for completed message
for (int i = 0; i < _dataBuffer.length; i++) { for (int i = 0; i < _dataBuffer.length; i++) {
if (_dataBuffer[i] == 0) { if (_dataBuffer[i] == 0) {
// get message data and remove from buffer // get message data and remove from buffer
var msgData = List<int>.from(_dataBuffer.getRange(0, i)); var msgData = List<int>.from(_dataBuffer.getRange(0, i));
_dataBuffer.removeRange(0, i + 1); _dataBuffer.removeRange(0, i + 1);
// check data length // check data length
if (msgData.length > 0) { if (msgData.length > 0) {
// convert to JSON // convert to JSON
var msgStr = utf8.decode(msgData, allowMalformed: false); var msgStr = utf8.decode(msgData, allowMalformed: false);
// build response // build response
var res = Response.fromJson(msgStr); var res = Response.fromJson(msgStr);
this._responses.add(res); this._responses.add(res);
} }
} }
} }
} }
}); });
this._socket.onClose.listen((e) { this._socket.onClose.listen((e) {
this.dispose(); this.dispose();
}); });
this._socket.onError.listen((e) { this._socket.onError.listen((e) {
this.dispose(); this.dispose();
}); });
} }
void changePass(String pass) { void changePass(String pass) {
if (pass.length > 0) if (pass.length > 0)
_cipher = RC4(utf8.encode(pass)); _cipher = RC4(utf8.encode(pass));
else else
_cipher = null; _cipher = null;
} }
void dispose() { void dispose() {
if (_socket != null) if (_socket != null)
_socket.close(); _socket.close();
_socket = null; _socket = null;
if (_responses != null) if (_responses != null)
_responses.close(); _responses.close();
if (_connections != null) if (_connections != null)
_connections.close(); _connections.close();
this._disposed = true; this._disposed = true;
this.free(); this.free();
} }
bool isDisposed() { bool isDisposed() {
return this._disposed; return this._disposed;
} }
void free() { void free() {
// release optional resource // release optional resource
if (this.resource != null) { if (this.resource != null) {
this.resource.release(); this.resource.release();
this.resource = null; this.resource = null;
} }
} }
bool isFree() { bool isFree() {
return this.resource == null; return this.resource == null;
} }
Future<Connection> onConnect() { Future<Connection> onConnect() {
return _connections.stream.first; return _connections.stream.first;
} }
bool isValid() { bool isValid() {
return this._socket != null && !this._disposed; return this._socket != null && !this._disposed;
} }
Future<Response> request(Request req) { Future<Response> request(Request req) {
// add response listener // add response listener
var res = _awaitResponse(req._id); var res = _awaitResponse(req._id);
// write request // write request
_writeRequest(req); _writeRequest(req);
// return future response // return future response
return res.then((res) { return res.then((res) {
// validate first // validate first
res.validate(); res.validate();
// return it // return it
return res; return res;
}); });
} }
void _writeRequest(Request req) async { void _writeRequest(Request req) async {
// convert to JSON // convert to JSON
var json = req.toJson() + "\x00"; var json = req.toJson() + "\x00";
var jsonEncoded = utf8.encode(json); var jsonEncoded = utf8.encode(json);
// cipher // cipher
if (_cipher != null) if (_cipher != null)
_cipher.crypt(jsonEncoded); _cipher.crypt(jsonEncoded);
// write to socket // write to socket
this._socket.sendByteBuffer(Int8List.fromList(jsonEncoded).buffer); this._socket.sendByteBuffer(Int8List.fromList(jsonEncoded).buffer);
} }
Future<Response> _awaitResponse(int id) { Future<Response> _awaitResponse(int id) {
return _responses.stream.timeout(_TIMEOUT).firstWhere( return _responses.stream.timeout(_TIMEOUT).firstWhere(
(res) => res._id == id, orElse: null); (res) => res._id == id, orElse: null);
} }
} }
@@ -1,11 +1,11 @@
part of spiceapi; part of spiceapi;
class APIError implements Exception { class APIError implements Exception {
String cause; String cause;
APIError(this.cause); APIError(this.cause);
@override @override
String toString() { String toString() {
return this.cause; return this.cause;
} }
} }
@@ -1,48 +1,48 @@
part of spiceapi; part of spiceapi;
class RC4 { class RC4 {
// state // state
int _a = 0; int _a = 0;
int _b = 0; int _b = 0;
List<int> _sBox = List<int>(256); List<int> _sBox = List<int>(256);
RC4(List<int> key) { RC4(List<int> key) {
// init sBox // init sBox
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
_sBox[i] = i; _sBox[i] = i;
} }
// process key // process key
int j = 0; int j = 0;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
// update // update
j = (j + _sBox[i] + key[i % key.length]) % 256; j = (j + _sBox[i] + key[i % key.length]) % 256;
// swap // swap
var tmp = _sBox[i]; var tmp = _sBox[i];
_sBox[i] = _sBox[j]; _sBox[i] = _sBox[j];
_sBox[j] = tmp; _sBox[j] = tmp;
} }
} }
void crypt(List<int> inData) { void crypt(List<int> inData) {
for (int i = 0; i < inData.length; i++) { for (int i = 0; i < inData.length; i++) {
// update // update
_a = (_a + 1) % 256; _a = (_a + 1) % 256;
_b = (_b + _sBox[_a]) % 256; _b = (_b + _sBox[_a]) % 256;
// swap // swap
var tmp = _sBox[_a]; var tmp = _sBox[_a];
_sBox[_a] = _sBox[_b]; _sBox[_a] = _sBox[_b];
_sBox[_b] = tmp; _sBox[_b] = tmp;
// crypt // crypt
inData[i] ^= _sBox[(_sBox[_a] + _sBox[_b]) % 256]; inData[i] ^= _sBox[(_sBox[_a] + _sBox[_b]) % 256];
} }
} }
} }
@@ -1,45 +1,45 @@
part of spiceapi; part of spiceapi;
class Request { class Request {
static int _lastID = 0; static int _lastID = 0;
// contents // contents
int _id; int _id;
String _module; String _module;
String _function; String _function;
List _params; List _params;
Request(String module, String function, {id}) { Request(String module, String function, {id}) {
// automatic ID iteration // automatic ID iteration
if (id == null) { if (id == null) {
if (++_lastID >= pow(2, 32)) if (++_lastID >= pow(2, 32))
_lastID = 1; _lastID = 1;
id = _lastID; id = _lastID;
} else } else
_lastID = id; _lastID = id;
// build contents // build contents
this._id = id; this._id = id;
this._module = module; this._module = module;
this._function = function; this._function = function;
this._params = List(); this._params = List();
} }
String toJson() { String toJson() {
return jsonEncode( return jsonEncode(
{ {
"id": this._id, "id": this._id,
"module": this._module, "module": this._module,
"function": this._function, "function": this._function,
"params": this._params, "params": this._params,
} }
); );
} }
void addParam(param) { void addParam(param) {
this._params.add(param); this._params.add(param);
} }
} }
@@ -1,35 +1,35 @@
part of spiceapi; part of spiceapi;
class Response { class Response {
String _json; String _json;
int _id; int _id;
List _errors; List _errors;
List _data; List _data;
Response.fromJson(String json) { Response.fromJson(String json) {
this._json = json; this._json = json;
var obj = jsonDecode(json); var obj = jsonDecode(json);
this._id = obj["id"]; this._id = obj["id"];
this._errors = obj["errors"]; this._errors = obj["errors"];
this._data = obj["data"]; this._data = obj["data"];
} }
void validate() { void validate() {
// check for errors // check for errors
if (_errors.length > 0) { if (_errors.length > 0) {
// TODO: add all errors // TODO: add all errors
throw APIError(_errors[0].toString()); throw APIError(_errors[0].toString());
} }
} }
List getData() { List getData() {
return _data; return _data;
} }
String toJson() { String toJson() {
return _json; return _json;
} }
} }
@@ -1,54 +1,54 @@
part of spiceapi; part of spiceapi;
class AnalogState { class AnalogState {
String name; String name;
double state; double state;
bool active; bool active;
AnalogState(this.name, this.state); AnalogState(this.name, this.state);
AnalogState._fromRead(this.name, this.state, this.active); AnalogState._fromRead(this.name, this.state, this.active);
} }
Future<List<AnalogState>> analogsRead(Connection con) { Future<List<AnalogState>> analogsRead(Connection con) {
var req = Request("analogs", "read"); var req = Request("analogs", "read");
return con.request(req).then((res) { return con.request(req).then((res) {
// build states list // build states list
List<AnalogState> states = []; List<AnalogState> states = [];
for (List state in res.getData()) { for (List state in res.getData()) {
states.add(AnalogState._fromRead( states.add(AnalogState._fromRead(
state[0], state[0],
state[1], state[1],
state[2], state[2],
)); ));
} }
// return it // return it
return states; return states;
}); });
} }
Future<void> analogsWrite(Connection con, List<AnalogState> states) { Future<void> analogsWrite(Connection con, List<AnalogState> states) {
var req = Request("analogs", "write"); var req = Request("analogs", "write");
// add params // add params
for (var state in states) { for (var state in states) {
var obj = [ var obj = [
state.name, state.name,
state.state state.state
]; ];
req.addParam(obj); req.addParam(obj);
} }
return con.request(req); return con.request(req);
} }
Future<void> analogsWriteReset(Connection con, List<String> names) { Future<void> analogsWriteReset(Connection con, List<String> names) {
var req = Request("analogs", "write_reset"); var req = Request("analogs", "write_reset");
// add params // add params
for (var name in names) for (var name in names)
req.addParam(name); req.addParam(name);
return con.request(req); return con.request(req);
} }
@@ -1,54 +1,54 @@
part of spiceapi; part of spiceapi;
class ButtonState { class ButtonState {
String name; String name;
double state; double state;
bool active; bool active;
ButtonState(this.name, this.state); ButtonState(this.name, this.state);
ButtonState._fromRead(this.name, this.state, this.active); ButtonState._fromRead(this.name, this.state, this.active);
} }
Future<List<ButtonState>> buttonsRead(Connection con) { Future<List<ButtonState>> buttonsRead(Connection con) {
var req = Request("buttons", "read"); var req = Request("buttons", "read");
return con.request(req).then((res) { return con.request(req).then((res) {
// build states list // build states list
List<ButtonState> states = []; List<ButtonState> states = [];
for (List state in res.getData()) { for (List state in res.getData()) {
states.add(ButtonState._fromRead( states.add(ButtonState._fromRead(
state[0], state[0],
state[1], state[1],
state[2], state[2],
)); ));
} }
// return it // return it
return states; return states;
}); });
} }
Future<void> buttonsWrite(Connection con, List<ButtonState> states) { Future<void> buttonsWrite(Connection con, List<ButtonState> states) {
var req = Request("buttons", "write"); var req = Request("buttons", "write");
// add params // add params
for (var state in states) { for (var state in states) {
var obj = [ var obj = [
state.name, state.name,
state.state state.state
]; ];
req.addParam(obj); req.addParam(obj);
} }
return con.request(req); return con.request(req);
} }
Future<void> buttonsWriteReset(Connection con, List<String> names) { Future<void> buttonsWriteReset(Connection con, List<String> names) {
var req = Request("buttons", "write_reset"); var req = Request("buttons", "write_reset");
// add params // add params
for (var name in names) for (var name in names)
req.addParam(name); req.addParam(name);
return con.request(req); return con.request(req);
} }
@@ -1,8 +1,8 @@
part of spiceapi; part of spiceapi;
Future<void> cardInsert(Connection con, int unit, String cardID) { Future<void> cardInsert(Connection con, int unit, String cardID) {
var req = Request("card", "insert"); var req = Request("card", "insert");
req.addParam(unit); req.addParam(unit);
req.addParam(cardID); req.addParam(cardID);
return con.request(req); return con.request(req);
} }
@@ -1,21 +1,21 @@
part of spiceapi; part of spiceapi;
Future<int> coinGet(Connection con) { Future<int> coinGet(Connection con) {
var req = Request("coin", "get"); var req = Request("coin", "get");
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
Future<void> coinSet(Connection con, int amount) { Future<void> coinSet(Connection con, int amount) {
var req = Request("coin", "set"); var req = Request("coin", "set");
req.addParam(amount); req.addParam(amount);
return con.request(req); return con.request(req);
} }
Future<void> coinInsert(Connection con, [int amount=1]) { Future<void> coinInsert(Connection con, [int amount=1]) {
var req = Request("coin", "insert"); var req = Request("coin", "insert");
if (amount != 1) if (amount != 1)
req.addParam(amount); req.addParam(amount);
return con.request(req); return con.request(req);
} }
@@ -1,36 +1,36 @@
part of spiceapi; part of spiceapi;
Future<void> controlRaise(Connection con, String signal) { Future<void> controlRaise(Connection con, String signal) {
var req = Request("control", "raise"); var req = Request("control", "raise");
req.addParam(signal); req.addParam(signal);
return con.request(req); return con.request(req);
} }
Future<void> controlExit(Connection con, int code) { Future<void> controlExit(Connection con, int code) {
var req = Request("control", "exit"); var req = Request("control", "exit");
req.addParam(code); req.addParam(code);
return con.request(req); return con.request(req);
} }
Future<void> controlRestart(Connection con) { Future<void> controlRestart(Connection con) {
var req = Request("control", "restart"); var req = Request("control", "restart");
return con.request(req); return con.request(req);
} }
Future<void> controlRefreshSession(Connection con) { Future<void> controlRefreshSession(Connection con) {
var rnd = new Random(); var rnd = new Random();
var req = Request("control", "session_refresh", id: rnd.nextInt(pow(2, 32))); var req = Request("control", "session_refresh", id: rnd.nextInt(pow(2, 32)));
return con.request(req).then((res) { return con.request(req).then((res) {
con.changePass(res.getData()[0]); con.changePass(res.getData()[0]);
}); });
} }
Future<void> controlShutdown(Connection con) { Future<void> controlShutdown(Connection con) {
var req = Request("control", "shutdown"); var req = Request("control", "shutdown");
return con.request(req); return con.request(req);
} }
Future<void> controlReboot(Connection con) { Future<void> controlReboot(Connection con) {
var req = Request("control", "reboot"); var req = Request("control", "reboot");
return con.request(req); return con.request(req);
} }
@@ -1,19 +1,19 @@
part of spiceapi; part of spiceapi;
Future<String> iidxTickerGet(Connection con) { Future<String> iidxTickerGet(Connection con) {
var req = Request("iidx", "ticker_get"); var req = Request("iidx", "ticker_get");
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
Future<void> iidxTickerSet(Connection con, String text) { Future<void> iidxTickerSet(Connection con, String text) {
var req = Request("iidx", "ticker_set"); var req = Request("iidx", "ticker_set");
req.addParam(text); req.addParam(text);
return con.request(req); return con.request(req);
} }
Future<void> iidxTickerReset(Connection con) { Future<void> iidxTickerReset(Connection con) {
var req = Request("iidx", "ticker_reset"); var req = Request("iidx", "ticker_reset");
return con.request(req); return con.request(req);
} }
@@ -1,22 +1,22 @@
part of spiceapi; part of spiceapi;
Future<Map> infoAVS(Connection con) { Future<Map> infoAVS(Connection con) {
var req = Request("info", "avs"); var req = Request("info", "avs");
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
Future<Map> infoLauncher(Connection con) { Future<Map> infoLauncher(Connection con) {
var req = Request("info", "launcher"); var req = Request("info", "launcher");
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
Future<Map> infoMemory(Connection con) { Future<Map> infoMemory(Connection con) {
var req = Request("info", "memory"); var req = Request("info", "memory");
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
@@ -1,28 +1,28 @@
part of spiceapi; part of spiceapi;
Future<void> keypadsWrite(Connection con, int unit, String input) { Future<void> keypadsWrite(Connection con, int unit, String input) {
var req = Request("keypads", "write"); var req = Request("keypads", "write");
req.addParam(unit); req.addParam(unit);
req.addParam(input); req.addParam(input);
return con.request(req); return con.request(req);
} }
Future<void> keypadsSet(Connection con, int unit, String buttons) { Future<void> keypadsSet(Connection con, int unit, String buttons) {
var req = Request("keypads", "set"); var req = Request("keypads", "set");
req.addParam(unit); req.addParam(unit);
for (int i = 0; i < buttons.length; i++) for (int i = 0; i < buttons.length; i++)
req.addParam(buttons[i]); req.addParam(buttons[i]);
return con.request(req); return con.request(req);
} }
Future<String> keypadsGet(Connection con, int unit) { Future<String> keypadsGet(Connection con, int unit) {
var req = Request("keypads", "get"); var req = Request("keypads", "get");
req.addParam(unit); req.addParam(unit);
return con.request(req).then((res) { return con.request(req).then((res) {
String buttons = ""; String buttons = "";
for (var obj in res.getData()) { for (var obj in res.getData()) {
buttons += obj; buttons += obj;
} }
return buttons; return buttons;
}); });
} }
@@ -1,54 +1,54 @@
part of spiceapi; part of spiceapi;
class LightState { class LightState {
String name; String name;
double state; double state;
bool active; bool active;
LightState(this.name, this.state); LightState(this.name, this.state);
LightState._fromRead(this.name, this.state, this.active); LightState._fromRead(this.name, this.state, this.active);
} }
Future<List<LightState>> lightsRead(Connection con) { Future<List<LightState>> lightsRead(Connection con) {
var req = Request("lights", "read"); var req = Request("lights", "read");
return con.request(req).then((res) { return con.request(req).then((res) {
// build states list // build states list
List<LightState> states = []; List<LightState> states = [];
for (List state in res.getData()) { for (List state in res.getData()) {
states.add(LightState._fromRead( states.add(LightState._fromRead(
state[0], state[0],
state[1], state[1],
state[2], state[2],
)); ));
} }
// return it // return it
return states; return states;
}); });
} }
Future<void> lightsWrite(Connection con, List<LightState> states) { Future<void> lightsWrite(Connection con, List<LightState> states) {
var req = Request("lights", "write"); var req = Request("lights", "write");
// add params // add params
for (var state in states) { for (var state in states) {
var obj = [ var obj = [
state.name, state.name,
state.state state.state
]; ];
req.addParam(obj); req.addParam(obj);
} }
return con.request(req); return con.request(req);
} }
Future<void> lightsWriteReset(Connection con, List<String> names) { Future<void> lightsWriteReset(Connection con, List<String> names) {
var req = Request("lights", "write_reset"); var req = Request("lights", "write_reset");
// add params // add params
for (var name in names) for (var name in names)
req.addParam(name); req.addParam(name);
return con.request(req); return con.request(req);
} }
@@ -1,35 +1,35 @@
part of spiceapi; part of spiceapi;
Future<void> memoryWrite(Connection con, Future<void> memoryWrite(Connection con,
String dllName, String data, int offset) { String dllName, String data, int offset) {
var req = Request("memory", "write"); var req = Request("memory", "write");
req.addParam(dllName); req.addParam(dllName);
req.addParam(data); req.addParam(data);
req.addParam(offset); req.addParam(offset);
return con.request(req); return con.request(req);
} }
Future<String> memoryRead(Connection con, Future<String> memoryRead(Connection con,
String dllName, int offset, int size) { String dllName, int offset, int size) {
var req = Request("memory", "read"); var req = Request("memory", "read");
req.addParam(dllName); req.addParam(dllName);
req.addParam(offset); req.addParam(offset);
req.addParam(size); req.addParam(size);
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
Future<int> memorySignature(Connection con, Future<int> memorySignature(Connection con,
String dllName, String signature, String replacement, String dllName, String signature, String replacement,
int offset, int usage) { int offset, int usage) {
var req = Request("memory", "signature"); var req = Request("memory", "signature");
req.addParam(dllName); req.addParam(dllName);
req.addParam(signature); req.addParam(signature);
req.addParam(replacement); req.addParam(replacement);
req.addParam(offset); req.addParam(offset);
req.addParam(usage); req.addParam(usage);
return con.request(req).then((res) { return con.request(req).then((res) {
return res.getData()[0]; return res.getData()[0];
}); });
} }
@@ -1,53 +1,53 @@
part of spiceapi; part of spiceapi;
class TouchState { class TouchState {
int id; int id;
int x, y; int x, y;
TouchState(this.id, this.x, this.y); TouchState(this.id, this.x, this.y);
} }
Future<List<TouchState>> touchRead(Connection con) { Future<List<TouchState>> touchRead(Connection con) {
var req = Request("touch", "read"); var req = Request("touch", "read");
return con.request(req).then((res) { return con.request(req).then((res) {
// build states list // build states list
List<TouchState> states = []; List<TouchState> states = [];
for (List state in res.getData()) { for (List state in res.getData()) {
states.add(TouchState( states.add(TouchState(
state[0], state[0],
state[1], state[1],
state[2], state[2],
)); ));
} }
// return it // return it
return states; return states;
}); });
} }
Future<void> touchWrite(Connection con, List<TouchState> states) { Future<void> touchWrite(Connection con, List<TouchState> states) {
var req = Request("touch", "write"); var req = Request("touch", "write");
// add params // add params
for (var state in states) { for (var state in states) {
var obj = [ var obj = [
state.id, state.id,
state.x, state.x,
state.y state.y
]; ];
req.addParam(obj); req.addParam(obj);
} }
return con.request(req); return con.request(req);
} }
Future<void> touchWriteReset(Connection con, List<int> touchIDs) { Future<void> touchWriteReset(Connection con, List<int> touchIDs) {
var req = Request("touch", "write_reset"); var req = Request("touch", "write_reset");
// add params // add params
for (var id in touchIDs) for (var id in touchIDs)
req.addParam(id); req.addParam(id);
return con.request(req); return con.request(req);
} }
+24 -24
View File
@@ -1,24 +1,24 @@
This is free and unencumbered software released into the public domain. This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any binary, for any purpose, commercial or non-commercial, and by any
means. means.
In jurisdictions that recognize copyright laws, the author or authors In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this relinquishment in perpetuity of all present and future rights to this
software under copyright law. software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
+23 -23
View File
@@ -1,23 +1,23 @@
library spiceapi; library spiceapi;
import 'dart:io'; import 'dart:io';
import 'dart:convert'; import 'dart:convert';
import 'dart:async'; import 'dart:async';
import 'dart:math'; import 'dart:math';
import 'dart:typed_data'; import 'dart:typed_data';
part "src/connection.dart"; part "src/connection.dart";
part "src/request.dart"; part "src/request.dart";
part "src/response.dart"; part "src/response.dart";
part "src/exceptions.dart"; part "src/exceptions.dart";
part "src/rc4.dart"; part "src/rc4.dart";
part "src/wrappers/analogs.dart"; part "src/wrappers/analogs.dart";
part "src/wrappers/buttons.dart"; part "src/wrappers/buttons.dart";
part "src/wrappers/capture.dart"; part "src/wrappers/capture.dart";
part "src/wrappers/card.dart"; part "src/wrappers/card.dart";
part "src/wrappers/coin.dart"; part "src/wrappers/coin.dart";
part "src/wrappers/control.dart"; part "src/wrappers/control.dart";
part "src/wrappers/info.dart"; part "src/wrappers/info.dart";
part "src/wrappers/keypads.dart"; part "src/wrappers/keypads.dart";
part "src/wrappers/lights.dart"; part "src/wrappers/lights.dart";
part "src/wrappers/memory.dart"; part "src/wrappers/memory.dart";
part "src/wrappers/iidx.dart"; part "src/wrappers/iidx.dart";
part "src/wrappers/touch.dart"; part "src/wrappers/touch.dart";
+192 -192
View File
@@ -1,192 +1,192 @@
part of spiceapi; part of spiceapi;
class Connection { class Connection {
// settings // settings
static const _TIMEOUT = Duration(seconds: 3); static const _TIMEOUT = Duration(seconds: 3);
static const _BUFFER_SIZE = 1024 * 1024 * 8; static const _BUFFER_SIZE = 1024 * 1024 * 8;
// state // state
final String host, pass; final String host, pass;
final int port; final int port;
var resource; var resource;
List<int> _dataBuffer; List<int> _dataBuffer;
StreamController<Response> _responses; StreamController<Response> _responses;
StreamController<Connection> _connections; StreamController<Connection> _connections;
Socket _socket; Socket _socket;
RC4 _cipher; RC4 _cipher;
bool _disposed = false; bool _disposed = false;
Connection(this.host, this.port, this.pass, Connection(this.host, this.port, this.pass,
{this.resource, bool refreshSession=true}) { {this.resource, bool refreshSession=true}) {
// initialize // initialize
_dataBuffer = List<int>(); _dataBuffer = List<int>();
_responses = StreamController<Response>.broadcast(); _responses = StreamController<Response>.broadcast();
_connections = StreamController<Connection>.broadcast(); _connections = StreamController<Connection>.broadcast();
if (pass.length > 0) if (pass.length > 0)
_cipher = RC4(utf8.encode(pass)); _cipher = RC4(utf8.encode(pass));
// connect // connect
Socket.connect(host, port, timeout: _TIMEOUT).then((socket) async { Socket.connect(host, port, timeout: _TIMEOUT).then((socket) async {
// remember socket // remember socket
this._socket = socket; this._socket = socket;
// listen to data // listen to data
socket.listen((data) { socket.listen((data) {
// cipher // cipher
if (_cipher != null) if (_cipher != null)
_cipher.crypt(data); _cipher.crypt(data);
// add data to buffer // add data to buffer
_dataBuffer.addAll(data); _dataBuffer.addAll(data);
// check buffer size // check buffer size
if (_dataBuffer.length > _BUFFER_SIZE) { if (_dataBuffer.length > _BUFFER_SIZE) {
socket.destroy(); socket.destroy();
return; return;
} }
// check for completed message // check for completed message
for (int i = 0; i < _dataBuffer.length; i++) { for (int i = 0; i < _dataBuffer.length; i++) {
if (_dataBuffer[i] == 0) { if (_dataBuffer[i] == 0) {
// get message data and remove from buffer // get message data and remove from buffer
var msgData = List<int>.from(_dataBuffer.getRange(0, i)); var msgData = List<int>.from(_dataBuffer.getRange(0, i));
_dataBuffer.removeRange(0, i + 1); _dataBuffer.removeRange(0, i + 1);
// check data length // check data length
if (msgData.length > 0) { if (msgData.length > 0) {
// convert to JSON // convert to JSON
var msgStr = utf8.decode(msgData, allowMalformed: false); var msgStr = utf8.decode(msgData, allowMalformed: false);
// build response // build response
var res = Response.fromJson(msgStr); var res = Response.fromJson(msgStr);
this._responses.add(res); this._responses.add(res);
} }
} }
} }
}, onError: (e) { }, onError: (e) {
// dispose on listen error // dispose on listen error
this.dispose(); this.dispose();
}, onDone: () { }, onDone: () {
// dispose on listen done // dispose on listen done
this.dispose(); this.dispose();
}); });
// refresh session // refresh session
bool error = false; bool error = false;
if (refreshSession) { if (refreshSession) {
try { try {
await controlRefreshSession(this); await controlRefreshSession(this);
} on Error { } on Error {
error = true; error = true;
} on TimeoutException { } on TimeoutException {
error = true; error = true;
} }
} }
// mark as connected // mark as connected
if (!this._connections.isClosed) if (!this._connections.isClosed)
this._connections.add(this); this._connections.add(this);
if (error) if (error)
this.dispose(); this.dispose();
}, onError: (e) { }, onError: (e) {
// dispose on connection error // dispose on connection error
this.dispose(); this.dispose();
}); });
} }
void changePass(String pass) { void changePass(String pass) {
if (pass.length > 0) if (pass.length > 0)
_cipher = RC4(utf8.encode(pass)); _cipher = RC4(utf8.encode(pass));
else else
_cipher = null; _cipher = null;
} }
void dispose() { void dispose() {
if (_socket != null) if (_socket != null)
_socket.destroy(); _socket.destroy();
if (_responses != null) if (_responses != null)
_responses.close(); _responses.close();
if (_connections != null) if (_connections != null)
_connections.close(); _connections.close();
this._disposed = true; this._disposed = true;
this.free(); this.free();
} }
bool isDisposed() { bool isDisposed() {
return this._disposed; return this._disposed;
} }
void free() { void free() {
// release optional resource // release optional resource
if (this.resource != null) { if (this.resource != null) {
this.resource.release(); this.resource.release();
this.resource = null; this.resource = null;
} }
} }
bool isFree() { bool isFree() {
return this.resource == null; return this.resource == null;
} }
Future<Connection> onConnect() { Future<Connection> onConnect() {
return _connections.stream.first; return _connections.stream.first;
} }
bool isValid() { bool isValid() {
return this._socket != null && !this._disposed; return this._socket != null && !this._disposed;
} }
Future<Response> request(Request req) { Future<Response> request(Request req) {
// add response listener // add response listener
var res = _awaitResponse(req._id); var res = _awaitResponse(req._id);
// write request // write request
_writeRequest(req); _writeRequest(req);
// return future response // return future response
return res.then((res) { return res.then((res) {
// validate first // validate first
res.validate(); res.validate();
// return it // return it
return res; return res;
}); });
} }
void _writeRequest(Request req) async { void _writeRequest(Request req) async {
// convert to JSON // convert to JSON
var json = req.toJson() + "\x00"; var json = req.toJson() + "\x00";
var jsonEncoded = utf8.encode(json); var jsonEncoded = utf8.encode(json);
// cipher // cipher
if (_cipher != null) if (_cipher != null)
_cipher.crypt(jsonEncoded); _cipher.crypt(jsonEncoded);
// write to socket // write to socket
this._socket.add(jsonEncoded); this._socket.add(jsonEncoded);
} }
Future<Response> _awaitResponse(int id) { Future<Response> _awaitResponse(int id) {
return _responses.stream.timeout(_TIMEOUT).firstWhere( return _responses.stream.timeout(_TIMEOUT).firstWhere(
(res) => res._id == id, orElse: null); (res) => res._id == id, orElse: null);
} }
} }
+11 -11
View File
@@ -1,11 +1,11 @@
part of spiceapi; part of spiceapi;
class APIError implements Exception { class APIError implements Exception {
String cause; String cause;
APIError(this.cause); APIError(this.cause);
@override @override
String toString() { String toString() {
return this.cause; return this.cause;
} }
} }
+48 -48
View File
@@ -1,48 +1,48 @@
part of spiceapi; part of spiceapi;
class RC4 { class RC4 {
// state // state
int _a = 0; int _a = 0;
int _b = 0; int _b = 0;
List<int> _sBox = List<int>(256); List<int> _sBox = List<int>(256);
RC4(List<int> key) { RC4(List<int> key) {
// init sBox // init sBox
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
_sBox[i] = i; _sBox[i] = i;
} }
// process key // process key
int j = 0; int j = 0;
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
// update // update
j = (j + _sBox[i] + key[i % key.length]) % 256; j = (j + _sBox[i] + key[i % key.length]) % 256;
// swap // swap
var tmp = _sBox[i]; var tmp = _sBox[i];
_sBox[i] = _sBox[j]; _sBox[i] = _sBox[j];
_sBox[j] = tmp; _sBox[j] = tmp;
} }
} }
void crypt(List<int> inData) { void crypt(List<int> inData) {
for (int i = 0; i < inData.length; i++) { for (int i = 0; i < inData.length; i++) {
// update // update
_a = (_a + 1) % 256; _a = (_a + 1) % 256;
_b = (_b + _sBox[_a]) % 256; _b = (_b + _sBox[_a]) % 256;
// swap // swap
var tmp = _sBox[_a]; var tmp = _sBox[_a];
_sBox[_a] = _sBox[_b]; _sBox[_a] = _sBox[_b];
_sBox[_b] = tmp; _sBox[_b] = tmp;
// crypt // crypt
inData[i] ^= _sBox[(_sBox[_a] + _sBox[_b]) % 256]; inData[i] ^= _sBox[(_sBox[_a] + _sBox[_b]) % 256];
} }
} }
} }

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