chuniio-brokenithm/chuniio/src/chuniio.c

232 lines
6.1 KiB
C

//
// Created by beerpsi on 12/30/2023.
//
#include "chuniio.h"
#include <process.h>
#include "arch.h"
#include "config.h"
#include "ipc_memory_info.h"
#define MEM_FILE_NAME "Local\\BROKENITHM_SHARED_BUFFER"
struct IPCMemoryInfo *chuni_io_file_mapping;
#ifdef ENV32BIT
#include "servers/android.h"
#include "servers/common.h"
#include "servers/ios.h"
HRESULT server_start() {
HANDLE hMapFile = OpenFileMappingA(FILE_MAP_ALL_ACCESS, false, MEM_FILE_NAME);
if (hMapFile == NULL) {
hMapFile = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
1024, MEM_FILE_NAME);
if (hMapFile == NULL) {
print_err("[ERROR] CreateFileMapping failed! error: %lu\n", GetLastError());
return E_FAIL;
}
}
struct IPCMemoryInfo *memory =
MapViewOfFileEx(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 1024, NULL);
chuni_io_file_mapping = memory;
HRESULT result;
if ((result = android_init_server(memory))) {
print_err("[ERROR] Android server intialization failed: %ld", result);
return result;
}
if ((result = ios_init_server(memory))) {
print_err("[ERROR] iOS server initialization failed: %ld", result);
return result;
}
return S_OK;
}
#endif
#ifdef ENV64BIT
#include "util/dprintf.h"
static HANDLE chuni_io_file_mapping_handle;
void chuni_io_init_shared_memory() {
if (chuni_io_file_mapping) {
dprintf("chuni_io_init_shared_memory: shared memory already exists\n");
return;
}
if ((chuni_io_file_mapping_handle =
CreateFileMapping(INVALID_HANDLE_VALUE, 0, PAGE_READWRITE, 0,
sizeof(struct IPCMemoryInfo), MEM_FILE_NAME)) == 0) {
dprintf("chuni_io_init_shared_memory: could not create file mapping: %ld\n",
GetLastError());
return;
}
if ((chuni_io_file_mapping = (struct IPCMemoryInfo *)MapViewOfFile(
chuni_io_file_mapping_handle, FILE_MAP_ALL_ACCESS, 0, 0,
sizeof(struct IPCMemoryInfo))) == 0) {
dprintf("chuni_io_init_shared_memory: could not get view of file: %ld\n",
GetLastError());
return;
}
memset(chuni_io_file_mapping, 0, sizeof(struct IPCMemoryInfo));
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
}
#endif
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
static bool chuni_io_coin;
static uint16_t chuni_io_coins;
static uint8_t chuni_io_hand_pos;
static HANDLE chuni_io_slider_thread;
static bool chuni_io_slider_stop_flag;
static struct chuni_io_config chuni_io_cfg;
uint16_t chuni_io_get_api_version() { return 0x0102; }
HRESULT chuni_io_jvs_init() {
chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini");
#ifdef ENV32BIT
HRESULT result = server_start();
if (result != S_OK) {
return result;
}
#endif
#ifdef ENV64BIT
chuni_io_init_shared_memory();
#endif
return S_OK;
}
void chuni_io_jvs_read_coin_counter(uint16_t *total) {
if (total == NULL) {
return;
}
if (chuni_io_file_mapping && chuni_io_file_mapping->coinInsertion) {
chuni_io_coins++;
chuni_io_file_mapping->coinInsertion = 0;
} else {
if (GetAsyncKeyState(chuni_io_cfg.vk_coin)) {
if (!chuni_io_coin) {
chuni_io_coin = true;
chuni_io_coins++;
}
} else {
chuni_io_coin = false;
}
}
*total = chuni_io_coins;
}
void chuni_io_jvs_poll(uint8_t *opbtn, uint8_t *beams) {
size_t i;
if ((chuni_io_file_mapping && chuni_io_file_mapping->testBtn) ||
GetAsyncKeyState(chuni_io_cfg.vk_test)) {
*opbtn |= CHUNI_IO_OPBTN_TEST; /* Test */
}
if ((chuni_io_file_mapping && chuni_io_file_mapping->serviceBtn) ||
GetAsyncKeyState(chuni_io_cfg.vk_service)) {
*opbtn |= CHUNI_IO_OPBTN_SERVICE; /* Service */
}
if (GetAsyncKeyState(chuni_io_cfg.vk_ir_emu)) {
if (chuni_io_hand_pos < 6) {
chuni_io_hand_pos++;
}
} else {
if (chuni_io_hand_pos > 0) {
chuni_io_hand_pos--;
}
}
for (i = 0; i < 6; i++) {
if (chuni_io_hand_pos > i) {
*beams |= (1 << i);
}
}
// IR format is beams[5:0] = {b5,b6,b3,b4,b1,b2};
for (i = 0; i < 3; i++) {
if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i * 2])
*beams |= 1 << (i * 2 + 1);
if (chuni_io_file_mapping && chuni_io_file_mapping->airIoStatus[i * 2 + 1])
*beams |= 1 << i * 2;
}
}
HRESULT chuni_io_slider_init() { return S_OK; }
void chuni_io_slider_start(void *callback) {
if (chuni_io_slider_thread != NULL) {
return;
}
chuni_io_slider_thread =
(HANDLE)_beginthreadex(NULL, 0, chuni_io_slider_thread_proc, callback, 0, NULL);
}
void chuni_io_slider_stop(void) {
if (chuni_io_slider_thread == NULL) {
return;
}
chuni_io_slider_stop_flag = true;
WaitForSingleObject(chuni_io_slider_thread, INFINITE);
CloseHandle(chuni_io_slider_thread);
chuni_io_slider_thread = NULL;
chuni_io_slider_stop_flag = false;
}
void chuni_io_slider_set_leds(const uint8_t *rgb) {
if (chuni_io_file_mapping) {
memcpy(chuni_io_file_mapping->ledRgbData, rgb, 32 * 3);
}
}
HRESULT chuni_io_led_init(void) { return S_OK; }
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {}
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) {
const chuni_io_slider_callback_t callback = ctx;
#pragma clang diagnostic push
#pragma ide diagnostic ignored "LoopDoesntUseConditionVariableInspection"
// ReSharper disable once CppDFALoopConditionNotUpdated
while (!chuni_io_slider_stop_flag) {
uint8_t pressure[32];
if (chuni_io_file_mapping) {
memcpy(pressure, chuni_io_file_mapping->sliderIoStatus, 32);
}
callback(pressure);
Sleep(1);
}
#pragma clang diagnostic pop
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
return TRUE;
}