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

This commit is contained in:
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/")
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)

View File

@ -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;
}

View File

@ -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>