diff --git a/CMakeLists.txt b/CMakeLists.txt index dbad207..b1fc980 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/src/chuniio.c b/src/chuniio.c index 6259ef3..be754e3 100644 --- a/src/chuniio.c +++ b/src/chuniio.c @@ -4,31 +4,30 @@ #include "chuniio.h" -#include #include -#include -#include #include -#include #include "config.h" #include "struct.h" #include "util/dprintf.h" +#ifdef ENV32BIT +#include +#include +#include + +#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; } diff --git a/src/chuniio.h b/src/chuniio.h index bd8963b..8c60729 100644 --- a/src/chuniio.h +++ b/src/chuniio.h @@ -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 #include