From 50997a8b758647f568793208ed175d89d96ee7ba Mon Sep 17 00:00:00 2001 From: Lephenixnoir Date: Sun, 25 Aug 2024 23:10:51 +0200 Subject: [PATCH] very crude Windows build (WIP): disable fxlink TUI, gdb bridge There is no direct replacement for poll() in the Windows API, so I'm gonna disable the fxlink TUI for now and maybe later figure out how to do something equivalent, even if more brute-forcey. --- .gitignore | 1 + CMakeLists.txt | 25 ++++++++++++------- README.md | 21 ++++++++++++++++ fxgxa/dump.c | 10 ++++---- fxgxa/endianness.h | 36 ++++++++++++++++++++++++++++ fxlink/main.c | 2 ++ fxlink/tui/command-util.c | 5 ++++ fxlink/tui/commands.c | 5 ++++ fxlink/tui/tui-interactive.c | 21 ++++++++++------ libfxlink/defs.c | 6 +++++ libfxlink/devices.c | 4 ++++ libfxlink/filter.c | 8 ++++++- libfxlink/include/fxlink/config.h.in | 3 +++ libfxlink/include/fxlink/defs.h | 7 +++++- libfxlink/include/fxlink/devices.h | 6 ++++- libfxlink/logging.c | 4 ++++ 16 files changed, 141 insertions(+), 23 deletions(-) diff --git a/.gitignore b/.gitignore index da528b0..36a1be8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Build directory build/ +build-win64/ # Documentation drafts doc/ diff --git a/CMakeLists.txt b/CMakeLists.txt index cf53515..7771c04 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ endif() if(NOT FXLINK_DISABLE_SDL2) pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET) endif() -pkg_check_modules(ncurses REQUIRED ncurses IMPORTED_TARGET) +pkg_check_modules(ncurses REQUIRED ncursesw IMPORTED_TARGET) set(CMAKE_INSTALL_MESSAGE LAZY) set(SRC "${CMAKE_CURRENT_SOURCE_DIR}") @@ -30,8 +30,13 @@ target_include_directories(fxgxa PUBLIC fxgxa/) target_link_libraries(fxgxa PkgConfig::libpng) # fxg1a as a symlink (for compatibility) -add_custom_target(fxg1a ALL - COMMAND ${CMAKE_COMMAND} -E create_symlink "fxgxa" "fxg1a") +if(WIN32) + add_custom_target(fxg1a ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink "fxgxa.exe" "fxg1a.exe") +else() + add_custom_target(fxg1a ALL + COMMAND ${CMAKE_COMMAND} -E create_symlink "fxgxa" "fxg1a") +endif() # fxsdk add_custom_command(OUTPUT "${BIN}/fxsdk.sh" @@ -86,10 +91,12 @@ if(NOT FXLINK_DISABLE_SDL2) endif() # fxsdk-gdb-bridge -add_executable(fxsdk-gdb-bridge fxsdk/gdb-bridge.c) -target_link_libraries(fxsdk-gdb-bridge libfxlink) -target_include_directories(fxsdk-gdb-bridge PRIVATE - "${SRC}/fxlink/include") +if(NOT WIN32) + add_executable(fxsdk-gdb-bridge fxsdk/gdb-bridge.c) + target_link_libraries(fxsdk-gdb-bridge libfxlink) + target_include_directories(fxsdk-gdb-bridge PRIVATE + "${SRC}/fxlink/include") +endif() # Install rules @@ -98,7 +105,9 @@ install(PROGRAMS "${BIN}/fxsdk.sh" TYPE BIN RENAME fxsdk) install(DIRECTORY fxsdk/assets DESTINATION share/fxsdk) install(DIRECTORY fxsdk/scripts DESTINATION share/fxsdk USE_SOURCE_PERMISSIONS) install(DIRECTORY fxsdk/cmake/ DESTINATION lib/cmake/fxsdk) -install(TARGETS fxsdk-gdb-bridge) +if(NOT WIN32) + install(TARGETS fxsdk-gdb-bridge) +endif() # fxgxa, fxg1a install(TARGETS fxgxa) install(FILES "${BIN}/fxg1a" TYPE BIN) diff --git a/README.md b/README.md index d2d3bab..9c12eb8 100644 --- a/README.md +++ b/README.md @@ -169,3 +169,24 @@ When configuring, you should set an install prefix that you have write access to ``` You can then proceed to install the cross-compiler. If in doubt about the order in which you need to install repositories, refer to the [GiteaPC README](https://gitea.planet-casio.com/Lephenixnoir/GiteaPC) or check the `giteapc.make` files of each repository, where dependencies are listed. + +## Building for Windows from Arch Linux using a cross-compiler + +⚠️ This is experimental/not yet officially supported. Intended to build fxlink only. + +_Credits to [Cahute](https://cahuteproject.org/guides/build.html) from which this process is based._ + +Install the cross-compiler and cross-libraries from AUR. + +```bash +% yay -S python python-toml mingw-w64 \ + mingw-w64-cmake mingw-w64-libusb mingw-w64-sdl2 mingw-w64-libpng \ + mingw-w64-ncurses +``` + +Configure and build. + +```bash +% x86_64-w64-mingw32-cmake -B build-win64 -DFXLINK_DISABLE_UDISKS2=1 -DFXLINK_DISABLE_POLL=1 +% make -C build-win64 +``` diff --git a/fxgxa/dump.c b/fxgxa/dump.c index 0c610f0..5575b6c 100644 --- a/fxgxa/dump.c +++ b/fxgxa/dump.c @@ -53,7 +53,7 @@ static int check_g1a(int test, struct g1a const *g1a, size_t size,char *status) m("Sequence 2 0x01 0x%02x", h->seq2); return (h->seq2 != 0x01) ? 1:0; case 5: - m("File size 1 %-8zu %u", size, + m("File size 1 %-8lu %u", (unsigned long)size, be32toh(h->filesize_be1)); return (be32toh(h->filesize_be1) != size) ? 2:0; case 6: @@ -66,7 +66,7 @@ static int check_g1a(int test, struct g1a const *g1a, size_t size,char *status) be16toh(h->checksum)); return (be16toh(h->checksum) != sum) ? 2:0; case 8: - m("File size 2 %-8zu %u", size, + m("File size 2 %-8lu %u", (unsigned long)size, be32toh(h->filesize_be2)); return (be32toh(h->filesize_be2) != size) ? 2:0; default: @@ -170,7 +170,7 @@ static int check_g3a(int test, struct g3a const *g3a, size_t size,char *status) m("Sequence 2 0x01 0x%02x", h->seq2); return (h->seq2 != 0x01) ? 1:0; case 5: - m("File size 1 %-8zu %u", size, + m("File size 1 %-8lu %u", (unsigned long)size, be32toh(h->filesize_be1)); return (be32toh(h->filesize_be1) != size) ? 2:0; case 6: @@ -183,7 +183,7 @@ static int check_g3a(int test, struct g3a const *g3a, size_t size,char *status) be16toh(h->checksum)); return (be16toh(h->checksum) != sum) ? 2:0; case 8: - m("File size 2 %-8zu %u", size - 0x7004, + m("File size 2 %-8lu %u", (unsigned long)size - 0x7004, be32toh(h->filesize_be2)); return (be32toh(h->filesize_be2) != size - 0x7004) ? 2:0; case 9: @@ -192,7 +192,7 @@ static int check_g3a(int test, struct g3a const *g3a, size_t size,char *status) be32toh(h->checksum_2)); return (be32toh(h->checksum_2) != sum2) ? 2:0; case 10: - m("File size 1 %-8zu %u", size, + m("File size 1 %-8lu %u", (unsigned long)size, be32toh(h->filesize_be3)); return (be32toh(h->filesize_be3) != size) ? 2:0; case 11: diff --git a/fxgxa/endianness.h b/fxgxa/endianness.h index 30361e2..5553d6f 100644 --- a/fxgxa/endianness.h +++ b/fxgxa/endianness.h @@ -24,6 +24,42 @@ #define be64toh(x) OSSwapBigToHostInt64(x) #define le64toh(x) OSSwapLittleToHostInt64(x) +#elif defined(__WINDOWS__) || defined(_WIN16) || defined(_WIN32) || defined(_WIN64) + + #include + + #if BYTE_ORDER == LITTLE_ENDIAN + #define htobe16(x) __builtin_bswap16(x) + #define htole16(x) (x) + #define be16toh(x) __builtin_bswap16(x) + #define le16toh(x) (x) + + #define htobe32(x) __builtin_bswap32(x) + #define htole32(x) (x) + #define be32toh(x) __builtin_bswap32(x) + #define le32toh(x) (x) + + #define htobe64(x) __builtin_bswap64(x) + #define htole64(x) (x) + #define be64toh(x) __builtin_bswap64(x) + #define le64toh(x) (x) + #elif BYTE_ORDER == BIG_ENDIAN + #define htobe16(x) (x) + #define htole16(x) __builtin_bswap16(x) + #define be16toh(x) (x) + #define le16toh(x) __builtin_bswap16(x) + + #define htobe32(x) (x) + #define htole32(x) __builtin_bswap32(x) + #define be32toh(x) (x) + #define le32toh(x) __builtin_bswap32(x) + + #define htobe64(x) (x) + #define htole64(x) __builtin_bswap64(x) + #define be64toh(x) (x) + #define le64toh(x) __builtin_bswap64(x) + #endif + #elif defined(__linux__) #include diff --git a/fxlink/main.c b/fxlink/main.c index 4a49f5d..9db1a64 100644 --- a/fxlink/main.c +++ b/fxlink/main.c @@ -237,7 +237,9 @@ int main(int argc, char **argv) while(repeat); } else if(mode == 't') { +#ifndef FXLINK_DISABLE_POLL rc = main_tui_interactive(context); +#endif } else if(mode == 'p') { rc = main_push(filter, &delay, context, argv + optind); diff --git a/fxlink/tui/command-util.c b/fxlink/tui/command-util.c index 93035c4..7e542e8 100644 --- a/fxlink/tui/command-util.c +++ b/fxlink/tui/command-util.c @@ -4,6 +4,9 @@ // \___/ License: MIT // //---------------------------------------------------------------------------// +#include +#ifndef FXLINK_DISABLE_POLL + #include "tui.h" #include "command-util.h" #include @@ -377,3 +380,5 @@ FXLINK_COMMAND("?cmdtree") node_dump(cmdtree, 0); return 0; } + +#endif diff --git a/fxlink/tui/commands.c b/fxlink/tui/commands.c index 5afa8b3..14e6c08 100644 --- a/fxlink/tui/commands.c +++ b/fxlink/tui/commands.c @@ -4,6 +4,9 @@ // \___/ License: MIT // //---------------------------------------------------------------------------// +#include +#ifndef FXLINK_DISABLE_POLL + #include "tui.h" #include "command-util.h" #include @@ -271,3 +274,5 @@ FXLINK_COMMAND("gintctl test all", DEVICE(fdev)) test_read_unaligned(fdev); return 0; } + +#endif diff --git a/fxlink/tui/tui-interactive.c b/fxlink/tui/tui-interactive.c index 5dc000b..1183461 100644 --- a/fxlink/tui/tui-interactive.c +++ b/fxlink/tui/tui-interactive.c @@ -4,6 +4,9 @@ // \___/ License: MIT // //---------------------------------------------------------------------------// +#include +#ifndef FXLINK_DISABLE_POLL + #include "../fxlink.h" #include "tui.h" #include @@ -202,24 +205,24 @@ static void TUI_render_transfers(void) if(!comm) continue; - struct fxlink_transfer *IN = comm->ftransfer_IN; - struct fxlink_transfer *OUT = comm->ftransfer_OUT; + struct fxlink_transfer *in = comm->ftransfer_IN; + struct fxlink_transfer *out = comm->ftransfer_OUT; - if(IN) { + if(in) { mvwaddstr(win, y, 1, fxlink_device_id(fdev)); mvwaddstr(win, y, 10, "IN"); - mvwaddstr(win, y, 16, fxlink_size_string(IN->msg.size)); + mvwaddstr(win, y, 16, fxlink_size_string(in->msg.size)); wmove(win, y, 26); - progress_bar(win, 32, IN->processed_size, IN->msg.size); + progress_bar(win, 32, in->processed_size, in->msg.size); has_transfers = true; y++; } - if(OUT) { + if(out) { mvwaddstr(win, y, 1, fxlink_device_id(fdev)); mvwaddstr(win, y, 10, "OUT"); - mvwaddstr(win, y, 16, fxlink_size_string(OUT->msg.size)); + mvwaddstr(win, y, 16, fxlink_size_string(out->msg.size)); has_transfers = true; y++; } @@ -259,10 +262,12 @@ static bool TUI_setup(void) memset(&TUI, 0, sizeof TUI); /* Set up the SINGWINCH handler */ +#if !defined(_WIN16) && !defined(_WIN32) && !defined(_WIN64) struct sigaction WINCH; sigaction(SIGWINCH, NULL, &WINCH); WINCH.sa_handler = TUI_SIGWINCH_handler; sigaction(SIGWINCH, &WINCH, NULL); +#endif /* Initialize the main screen */ initscr(); @@ -590,3 +595,5 @@ int main_tui_interactive(libusb_context *ctx) TUI_quit(); return 0; } + +#endif diff --git a/libfxlink/defs.c b/libfxlink/defs.c index a684532..a6a9074 100644 --- a/libfxlink/defs.c +++ b/libfxlink/defs.c @@ -47,7 +47,11 @@ char *fxlink_gen_file_name(char const *path, char const *name, time_t time_raw; struct tm time_bd; time(&time_raw); +#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64) + time_bd = *localtime(&time_raw); +#else localtime_r(&time_raw, &time_bd); +#endif while(1) { asprintf(&filename, "%s/fxlink-%.16s-%04d.%02d.%02d-%02dh%02d-%d%s", @@ -67,6 +71,7 @@ char *fxlink_gen_file_name(char const *path, char const *name, return filename; } +#ifndef FXLINK_DISABLE_POLL int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...) { /* Convenience macro to iterate on file descriptor arrays */ @@ -104,6 +109,7 @@ int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...) free(concat); return rc; } +#endif /* FXLINK_DISABLE_POLL */ char const *fxlink_size_string(int bytes) { diff --git a/libfxlink/devices.c b/libfxlink/devices.c index 271e720..a1ca83e 100644 --- a/libfxlink/devices.c +++ b/libfxlink/devices.c @@ -635,6 +635,8 @@ bool fxlink_device_start_bulk_OUT(struct fxlink_device *fdev, // Polled file descriptor tracking //--- +#ifndef FXLINK_DISABLE_POLL + static void generate_poll_fds(struct fxlink_pollfds *tracker) { /* Get the set of libusb file descriptors to poll for news */ @@ -705,6 +707,8 @@ void fxlink_pollfds_stop(struct fxlink_pollfds *tracker) memset(tracker, 0, sizeof *tracker); } +#endif /* FXLINK_DISABLE_POLL */ + //--- // Device tracking //--- diff --git a/libfxlink/filter.c b/libfxlink/filter.c index 530ca7e..59195c1 100644 --- a/libfxlink/filter.c +++ b/libfxlink/filter.c @@ -29,7 +29,13 @@ static char *read_word(char const **input) { char const *str = *input; while(**input && isword(**input)) (*input)++; - return strndup(str, *input - str); + + char *rc = malloc(*input - str + 1); + if(!rc) + return NULL; + memcpy(rc, str, *input - str); + rc[*input - str] = 0; + return rc; } /* Reads a property from the input source. Advances *input and sets *name and diff --git a/libfxlink/include/fxlink/config.h.in b/libfxlink/include/fxlink/config.h.in index fa44496..446795b 100644 --- a/libfxlink/include/fxlink/config.h.in +++ b/libfxlink/include/fxlink/config.h.in @@ -13,5 +13,8 @@ /* Disable SDL2 interfaces. */ #cmakedefine FXLINK_DISABLE_SDL2 +/* Disable poll-based interfaces. */ +#cmakedefine FXLINK_DISABLE_POLL + /* fxSDK version */ #define FXLINK_VERSION "@CMAKE_PROJECT_VERSION@" diff --git a/libfxlink/include/fxlink/defs.h b/libfxlink/include/fxlink/defs.h index b2c2c8e..2e4b83a 100644 --- a/libfxlink/include/fxlink/defs.h +++ b/libfxlink/include/fxlink/defs.h @@ -12,7 +12,10 @@ #include #include #include -#include + +#ifndef FXLINK_DISABLE_POLL +# include +#endif static inline int min(int x, int y) { @@ -84,8 +87,10 @@ char const *fmt_to_ANSI(int format); char *fxlink_gen_file_name(char const *path, char const *name, char const *suffix); +#ifndef FXLINK_DISABLE_POLL /* Modified poll with a variable number of arrays. */ int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...); +#endif /* Write out the given size (in bytes) in a human-readable form. Returns a pointer to a statically-allocated string. */ diff --git a/libfxlink/include/fxlink/devices.h b/libfxlink/include/fxlink/devices.h index d06defb..4a5d6dc 100644 --- a/libfxlink/include/fxlink/devices.h +++ b/libfxlink/include/fxlink/devices.h @@ -48,8 +48,8 @@ #pragma once #include #include +#include #include -#include /* Device information tracked for every USB device. */ struct fxlink_device { @@ -255,6 +255,8 @@ void fxlink_device_cleanup(struct fxlink_device *fdev); // notification API. //--- +#ifndef FXLINK_DISABLE_POLL + /* Tracker for libusb file descriptors to be polled in a main loop. */ struct fxlink_pollfds { /* libusb context to be tracked (must remain constant) */ @@ -274,6 +276,8 @@ void fxlink_pollfds_track(struct fxlink_pollfds *tracker, libusb_context *ctx); called before the tracker structure gets destroyed. */ void fxlink_pollfds_stop(struct fxlink_pollfds *tracker); +#endif /* FXLINK_DISABLE_POLL */ + //--- // Device tracking // diff --git a/libfxlink/logging.c b/libfxlink/logging.c index 55daca6..b6d0f84 100644 --- a/libfxlink/logging.c +++ b/libfxlink/logging.c @@ -84,7 +84,11 @@ int hlog(char const *fmt, ...) { time_t t = time(NULL); struct tm tm; +#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64) + tm = *localtime(&t); +#else localtime_r(&t, &tm); +#endif flog(FMT_WHITE | FMT_DIM, "[%02d:%02d] ", tm.tm_hour, tm.tm_min); LOG_VA_ARGS(fmt, flogv(FMT_YELLOW | FMT_DIM, fmt, _args));