forked from beerpsi/chuniio-brokenithm
feat: allow split dlls to work, allow multiple TCP connections
This commit is contained in:
parent
bf14d32980
commit
f9438b78fa
@ -3,7 +3,7 @@ project(chuniio_brokenithm)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
include_directories("${CMAKE_SOURCE_DIR}/include/")
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
|
||||
link_directories(src)
|
||||
add_library(chuniio_brokenithm SHARED src/chuniio.c
|
||||
@ -16,5 +16,5 @@ add_library(chuniio_brokenithm SHARED src/chuniio.c
|
||||
src/util/dprintf.h)
|
||||
|
||||
set_target_properties(chuniio_brokenithm PROPERTIES PREFIX "")
|
||||
set_target_properties(chuniio_brokenithm PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||
# set_target_properties(chuniio_brokenithm PROPERTIES COMPILE_FLAGS "-m32" LINK_FLAGS "-m32")
|
||||
target_link_libraries(chuniio_brokenithm ws2_32)
|
||||
|
175
src/chuniio.c
175
src/chuniio.c
@ -4,31 +4,30 @@
|
||||
|
||||
#include "chuniio.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <process.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "struct.h"
|
||||
#include "util/dprintf.h"
|
||||
|
||||
#ifdef ENV32BIT
|
||||
#include <stdatomic.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "socket.h"
|
||||
#endif
|
||||
|
||||
//region Brokenithm
|
||||
struct IPCMemoryInfo* chuni_io_file_mapping;
|
||||
|
||||
const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER";
|
||||
|
||||
char remote_address[BUFSIZ];
|
||||
uint16_t remote_port = 52468;
|
||||
#ifdef ENV32BIT
|
||||
uint16_t server_port = 52468;
|
||||
bool tcp_mode = false;
|
||||
|
||||
volatile sig_atomic_t EXIT_FLAG = false, CONNECTED = false;
|
||||
|
||||
uint32_t last_input_packet_id = 0;
|
||||
|
||||
enum {
|
||||
CARD_AIME,
|
||||
CARD_FELICA,
|
||||
@ -40,9 +39,14 @@ enum {
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
SOCKET sHost;
|
||||
SOCKET sock;
|
||||
char remote_address[BUFSIZ];
|
||||
uint16_t remote_port;
|
||||
atomic_bool exit_flag;
|
||||
atomic_bool connected;
|
||||
uint32_t last_input_packet_id;
|
||||
struct IPCMemoryInfo* memory;
|
||||
} thread_args;
|
||||
} thread_ctx;
|
||||
|
||||
void socket_set_timeout(SOCKET sHost, int timeout) {
|
||||
setsockopt(sHost, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int));
|
||||
@ -96,17 +100,17 @@ void get_socks_address(const struct PacketConnect* pkt, char* address, int addre
|
||||
}
|
||||
}
|
||||
|
||||
void update_packet_id(uint32_t new_packet_id)
|
||||
void update_packet_id(thread_ctx *ctx, uint32_t new_packet_id)
|
||||
{
|
||||
if (last_input_packet_id > new_packet_id) {
|
||||
if (ctx->last_input_packet_id > new_packet_id) {
|
||||
print_err("[WARN] Packet #%" PRIu32 " came too late\n", new_packet_id);
|
||||
} else if (new_packet_id > last_input_packet_id + 1) {
|
||||
} else if (new_packet_id > ctx->last_input_packet_id + 1) {
|
||||
print_err("[WARN] Packets between #%" PRIu32 " and #%" PRIu32 " total %" PRIu32 " packet(s) are missing, probably too late or dropped\n",
|
||||
last_input_packet_id, new_packet_id, new_packet_id - last_input_packet_id - 1);
|
||||
} else if (new_packet_id == last_input_packet_id) {
|
||||
ctx->last_input_packet_id, new_packet_id, new_packet_id - ctx->last_input_packet_id - 1);
|
||||
} else if (new_packet_id == ctx->last_input_packet_id) {
|
||||
print_err("[WARN] Packet #%" PRIu32 " duplicated\n", new_packet_id);
|
||||
}
|
||||
last_input_packet_id = new_packet_id;
|
||||
ctx->last_input_packet_id = new_packet_id;
|
||||
}
|
||||
|
||||
void dump_bytes(const void *ptr, size_t nbytes, bool hex_string)
|
||||
@ -185,25 +189,26 @@ uint8_t previous_led_status[3 * 32];
|
||||
bool has_previous_led_status = false;
|
||||
int skip_count = 0;
|
||||
|
||||
unsigned int __stdcall thread_led_broadcast(void *ctx) {
|
||||
thread_args *args = (thread_args*)ctx;
|
||||
unsigned int __stdcall thread_led_broadcast(void *v) {
|
||||
thread_ctx *ctx = (thread_ctx*)v;
|
||||
|
||||
SOCKET sHost = args->sHost;
|
||||
struct IPCMemoryInfo* memory = args->memory;
|
||||
SOCKET sHost = ctx->sock;
|
||||
struct IPCMemoryInfo* memory = ctx->memory;
|
||||
|
||||
struct sockaddr_in addr = {};
|
||||
make_ipv4_address(&addr, remote_address, remote_port);
|
||||
make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port);
|
||||
|
||||
char send_buffer[4 + 3 * 32];
|
||||
send_buffer[0] = 100;
|
||||
send_buffer[0] = 99;
|
||||
send_buffer[1] = 'L';
|
||||
send_buffer[2] = 'E';
|
||||
send_buffer[3] = 'D';
|
||||
|
||||
uint8_t current_led_status[3 * 32];
|
||||
|
||||
while (!EXIT_FLAG) {
|
||||
if (!CONNECTED) {
|
||||
|
||||
while (!atomic_load(&ctx->exit_flag)) {
|
||||
if (!atomic_load(&ctx->connected)) {
|
||||
Sleep(50);
|
||||
continue;
|
||||
}
|
||||
@ -232,8 +237,8 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) {
|
||||
continue;
|
||||
} else {
|
||||
print_err("[INFO] Device disconnected!\n");
|
||||
CONNECTED = false;
|
||||
EXIT_FLAG = true;
|
||||
atomic_store(&ctx->connected, false);
|
||||
atomic_store(&ctx->exit_flag, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -250,21 +255,21 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) {
|
||||
|
||||
uint8_t last_card_id[10];
|
||||
|
||||
unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
thread_args *args = (thread_args*)ctx;
|
||||
unsigned int __stdcall thread_input_recv(void *v) {
|
||||
thread_ctx *ctx = (thread_ctx*)v;
|
||||
|
||||
SOCKET sHost = args->sHost;
|
||||
struct IPCMemoryInfo* memory = args->memory;
|
||||
SOCKET sHost = ctx->sock;
|
||||
struct IPCMemoryInfo* memory = ctx->memory;
|
||||
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
struct sockaddr_in addr = {};
|
||||
make_ipv4_address(&addr, remote_address, remote_port);
|
||||
make_ipv4_address(&addr, ctx->remote_address, ctx->remote_port);
|
||||
|
||||
int recv_len, packet_len;
|
||||
uint8_t real_len;
|
||||
|
||||
while (!EXIT_FLAG) {
|
||||
while (!atomic_load(&ctx->exit_flag)) {
|
||||
if (!tcp_mode) {
|
||||
/**
|
||||
on UDP mode data is sent as packets, so just receive into a buffer big enough for 1 packet
|
||||
@ -297,8 +302,8 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
continue;
|
||||
} else {
|
||||
print_err("[INFO] Device disconnected!\n");
|
||||
CONNECTED = false;
|
||||
EXIT_FLAG = true;
|
||||
atomic_store(&ctx->connected, false);
|
||||
atomic_store(&ctx->exit_flag, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -307,7 +312,7 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
}
|
||||
|
||||
real_len = buffer[0];
|
||||
packet_len = real_len + 1;
|
||||
packet_len = real_len + 1; // 1 for the packetSize
|
||||
|
||||
while (recv_len < packet_len) {
|
||||
int read = recv(sHost, buffer + recv_len, packet_len - recv_len, 0);
|
||||
@ -317,8 +322,8 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
continue;
|
||||
} else {
|
||||
print_err("[INFO] Device disconnected!\n");
|
||||
CONNECTED = false;
|
||||
EXIT_FLAG = true;
|
||||
atomic_store(&ctx->connected, false);
|
||||
atomic_store(&ctx->exit_flag, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -335,7 +340,7 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
memory->testBtn = pkt->testBtn;
|
||||
memory->serviceBtn = pkt->serviceBtn;
|
||||
|
||||
update_packet_id(ntohl(pkt->packetId));
|
||||
update_packet_id(ctx, ntohl(pkt->packetId));
|
||||
} else if (packet_len >= sizeof(struct PacketInputNoAir) && buffer[1] == 'I' && buffer[2] == 'P' && buffer[3] == 'T') { // without air
|
||||
struct PacketInputNoAir* pkt = (struct PacketInputNoAir*)buffer;
|
||||
|
||||
@ -343,7 +348,7 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
memory->testBtn = pkt->testBtn;
|
||||
memory->serviceBtn = pkt->serviceBtn;
|
||||
|
||||
update_packet_id(ntohl(pkt->packetId));
|
||||
update_packet_id(ctx, ntohl(pkt->packetId));
|
||||
} else if (packet_len >= sizeof(struct PacketFunction) && buffer[1] == 'F' && buffer[2] == 'N' && buffer[3] == 'C') {
|
||||
struct PacketFunction* pkt = (struct PacketFunction*)buffer;
|
||||
|
||||
@ -358,26 +363,26 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
|
||||
} else if (packet_len >= sizeof(struct PacketConnect) && buffer[1] == 'C' && buffer[2] == 'O' && buffer[3] == 'N') {
|
||||
struct PacketConnect* pkt = (struct PacketConnect*)buffer;
|
||||
|
||||
get_socks_address(pkt, remote_address, BUFSIZ - 1, &remote_port);
|
||||
print_err("[INFO] Device %s:%d connected.\n", remote_address, remote_port);
|
||||
get_socks_address(pkt, ctx->remote_address, BUFSIZ - 1, &ctx->remote_port);
|
||||
print_err("[INFO] Device %s:%d connected.\n", ctx->remote_address, ctx->remote_port);
|
||||
|
||||
last_input_packet_id = 0;
|
||||
CONNECTED = true;
|
||||
ctx->last_input_packet_id = 0;
|
||||
atomic_store(&ctx->connected, true);
|
||||
} else if (packet_len >= 4 && buffer[1] == 'D' && buffer[2] == 'I' && buffer[3] == 'S') {
|
||||
CONNECTED = false;
|
||||
atomic_store(&ctx->connected, false);
|
||||
|
||||
if (tcp_mode) {
|
||||
EXIT_FLAG = 1;
|
||||
atomic_store(&ctx->exit_flag, true);
|
||||
print_err("[INFO] Device disconnected!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if (strlen(remote_address)) {
|
||||
print_err("[INFO] Device %s:%d disconnected.\n", remote_address, remote_port);
|
||||
memset(remote_address, 0, BUFSIZ);
|
||||
if (strlen(ctx->remote_address)) {
|
||||
print_err("[INFO] Device %s:%d disconnected.\n", ctx->remote_address, ctx->remote_port);
|
||||
memset(ctx->remote_address, 0, BUFSIZ);
|
||||
}
|
||||
} else if (packet_len >= sizeof(struct PacketPing) && buffer[1] == 'P' && buffer[2] == 'I' && buffer[3] == 'N') {
|
||||
if (!CONNECTED) {
|
||||
if (!atomic_load(&ctx->connected)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -421,7 +426,13 @@ unsigned int __stdcall server_thread_proc(void* ctx) {
|
||||
|
||||
print_err("[INFO] Waiting for device on port %d...\n", server_port);
|
||||
|
||||
thread_args args = { .memory = memory, .sHost = sHost };
|
||||
thread_ctx args = {
|
||||
.sock = sHost,
|
||||
.exit_flag = ATOMIC_VAR_INIT(false),
|
||||
.connected = ATOMIC_VAR_INIT(true),
|
||||
.last_input_packet_id = 0,
|
||||
.memory = memory
|
||||
};
|
||||
|
||||
HANDLE led_thread = (HANDLE)_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
|
||||
HANDLE input_thread = (HANDLE)_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
|
||||
@ -440,10 +451,11 @@ unsigned int __stdcall server_thread_proc(void* ctx) {
|
||||
|
||||
listen(sHost, 10);
|
||||
|
||||
print_err("[INFO] Waiting for device on port %d...\n", server_port);
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma ide diagnostic ignored "EndlessLoop"
|
||||
for (;;) {
|
||||
print_err("[INFO] Waiting for device on port %d...\n", server_port);
|
||||
struct sockaddr_in user_socket = {};
|
||||
socklen_t sock_size = sizeof(struct sockaddr_in);
|
||||
SOCKET acc_socket = accept(sHost, (struct sockaddr *)&user_socket, &sock_size);
|
||||
@ -454,24 +466,16 @@ unsigned int __stdcall server_thread_proc(void* ctx) {
|
||||
print_err("[INFO] Device %s:%d connected.\n", user_address, user_socket.sin_port);
|
||||
}
|
||||
|
||||
CONNECTED = true;
|
||||
EXIT_FLAG = false;
|
||||
thread_ctx args = {
|
||||
.sock = acc_socket,
|
||||
.exit_flag = ATOMIC_VAR_INIT(false),
|
||||
.connected = ATOMIC_VAR_INIT(true),
|
||||
.last_input_packet_id = 0,
|
||||
.memory = memory
|
||||
};
|
||||
|
||||
thread_args args = { .memory = memory, .sHost = acc_socket };
|
||||
|
||||
HANDLE led_thread = (HANDLE)_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
|
||||
HANDLE input_thread = (HANDLE)_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
|
||||
|
||||
WaitForSingleObject(led_thread, INFINITE);
|
||||
WaitForSingleObject(input_thread, INFINITE);
|
||||
|
||||
CloseHandle(led_thread);
|
||||
CloseHandle(input_thread);
|
||||
|
||||
print_err("[INFO] Exiting gracefully...\n");
|
||||
last_input_packet_id = 0;
|
||||
EXIT_FLAG = true;
|
||||
CONNECTED = false;
|
||||
_beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
|
||||
_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
@ -511,9 +515,35 @@ HRESULT server_start() {
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
#endif
|
||||
//endregion
|
||||
|
||||
//region ChuniIO stuff
|
||||
#ifdef ENV64BIT
|
||||
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), memFileName)) == 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;
|
||||
@ -530,10 +560,15 @@ uint16_t chuni_io_get_api_version() {
|
||||
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;
|
||||
}
|
||||
|
@ -5,7 +5,23 @@
|
||||
#ifndef CHUNIIO_BROKENITHM_CHUNIIO_H
|
||||
#define CHUNIIO_BROKENITHM_CHUNIIO_H
|
||||
|
||||
#include "socket.h"
|
||||
#if _WIN32 || _WIN64
|
||||
#if _WIN64
|
||||
#define ENV64BIT
|
||||
#else
|
||||
#define ENV32BIT
|
||||
#endif // _WIN64
|
||||
#endif // _WIN32 || _WIN64
|
||||
|
||||
#if __GNUC__
|
||||
#if __x86_64__ || __ppc64__
|
||||
#define ENV64BIT
|
||||
#else
|
||||
#define ENV32BIT
|
||||
#endif // __x86_64__ || __ppc64__
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
Loading…
Reference in New Issue
Block a user