feat: allow split dlls to work, allow multiple TCP connections

trunk
beerpsi 2023-12-30 19:16:18 +07:00
parent bf14d32980
commit f9438b78fa
3 changed files with 124 additions and 73 deletions

View File

@ -3,7 +3,7 @@ project(chuniio_brokenithm)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include_directories("${CMAKE_SOURCE_DIR}/include/") include_directories("${CMAKE_SOURCE_DIR}/include/")
set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_STANDARD 11)
link_directories(src) link_directories(src)
add_library(chuniio_brokenithm SHARED src/chuniio.c add_library(chuniio_brokenithm SHARED src/chuniio.c
@ -16,5 +16,5 @@ add_library(chuniio_brokenithm SHARED src/chuniio.c
src/util/dprintf.h) src/util/dprintf.h)
set_target_properties(chuniio_brokenithm PROPERTIES PREFIX "") 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) target_link_libraries(chuniio_brokenithm ws2_32)

View File

@ -4,31 +4,30 @@
#include "chuniio.h" #include "chuniio.h"
#include <stdio.h>
#include <inttypes.h> #include <inttypes.h>
#include <signal.h>
#include <time.h>
#include <process.h> #include <process.h>
#include <assert.h>
#include "config.h" #include "config.h"
#include "struct.h" #include "struct.h"
#include "util/dprintf.h" #include "util/dprintf.h"
#ifdef ENV32BIT
#include <stdatomic.h>
#include <stdio.h>
#include <time.h>
#include "socket.h"
#endif
//region Brokenithm //region Brokenithm
struct IPCMemoryInfo* chuni_io_file_mapping; struct IPCMemoryInfo* chuni_io_file_mapping;
const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER"; const char *memFileName = "Local\\BROKENITHM_SHARED_BUFFER";
char remote_address[BUFSIZ]; #ifdef ENV32BIT
uint16_t remote_port = 52468;
uint16_t server_port = 52468; uint16_t server_port = 52468;
bool tcp_mode = false; bool tcp_mode = false;
volatile sig_atomic_t EXIT_FLAG = false, CONNECTED = false;
uint32_t last_input_packet_id = 0;
enum { enum {
CARD_AIME, CARD_AIME,
CARD_FELICA, CARD_FELICA,
@ -40,9 +39,14 @@ enum {
}; };
typedef struct { 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; struct IPCMemoryInfo* memory;
} thread_args; } thread_ctx;
void socket_set_timeout(SOCKET sHost, int timeout) { void socket_set_timeout(SOCKET sHost, int timeout) {
setsockopt(sHost, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(int)); 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); 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", 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); ctx->last_input_packet_id, new_packet_id, new_packet_id - ctx->last_input_packet_id - 1);
} else if (new_packet_id == last_input_packet_id) { } else if (new_packet_id == ctx->last_input_packet_id) {
print_err("[WARN] Packet #%" PRIu32 " duplicated\n", new_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) 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; bool has_previous_led_status = false;
int skip_count = 0; int skip_count = 0;
unsigned int __stdcall thread_led_broadcast(void *ctx) { unsigned int __stdcall thread_led_broadcast(void *v) {
thread_args *args = (thread_args*)ctx; thread_ctx *ctx = (thread_ctx*)v;
SOCKET sHost = args->sHost; SOCKET sHost = ctx->sock;
struct IPCMemoryInfo* memory = args->memory; struct IPCMemoryInfo* memory = ctx->memory;
struct sockaddr_in addr = {}; 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]; char send_buffer[4 + 3 * 32];
send_buffer[0] = 100; send_buffer[0] = 99;
send_buffer[1] = 'L'; send_buffer[1] = 'L';
send_buffer[2] = 'E'; send_buffer[2] = 'E';
send_buffer[3] = 'D'; send_buffer[3] = 'D';
uint8_t current_led_status[3 * 32]; 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); Sleep(50);
continue; continue;
} }
@ -232,8 +237,8 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) {
continue; continue;
} else { } else {
print_err("[INFO] Device disconnected!\n"); print_err("[INFO] Device disconnected!\n");
CONNECTED = false; atomic_store(&ctx->connected, false);
EXIT_FLAG = true; atomic_store(&ctx->exit_flag, true);
break; break;
} }
} }
@ -250,21 +255,21 @@ unsigned int __stdcall thread_led_broadcast(void *ctx) {
uint8_t last_card_id[10]; uint8_t last_card_id[10];
unsigned int __stdcall thread_input_recv(void *ctx) { unsigned int __stdcall thread_input_recv(void *v) {
thread_args *args = (thread_args*)ctx; thread_ctx *ctx = (thread_ctx*)v;
SOCKET sHost = args->sHost; SOCKET sHost = ctx->sock;
struct IPCMemoryInfo* memory = args->memory; struct IPCMemoryInfo* memory = ctx->memory;
char buffer[BUFSIZ]; char buffer[BUFSIZ];
struct sockaddr_in addr = {}; 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; int recv_len, packet_len;
uint8_t real_len; uint8_t real_len;
while (!EXIT_FLAG) { while (!atomic_load(&ctx->exit_flag)) {
if (!tcp_mode) { if (!tcp_mode) {
/** /**
on UDP mode data is sent as packets, so just receive into a buffer big enough for 1 packet 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; continue;
} else { } else {
print_err("[INFO] Device disconnected!\n"); print_err("[INFO] Device disconnected!\n");
CONNECTED = false; atomic_store(&ctx->connected, false);
EXIT_FLAG = true; atomic_store(&ctx->exit_flag, true);
break; break;
} }
} }
@ -307,7 +312,7 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
} }
real_len = buffer[0]; real_len = buffer[0];
packet_len = real_len + 1; packet_len = real_len + 1; // 1 for the packetSize
while (recv_len < packet_len) { while (recv_len < packet_len) {
int read = recv(sHost, buffer + recv_len, packet_len - recv_len, 0); 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; continue;
} else { } else {
print_err("[INFO] Device disconnected!\n"); print_err("[INFO] Device disconnected!\n");
CONNECTED = false; atomic_store(&ctx->connected, false);
EXIT_FLAG = true; atomic_store(&ctx->exit_flag, true);
break; break;
} }
} }
@ -335,7 +340,7 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
memory->testBtn = pkt->testBtn; memory->testBtn = pkt->testBtn;
memory->serviceBtn = pkt->serviceBtn; 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 } else if (packet_len >= sizeof(struct PacketInputNoAir) && buffer[1] == 'I' && buffer[2] == 'P' && buffer[3] == 'T') { // without air
struct PacketInputNoAir* pkt = (struct PacketInputNoAir*)buffer; struct PacketInputNoAir* pkt = (struct PacketInputNoAir*)buffer;
@ -343,7 +348,7 @@ unsigned int __stdcall thread_input_recv(void *ctx) {
memory->testBtn = pkt->testBtn; memory->testBtn = pkt->testBtn;
memory->serviceBtn = pkt->serviceBtn; 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') { } else if (packet_len >= sizeof(struct PacketFunction) && buffer[1] == 'F' && buffer[2] == 'N' && buffer[3] == 'C') {
struct PacketFunction* pkt = (struct PacketFunction*)buffer; 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') { } else if (packet_len >= sizeof(struct PacketConnect) && buffer[1] == 'C' && buffer[2] == 'O' && buffer[3] == 'N') {
struct PacketConnect* pkt = (struct PacketConnect*)buffer; struct PacketConnect* pkt = (struct PacketConnect*)buffer;
get_socks_address(pkt, remote_address, BUFSIZ - 1, &remote_port); get_socks_address(pkt, ctx->remote_address, BUFSIZ - 1, &ctx->remote_port);
print_err("[INFO] Device %s:%d connected.\n", remote_address, remote_port); print_err("[INFO] Device %s:%d connected.\n", ctx->remote_address, ctx->remote_port);
last_input_packet_id = 0; ctx->last_input_packet_id = 0;
CONNECTED = true; atomic_store(&ctx->connected, true);
} else if (packet_len >= 4 && buffer[1] == 'D' && buffer[2] == 'I' && buffer[3] == 'S') { } else if (packet_len >= 4 && buffer[1] == 'D' && buffer[2] == 'I' && buffer[3] == 'S') {
CONNECTED = false; atomic_store(&ctx->connected, false);
if (tcp_mode) { if (tcp_mode) {
EXIT_FLAG = 1; atomic_store(&ctx->exit_flag, true);
print_err("[INFO] Device disconnected!\n"); print_err("[INFO] Device disconnected!\n");
break; break;
} }
if (strlen(remote_address)) { if (strlen(ctx->remote_address)) {
print_err("[INFO] Device %s:%d disconnected.\n", remote_address, remote_port); print_err("[INFO] Device %s:%d disconnected.\n", ctx->remote_address, ctx->remote_port);
memset(remote_address, 0, BUFSIZ); memset(ctx->remote_address, 0, BUFSIZ);
} }
} else if (packet_len >= sizeof(struct PacketPing) && buffer[1] == 'P' && buffer[2] == 'I' && buffer[3] == 'N') { } else if (packet_len >= sizeof(struct PacketPing) && buffer[1] == 'P' && buffer[2] == 'I' && buffer[3] == 'N') {
if (!CONNECTED) { if (!atomic_load(&ctx->connected)) {
continue; 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); 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 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); 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); listen(sHost, 10);
print_err("[INFO] Waiting for device on port %d...\n", server_port);
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma ide diagnostic ignored "EndlessLoop" #pragma ide diagnostic ignored "EndlessLoop"
for (;;) { for (;;) {
print_err("[INFO] Waiting for device on port %d...\n", server_port);
struct sockaddr_in user_socket = {}; struct sockaddr_in user_socket = {};
socklen_t sock_size = sizeof(struct sockaddr_in); socklen_t sock_size = sizeof(struct sockaddr_in);
SOCKET acc_socket = accept(sHost, (struct sockaddr *)&user_socket, &sock_size); 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); print_err("[INFO] Device %s:%d connected.\n", user_address, user_socket.sin_port);
} }
CONNECTED = true; thread_ctx args = {
EXIT_FLAG = false; .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 }; _beginthreadex(NULL, 0, thread_led_broadcast, &args, 0, NULL);
_beginthreadex(NULL, 0, thread_input_recv, &args, 0, NULL);
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;
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop
} }
@ -511,9 +515,35 @@ HRESULT server_start() {
return S_OK; return S_OK;
} }
#endif
//endregion //endregion
//region ChuniIO stuff //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 unsigned int __stdcall chuni_io_slider_thread_proc(void *ctx);
static bool chuni_io_coin; static bool chuni_io_coin;
@ -530,10 +560,15 @@ uint16_t chuni_io_get_api_version() {
HRESULT chuni_io_jvs_init() { HRESULT chuni_io_jvs_init() {
chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini"); chuni_io_config_load(&chuni_io_cfg, L".\\segatools.ini");
#ifdef ENV32BIT
HRESULT result = server_start(); HRESULT result = server_start();
if (result != S_OK) { if (result != S_OK) {
return result; return result;
} }
#endif
#ifdef ENV64BIT
chuni_io_init_shared_memory();
#endif
return S_OK; return S_OK;
} }

View File

@ -5,7 +5,23 @@
#ifndef CHUNIIO_BROKENITHM_CHUNIIO_H #ifndef CHUNIIO_BROKENITHM_CHUNIIO_H
#define 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 <windows.h>
#include <stdbool.h> #include <stdbool.h>