chuniio-brokenithm/chuniio/src/chuniio.c

222 lines
5.6 KiB
C

//
// Created by beerpsi on 12/30/2023.
//
#include "chuniio.h"
#include <process.h>
#include <stdatomic.h>
#include "arch.h"
#include "config.h"
#include "ledoutput.h"
#include "ipc_memory_info.h"
#include "util/dprintf.h"
#ifdef ENV32BIT
#include "servers/android.h"
#include "servers/common.h"
#include "servers/ios.h"
#endif
#define MEM_FILE_NAME "Local\\BROKENITHM_SHARED_BUFFER"
static HANDLE chuni_io_file_mapping_handle;
struct IPCMemoryInfo *chuni_io_file_mapping;
HRESULT chuni_io_init_shared_memory() {
if (chuni_io_file_mapping) {
dprintf("chuni_io_init_shared_memory: shared memory already exists\n");
return E_FAIL;
}
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 E_FAIL;
}
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 E_FAIL;
}
memset(chuni_io_file_mapping, 0, sizeof(struct IPCMemoryInfo));
SetThreadExecutionState(ES_DISPLAY_REQUIRED | ES_CONTINUOUS);
return S_OK;
}
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 volatile atomic_flag chuni_io_slider_run_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");
HRESULT result;
if ((result = chuni_io_init_shared_memory())) {
return result;
}
led_init_mutex = CreateMutex(NULL, FALSE, NULL);
if (led_init_mutex == NULL) {
return E_FAIL;
}
#ifdef ENV32BIT
if ((result = android_init_server(chuni_io_file_mapping))) {
print_err("[ERROR] Android server intialization failed: %ld", result);
return result;
}
if ((result = ios_init_server(chuni_io_file_mapping))) {
print_err("[ERROR] iOS server initialization failed: %ld", result);
return result;
}
#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;
}
if ((chuni_io_file_mapping && chuni_io_file_mapping->serviceBtn) ||
GetAsyncKeyState(chuni_io_cfg.vk_service)) {
*opbtn |= CHUNI_IO_OPBTN_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 led_output_init(&chuni_io_cfg);
}
void chuni_io_slider_start(void *callback) {
if (chuni_io_slider_thread != NULL) {
return;
}
atomic_flag_test_and_set(&chuni_io_slider_run_flag);
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;
}
atomic_flag_clear(&chuni_io_slider_run_flag);
WaitForSingleObject(chuni_io_slider_thread, INFINITE);
CloseHandle(chuni_io_slider_thread);
chuni_io_slider_thread = NULL;
}
void chuni_io_slider_set_leds(const uint8_t *rgb) {
led_output_update(2, rgb);
if (chuni_io_file_mapping) {
memcpy(chuni_io_file_mapping->ledRgbData, rgb, 32 * 3);
}
}
HRESULT chuni_io_led_init(void) {
return led_output_init(&chuni_io_cfg);
}
void chuni_io_led_set_colors(uint8_t board, uint8_t *rgb) {
led_output_update(board, rgb);
}
static unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx) {
const chuni_io_slider_callback_t callback = ctx;
while (atomic_flag_test_and_set(&chuni_io_slider_run_flag)) {
uint8_t pressure[32];
if (chuni_io_file_mapping) {
memcpy(pressure, chuni_io_file_mapping->sliderIoStatus, 32);
}
callback(pressure);
Sleep(1);
}
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
return TRUE;
}