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.
This commit is contained in:
Lephenixnoir 2024-08-25 23:10:51 +02:00
parent e201304423
commit 50997a8b75
No known key found for this signature in database
GPG key ID: 1BBA026E13FC0495
16 changed files with 141 additions and 23 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
# Build directory # Build directory
build/ build/
build-win64/
# Documentation drafts # Documentation drafts
doc/ doc/

View file

@ -15,7 +15,7 @@ endif()
if(NOT FXLINK_DISABLE_SDL2) if(NOT FXLINK_DISABLE_SDL2)
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET) pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
endif() endif()
pkg_check_modules(ncurses REQUIRED ncurses IMPORTED_TARGET) pkg_check_modules(ncurses REQUIRED ncursesw IMPORTED_TARGET)
set(CMAKE_INSTALL_MESSAGE LAZY) set(CMAKE_INSTALL_MESSAGE LAZY)
set(SRC "${CMAKE_CURRENT_SOURCE_DIR}") set(SRC "${CMAKE_CURRENT_SOURCE_DIR}")
@ -30,8 +30,13 @@ target_include_directories(fxgxa PUBLIC fxgxa/)
target_link_libraries(fxgxa PkgConfig::libpng) target_link_libraries(fxgxa PkgConfig::libpng)
# fxg1a as a symlink (for compatibility) # fxg1a as a symlink (for compatibility)
add_custom_target(fxg1a ALL 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") COMMAND ${CMAKE_COMMAND} -E create_symlink "fxgxa" "fxg1a")
endif()
# fxsdk # fxsdk
add_custom_command(OUTPUT "${BIN}/fxsdk.sh" add_custom_command(OUTPUT "${BIN}/fxsdk.sh"
@ -86,10 +91,12 @@ if(NOT FXLINK_DISABLE_SDL2)
endif() endif()
# fxsdk-gdb-bridge # fxsdk-gdb-bridge
add_executable(fxsdk-gdb-bridge fxsdk/gdb-bridge.c) if(NOT WIN32)
target_link_libraries(fxsdk-gdb-bridge libfxlink) add_executable(fxsdk-gdb-bridge fxsdk/gdb-bridge.c)
target_include_directories(fxsdk-gdb-bridge PRIVATE target_link_libraries(fxsdk-gdb-bridge libfxlink)
target_include_directories(fxsdk-gdb-bridge PRIVATE
"${SRC}/fxlink/include") "${SRC}/fxlink/include")
endif()
# Install rules # 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/assets DESTINATION share/fxsdk)
install(DIRECTORY fxsdk/scripts DESTINATION share/fxsdk USE_SOURCE_PERMISSIONS) install(DIRECTORY fxsdk/scripts DESTINATION share/fxsdk USE_SOURCE_PERMISSIONS)
install(DIRECTORY fxsdk/cmake/ DESTINATION lib/cmake/fxsdk) install(DIRECTORY fxsdk/cmake/ DESTINATION lib/cmake/fxsdk)
install(TARGETS fxsdk-gdb-bridge) if(NOT WIN32)
install(TARGETS fxsdk-gdb-bridge)
endif()
# fxgxa, fxg1a # fxgxa, fxg1a
install(TARGETS fxgxa) install(TARGETS fxgxa)
install(FILES "${BIN}/fxg1a" TYPE BIN) install(FILES "${BIN}/fxg1a" TYPE BIN)

View file

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

View file

@ -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); m("Sequence 2 0x01 0x%02x", h->seq2);
return (h->seq2 != 0x01) ? 1:0; return (h->seq2 != 0x01) ? 1:0;
case 5: case 5:
m("File size 1 %-8zu %u", size, m("File size 1 %-8lu %u", (unsigned long)size,
be32toh(h->filesize_be1)); be32toh(h->filesize_be1));
return (be32toh(h->filesize_be1) != size) ? 2:0; return (be32toh(h->filesize_be1) != size) ? 2:0;
case 6: case 6:
@ -66,7 +66,7 @@ static int check_g1a(int test, struct g1a const *g1a, size_t size,char *status)
be16toh(h->checksum)); be16toh(h->checksum));
return (be16toh(h->checksum) != sum) ? 2:0; return (be16toh(h->checksum) != sum) ? 2:0;
case 8: case 8:
m("File size 2 %-8zu %u", size, m("File size 2 %-8lu %u", (unsigned long)size,
be32toh(h->filesize_be2)); be32toh(h->filesize_be2));
return (be32toh(h->filesize_be2) != size) ? 2:0; return (be32toh(h->filesize_be2) != size) ? 2:0;
default: 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); m("Sequence 2 0x01 0x%02x", h->seq2);
return (h->seq2 != 0x01) ? 1:0; return (h->seq2 != 0x01) ? 1:0;
case 5: case 5:
m("File size 1 %-8zu %u", size, m("File size 1 %-8lu %u", (unsigned long)size,
be32toh(h->filesize_be1)); be32toh(h->filesize_be1));
return (be32toh(h->filesize_be1) != size) ? 2:0; return (be32toh(h->filesize_be1) != size) ? 2:0;
case 6: case 6:
@ -183,7 +183,7 @@ static int check_g3a(int test, struct g3a const *g3a, size_t size,char *status)
be16toh(h->checksum)); be16toh(h->checksum));
return (be16toh(h->checksum) != sum) ? 2:0; return (be16toh(h->checksum) != sum) ? 2:0;
case 8: case 8:
m("File size 2 %-8zu %u", size - 0x7004, m("File size 2 %-8lu %u", (unsigned long)size - 0x7004,
be32toh(h->filesize_be2)); be32toh(h->filesize_be2));
return (be32toh(h->filesize_be2) != size - 0x7004) ? 2:0; return (be32toh(h->filesize_be2) != size - 0x7004) ? 2:0;
case 9: 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)); be32toh(h->checksum_2));
return (be32toh(h->checksum_2) != sum2) ? 2:0; return (be32toh(h->checksum_2) != sum2) ? 2:0;
case 10: case 10:
m("File size 1 %-8zu %u", size, m("File size 1 %-8lu %u", (unsigned long)size,
be32toh(h->filesize_be3)); be32toh(h->filesize_be3));
return (be32toh(h->filesize_be3) != size) ? 2:0; return (be32toh(h->filesize_be3) != size) ? 2:0;
case 11: case 11:

View file

@ -24,6 +24,42 @@
#define be64toh(x) OSSwapBigToHostInt64(x) #define be64toh(x) OSSwapBigToHostInt64(x)
#define le64toh(x) OSSwapLittleToHostInt64(x) #define le64toh(x) OSSwapLittleToHostInt64(x)
#elif defined(__WINDOWS__) || defined(_WIN16) || defined(_WIN32) || defined(_WIN64)
#include <winsock2.h>
#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__) #elif defined(__linux__)
#include <sys/types.h> #include <sys/types.h>

View file

@ -237,7 +237,9 @@ int main(int argc, char **argv)
while(repeat); while(repeat);
} }
else if(mode == 't') { else if(mode == 't') {
#ifndef FXLINK_DISABLE_POLL
rc = main_tui_interactive(context); rc = main_tui_interactive(context);
#endif
} }
else if(mode == 'p') { else if(mode == 'p') {
rc = main_push(filter, &delay, context, argv + optind); rc = main_push(filter, &delay, context, argv + optind);

View file

@ -4,6 +4,9 @@
// \___/ License: MIT <https://opensource.org/licenses/MIT> // // \___/ License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
#include <fxlink/config.h>
#ifndef FXLINK_DISABLE_POLL
#include "tui.h" #include "tui.h"
#include "command-util.h" #include "command-util.h"
#include <string.h> #include <string.h>
@ -377,3 +380,5 @@ FXLINK_COMMAND("?cmdtree")
node_dump(cmdtree, 0); node_dump(cmdtree, 0);
return 0; return 0;
} }
#endif

View file

@ -4,6 +4,9 @@
// \___/ License: MIT <https://opensource.org/licenses/MIT> // // \___/ License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
#include <fxlink/config.h>
#ifndef FXLINK_DISABLE_POLL
#include "tui.h" #include "tui.h"
#include "command-util.h" #include "command-util.h"
#include <string.h> #include <string.h>
@ -271,3 +274,5 @@ FXLINK_COMMAND("gintctl test all", DEVICE(fdev))
test_read_unaligned(fdev); test_read_unaligned(fdev);
return 0; return 0;
} }
#endif

View file

@ -4,6 +4,9 @@
// \___/ License: MIT <https://opensource.org/licenses/MIT> // // \___/ License: MIT <https://opensource.org/licenses/MIT> //
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
#include <fxlink/config.h>
#ifndef FXLINK_DISABLE_POLL
#include "../fxlink.h" #include "../fxlink.h"
#include "tui.h" #include "tui.h"
#include <fxlink/tooling/libpng.h> #include <fxlink/tooling/libpng.h>
@ -202,24 +205,24 @@ static void TUI_render_transfers(void)
if(!comm) if(!comm)
continue; continue;
struct fxlink_transfer *IN = comm->ftransfer_IN; struct fxlink_transfer *in = comm->ftransfer_IN;
struct fxlink_transfer *OUT = comm->ftransfer_OUT; struct fxlink_transfer *out = comm->ftransfer_OUT;
if(IN) { if(in) {
mvwaddstr(win, y, 1, fxlink_device_id(fdev)); mvwaddstr(win, y, 1, fxlink_device_id(fdev));
mvwaddstr(win, y, 10, "IN"); 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); 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; has_transfers = true;
y++; y++;
} }
if(OUT) { if(out) {
mvwaddstr(win, y, 1, fxlink_device_id(fdev)); mvwaddstr(win, y, 1, fxlink_device_id(fdev));
mvwaddstr(win, y, 10, "OUT"); 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; has_transfers = true;
y++; y++;
} }
@ -259,10 +262,12 @@ static bool TUI_setup(void)
memset(&TUI, 0, sizeof TUI); memset(&TUI, 0, sizeof TUI);
/* Set up the SINGWINCH handler */ /* Set up the SINGWINCH handler */
#if !defined(_WIN16) && !defined(_WIN32) && !defined(_WIN64)
struct sigaction WINCH; struct sigaction WINCH;
sigaction(SIGWINCH, NULL, &WINCH); sigaction(SIGWINCH, NULL, &WINCH);
WINCH.sa_handler = TUI_SIGWINCH_handler; WINCH.sa_handler = TUI_SIGWINCH_handler;
sigaction(SIGWINCH, &WINCH, NULL); sigaction(SIGWINCH, &WINCH, NULL);
#endif
/* Initialize the main screen */ /* Initialize the main screen */
initscr(); initscr();
@ -590,3 +595,5 @@ int main_tui_interactive(libusb_context *ctx)
TUI_quit(); TUI_quit();
return 0; return 0;
} }
#endif

View file

@ -47,7 +47,11 @@ char *fxlink_gen_file_name(char const *path, char const *name,
time_t time_raw; time_t time_raw;
struct tm time_bd; struct tm time_bd;
time(&time_raw); time(&time_raw);
#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64)
time_bd = *localtime(&time_raw);
#else
localtime_r(&time_raw, &time_bd); localtime_r(&time_raw, &time_bd);
#endif
while(1) { while(1) {
asprintf(&filename, "%s/fxlink-%.16s-%04d.%02d.%02d-%02dh%02d-%d%s", 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; return filename;
} }
#ifndef FXLINK_DISABLE_POLL
int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...) int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...)
{ {
/* Convenience macro to iterate on file descriptor arrays */ /* Convenience macro to iterate on file descriptor arrays */
@ -104,6 +109,7 @@ int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...)
free(concat); free(concat);
return rc; return rc;
} }
#endif /* FXLINK_DISABLE_POLL */
char const *fxlink_size_string(int bytes) char const *fxlink_size_string(int bytes)
{ {

View file

@ -635,6 +635,8 @@ bool fxlink_device_start_bulk_OUT(struct fxlink_device *fdev,
// Polled file descriptor tracking // Polled file descriptor tracking
//--- //---
#ifndef FXLINK_DISABLE_POLL
static void generate_poll_fds(struct fxlink_pollfds *tracker) static void generate_poll_fds(struct fxlink_pollfds *tracker)
{ {
/* Get the set of libusb file descriptors to poll for news */ /* 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); memset(tracker, 0, sizeof *tracker);
} }
#endif /* FXLINK_DISABLE_POLL */
//--- //---
// Device tracking // Device tracking
//--- //---

View file

@ -29,7 +29,13 @@ static char *read_word(char const **input)
{ {
char const *str = *input; char const *str = *input;
while(**input && isword(**input)) (*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 /* Reads a property from the input source. Advances *input and sets *name and

View file

@ -13,5 +13,8 @@
/* Disable SDL2 interfaces. */ /* Disable SDL2 interfaces. */
#cmakedefine FXLINK_DISABLE_SDL2 #cmakedefine FXLINK_DISABLE_SDL2
/* Disable poll-based interfaces. */
#cmakedefine FXLINK_DISABLE_POLL
/* fxSDK version */ /* fxSDK version */
#define FXLINK_VERSION "@CMAKE_PROJECT_VERSION@" #define FXLINK_VERSION "@CMAKE_PROJECT_VERSION@"

View file

@ -12,7 +12,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <poll.h>
#ifndef FXLINK_DISABLE_POLL
# include <poll.h>
#endif
static inline int min(int x, int y) 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 *fxlink_gen_file_name(char const *path, char const *name,
char const *suffix); char const *suffix);
#ifndef FXLINK_DISABLE_POLL
/* Modified poll with a variable number of arrays. */ /* Modified poll with a variable number of arrays. */
int fxlink_multipoll(int timeout, struct pollfd *fds1, int count1, ...); 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 /* Write out the given size (in bytes) in a human-readable form. Returns a
pointer to a statically-allocated string. */ pointer to a statically-allocated string. */

View file

@ -48,8 +48,8 @@
#pragma once #pragma once
#include <fxlink/protocol.h> #include <fxlink/protocol.h>
#include <fxlink/filter.h> #include <fxlink/filter.h>
#include <fxlink/defs.h>
#include <libusb.h> #include <libusb.h>
#include <poll.h>
/* Device information tracked for every USB device. */ /* Device information tracked for every USB device. */
struct fxlink_device { struct fxlink_device {
@ -255,6 +255,8 @@ void fxlink_device_cleanup(struct fxlink_device *fdev);
// notification API. // notification API.
//--- //---
#ifndef FXLINK_DISABLE_POLL
/* Tracker for libusb file descriptors to be polled in a main loop. */ /* Tracker for libusb file descriptors to be polled in a main loop. */
struct fxlink_pollfds { struct fxlink_pollfds {
/* libusb context to be tracked (must remain constant) */ /* 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. */ called before the tracker structure gets destroyed. */
void fxlink_pollfds_stop(struct fxlink_pollfds *tracker); void fxlink_pollfds_stop(struct fxlink_pollfds *tracker);
#endif /* FXLINK_DISABLE_POLL */
//--- //---
// Device tracking // Device tracking
// //

View file

@ -84,7 +84,11 @@ int hlog(char const *fmt, ...)
{ {
time_t t = time(NULL); time_t t = time(NULL);
struct tm tm; struct tm tm;
#if defined(_WIN16) || defined(_WIN32) || defined(_WIN64)
tm = *localtime(&t);
#else
localtime_r(&t, &tm); localtime_r(&t, &tm);
#endif
flog(FMT_WHITE | FMT_DIM, "[%02d:%02d] ", tm.tm_hour, tm.tm_min); flog(FMT_WHITE | FMT_DIM, "[%02d:%02d] ", tm.tm_hour, tm.tm_min);
LOG_VA_ARGS(fmt, flogv(FMT_YELLOW | FMT_DIM, fmt, _args)); LOG_VA_ARGS(fmt, flogv(FMT_YELLOW | FMT_DIM, fmt, _args));