Compare commits

...

8 commits

Author SHA1 Message Date
Lephenixnoir
6d75c3aa82
gdb-bridge: add missing include
Appears to be transitively included on your usual Linux distros but
not on MacOS.
2024-09-23 11:22:28 +02:00
Lephenixnoir
1ceeabdc36
fxconv: recognize the new line-distance param for fonts 2024-09-14 07:29:47 +02:00
Lephenixnoir
92a95e0090
libfxlink: no-colors option + don't always enumerate devices [Windows]
Enumerating devices constantly caused some sort of error/crash that
would stop the monitor after just one frame or so.
2024-09-14 07:29:15 +02:00
Lephenixnoir
efcd6ec241
libfxlink, fxlink: install rules for MinGW build [Windows] 2024-09-14 07:29:10 +02:00
Lephenixnoir
9de441d0f4
libfxlink: basic device enumeration without hotplug [Windows] 2024-09-14 07:26:56 +02:00
Lephenixnoir
c3d7fd6efa
fxlink: find SDL2 without -mwindows to stay in console [Windows]
When loading SDL2 with pkg-config the -mwindows flag is added, which
instructs the loader to load the program through WinMain() and not
create a console for it. This is intended for GUI programs. However,
fxlink is a CLI program with just occasionally an SDL window on top of
it. Disable -mwindows to keep the console and terminal output. I don't
know how to do that with the pkg-config CMake module, so use the SDL2
module for the Windows build instead.
2024-09-14 07:26:56 +02:00
Lephenixnoir
b83796a382
fxgxa: use standard fopen() for reading files [Windows] 2024-09-14 07:26:56 +02:00
Lephenixnoir
50997a8b75
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.
2024-09-14 07:26:56 +02:00
20 changed files with 255 additions and 73 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

@ -13,9 +13,16 @@ if(NOT FXLINK_DISABLE_UDISKS2)
pkg_check_modules(udisks2 REQUIRED udisks2 IMPORTED_TARGET) pkg_check_modules(udisks2 REQUIRED udisks2 IMPORTED_TARGET)
endif() endif()
if(NOT FXLINK_DISABLE_SDL2) if(NOT FXLINK_DISABLE_SDL2)
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET) if(WIN32)
set(SDL2_NO_MWINDOWS 1)
find_package(SDL2 REQUIRED)
else()
pkg_check_modules(sdl2 REQUIRED sdl2 IMPORTED_TARGET)
set(SDL2_LIBRARIES PkgConfig::sdl2)
set(SDL2_INCLUDE_DIRS)
endif()
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 +37,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)
COMMAND ${CMAKE_COMMAND} -E create_symlink "fxgxa" "fxg1a") 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 # fxsdk
add_custom_command(OUTPUT "${BIN}/fxsdk.sh" add_custom_command(OUTPUT "${BIN}/fxsdk.sh"
@ -82,34 +94,49 @@ if(NOT FXLINK_DISABLE_UDISKS2)
target_link_libraries(fxlink PkgConfig::udisks2) target_link_libraries(fxlink PkgConfig::udisks2)
endif() endif()
if(NOT FXLINK_DISABLE_SDL2) if(NOT FXLINK_DISABLE_SDL2)
target_link_libraries(fxlink PkgConfig::sdl2) target_link_libraries(fxlink ${SDL2_LIBRARIES})
target_include_directories(fxlink PRIVATE ${SDL2_INCLUDE_DIRS})
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)
"${SRC}/fxlink/include") target_include_directories(fxsdk-gdb-bridge PRIVATE
"${SRC}/fxlink/include")
endif()
# Install rules # Install rules
# fxsdk set(SYSROOT "")
install(PROGRAMS "${BIN}/fxsdk.sh" TYPE BIN RENAME fxsdk) if(WIN32)
install(DIRECTORY fxsdk/assets DESTINATION share/fxsdk) set(SYSROOT "x86_64-w64-mingw32/")
install(DIRECTORY fxsdk/scripts DESTINATION share/fxsdk USE_SOURCE_PERMISSIONS) endif()
install(DIRECTORY fxsdk/cmake/ DESTINATION lib/cmake/fxsdk)
install(TARGETS fxsdk-gdb-bridge) if(NOT WIN32)
# fxgxa, fxg1a # fxsdk
install(TARGETS fxgxa) install(PROGRAMS "${BIN}/fxsdk.sh" TYPE BIN RENAME fxsdk)
install(FILES "${BIN}/fxg1a" TYPE BIN) install(DIRECTORY fxsdk/assets DESTINATION share/fxsdk)
# fxconv install(DIRECTORY fxsdk/scripts DESTINATION share/fxsdk USE_SOURCE_PERMISSIONS)
install(PROGRAMS fxconv/fxconv-main.py TYPE BIN RENAME fxconv) install(DIRECTORY fxsdk/cmake/ DESTINATION lib/cmake/fxsdk)
install(FILES fxconv/fxconv.py TYPE BIN) install(TARGETS fxsdk-gdb-bridge)
# fxgxa, fxg1a
install(TARGETS fxgxa)
install(FILES "${BIN}/fxg1a" TYPE BIN)
# fxconv
install(PROGRAMS fxconv/fxconv-main.py TYPE BIN RENAME fxconv)
install(FILES fxconv/fxconv.py TYPE BIN)
# fxlink
install(TARGETS fxlink)
else()
# fxlink
install(TARGETS fxlink DESTINATION "${SYSROOT}bin")
endif()
# libfxlink # libfxlink
install(FILES "${BIN}/include/fxlink/config.h" DESTINATION include/fxlink/) install(FILES "${BIN}/include/fxlink/config.h"
install(DIRECTORY libfxlink/include/ DESTINATION include DESTINATION "${SYSROOT}include/fxlink/")
install(DIRECTORY libfxlink/include/ DESTINATION "${SYSROOT}include"
FILES_MATCHING PATTERN "*.h") FILES_MATCHING PATTERN "*.h")
install(DIRECTORY libfxlink/cmake/ DESTINATION lib/cmake) install(DIRECTORY libfxlink/cmake/ DESTINATION "${SYSROOT}lib/cmake")
install(TARGETS libfxlink DESTINATION lib) install(TARGETS libfxlink DESTINATION "${SYSROOT}lib")
# fxlink
install(TARGETS fxlink)

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. Install to get libfxlink.
```bash
% x86_64-w64-mingw32-cmake -B build-win64 -DCMAKE_INSTALL_PREFIX="$HOME/.local" -DFXLINK_DISABLE_UDISKS2=1 -DFXLINK_DISABLE_POLL=1 -DFXLINK_DISABLE_ANSIESC=1
% make -C build-win64 install
```

View file

@ -755,6 +755,9 @@ def convert_topti(input, params):
# Default character spacing to 1 # Default character spacing to 1
char_spacing = int(params.get("char-spacing", "1")) char_spacing = int(params.get("char-spacing", "1"))
# Default line distance to line height + 1
line_distance = int(params.get("line-distance", line_height + 1))
#-- #--
# Encoding blocks # Encoding blocks
#--- #---
@ -832,7 +835,7 @@ def convert_topti(input, params):
o += u8(flags) + u8(line_height) + u8(grid.h) + u8(len(blocks)) o += u8(flags) + u8(line_height) + u8(grid.h) + u8(len(blocks))
o += u32(glyph_count) o += u32(glyph_count)
o += u8(char_spacing) + bytes(3) o += u8(char_spacing) + u8(line_distance) + bytes(2)
o += ref(data_blocks) o += ref(data_blocks)
o += ref(data_glyphs) o += ref(data_glyphs)

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

@ -19,7 +19,7 @@ static void invert_header(void *gxa)
#define fail(msg, ...) { \ #define fail(msg, ...) { \
fprintf(stderr, "error: " msg ": %m\n", ##__VA_ARGS__); \ fprintf(stderr, "error: " msg ": %m\n", ##__VA_ARGS__); \
close(fd); \ fclose(fp); \
free(data); \ free(data); \
return NULL; \ return NULL; \
} }
@ -28,31 +28,31 @@ static void invert_header(void *gxa)
Allocates a buffer with @prepend leading bytes initialized to zero. */ Allocates a buffer with @prepend leading bytes initialized to zero. */
static void *load(const char *filename, size_t *size, int header, int footer) static void *load(const char *filename, size_t *size, int header, int footer)
{ {
int fd; FILE *fp;
struct stat statbuf;
void *data = NULL; void *data = NULL;
size_t filesize; long filesize;
fd = open(filename, O_RDONLY); fp = fopen(filename, "rb");
if(fd < 0) fail("cannot open %s", filename); if(!fp) fail("cannot open %s", filename);
int x = fstat(fd, &statbuf); fseek(fp, 0, SEEK_END);
if(x > 0) fail("cannot stat %s", filename); filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
filesize = statbuf.st_size; if(ftell(fp) != 0) fail("cannod rewind %s", filename);
data = malloc(header + filesize + footer); data = malloc(header + filesize + footer);
if(!data) fail("cannot load %s", filename); if(!data) fail("cannot load %s", filename);
size_t remaining = filesize; long remaining = filesize;
while(remaining > 0) while(remaining > 0)
{ {
size_t offset = header + filesize - remaining; long offset = header + filesize - remaining;
ssize_t y = read(fd, data + offset, remaining); long y = fread(data + offset, 1, remaining, fp);
if(y < 0) fail("cannot read from %s", filename); if(y <= 0) fail("cannot read from %s at offset %ld",
filename, offset);
remaining -= y; remaining -= y;
} }
close(fd); fclose(fp);
memset(data, 0, header); memset(data, 0, header);
memset(data + header + filesize, 0, footer); memset(data + header + filesize, 0, footer);

View file

@ -16,6 +16,11 @@
#include <errno.h> #include <errno.h>
#include <locale.h> #include <locale.h>
#ifndef FXLINK_DISABLE_SDL2
/* Grab main()-related macros */
#include <SDL2/SDL.h>
#endif
static const char *help_string = static const char *help_string =
"usage: %1$s (-l|-b|-t) [General options]\n" "usage: %1$s (-l|-b|-t) [General options]\n"
" %1$s -i [-r] [--fxlink-log[=<FILE>]] [General options]\n" " %1$s -i [-r] [--fxlink-log[=<FILE>]] [General options]\n"
@ -237,7 +242,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

@ -1,6 +1,7 @@
#include <assert.h> #include <assert.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/un.h> #include <sys/un.h>

View file

@ -1,23 +1,38 @@
# Locate the library file and includes # Locate the library file and includes
if(WIN32)
set(SYSROOT "x86_64-w64-mingw32/")
else()
set(SYSROOT)
endif()
find_library( find_library(
LIBFXLINK_PATH "fxlink" LIBFXLINK_PATH "fxlink" "libfxlink.a"
HINTS "$ENV{HOME}/.local/lib" "$ENV{FXSDK_PATH}/lib" HINTS "$ENV{HOME}/.local/${SYSROOT}lib" "$ENV{FXSDK_PATH}/${SYSROOT}lib"
) )
if(LIBFXLINK_PATH STREQUAL "LIBFXLINK_PATH-NOTFOUND") if(LIBFXLINK_PATH STREQUAL "LIBFXLINK_PATH-NOTFOUND")
message(SEND_ERROR # Try the paths directly
"Could not find libfxlink.a!\n" set(P1 "$ENV{HOME}/.local/${SYSROOT}lib/libfxlink.a")
"You can specify the install path with the environment variable " set(P2 "$ENV{FXSDK_PATH}/${SYSROOT}lib/libfxlink.a")
"FXSDK_PATH, such as FXSDK_PATH=$HOME/.local") if(EXISTS "${P1}")
else() set(LIBFXLINK_PATH "${P1}")
get_filename_component(LIBFXLINK_PATH "${LIBFXLINK_PATH}/../.." ABSOLUTE) elseif(DEFINED "$ENV{FXSDK_PATH}" AND EXISTS "${P2}")
set(LIBFXLINK_LIB "${LIBFXLINK_PATH}/lib/libfxlink.a") set(LIBFXLINK_PATH "${P2}")
set(LIBFXLINK_INCLUDE "${LIBFXLINK_PATH}/include") else()
message(FATAL_ERROR
message("(libfxlink) Found libfxlink at: ${LIBFXLINK_LIB}") "Could not find libfxlink.a!\n"
message("(libfxlink) Will take includes from: ${LIBFXLINK_INCLUDE}") "You can specify the install path with the environment variable "
"FXSDK_PATH, such as FXSDK_PATH=$HOME/.local")
endif()
endif() endif()
get_filename_component(LIBFXLINK_PATH "${LIBFXLINK_PATH}/../.." ABSOLUTE)
set(LIBFXLINK_LIB "${LIBFXLINK_PATH}/lib/libfxlink.a")
set(LIBFXLINK_INCLUDE "${LIBFXLINK_PATH}/include")
message("(libfxlink) Found libfxlink at: ${LIBFXLINK_LIB}")
message("(libfxlink) Will take includes from: ${LIBFXLINK_INCLUDE}")
# Find library version # Find library version
if(NOT EXISTS "${LIBFXLINK_INCLUDE}/fxlink/config.h") if(NOT EXISTS "${LIBFXLINK_INCLUDE}/fxlink/config.h")

View file

@ -15,6 +15,9 @@
char const *fmt_to_ANSI(int format) char const *fmt_to_ANSI(int format)
{ {
#ifdef FXLINK_DISABLE_ANSIESC
return "";
#else
static char buf[64]; static char buf[64];
int n = 0; int n = 0;
@ -36,6 +39,7 @@ char const *fmt_to_ANSI(int format)
strcpy(buf+n, "\e[3m"), n += 4; strcpy(buf+n, "\e[3m"), n += 4;
return buf; return buf;
#endif
} }
char *fxlink_gen_file_name(char const *path, char const *name, char *fxlink_gen_file_name(char const *path, char const *name,
@ -47,7 +51,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 +75,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 +113,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

@ -227,7 +227,8 @@ void fxlink_device_analysis_1(struct fxlink_device *fdev, bool quiet)
if(!quiet) { if(!quiet) {
hlog("calculators %s", fxlink_device_id(fdev)); hlog("calculators %s", fxlink_device_id(fdev));
log_("%1$d interface%2$s, class code%2$s", calc->interface_count, log_("%d interface%s, class code%s", calc->interface_count,
calc->interface_count != 1 ? "s" : "",
calc->interface_count != 1 ? "s" : ""); calc->interface_count != 1 ? "s" : "");
for(int i = 0; i < calc->interface_count; i++) { for(int i = 0; i < calc->interface_count; i++) {
@ -635,6 +636,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 +708,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
//--- //---
@ -813,13 +818,16 @@ bool fxlink_device_list_track(struct fxlink_device_list *list,
libusb_context *ctx) libusb_context *ctx)
{ {
memset(list, 0, sizeof *list); memset(list, 0, sizeof *list);
list->ctx = ctx;
if(!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) { if(!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
elog("libusb doesn't handle hotplug; devices may not be detected\n"); elog("libusb doesn't handle hotplug; devices may not be detected\n");
list->hotplug_supported = false;
enumerate_devices(ctx, list);
return false; return false;
} }
list->ctx = ctx; list->hotplug_supported = true;
libusb_hotplug_register_callback(ctx, libusb_hotplug_register_callback(ctx,
/* Both arriving and departing devices */ /* Both arriving and departing devices */
LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,

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,11 @@
/* Disable SDL2 interfaces. */ /* Disable SDL2 interfaces. */
#cmakedefine FXLINK_DISABLE_SDL2 #cmakedefine FXLINK_DISABLE_SDL2
/* Disable poll-based interfaces. */
#cmakedefine FXLINK_DISABLE_POLL
/* Disable printing ANSI escape sequences. */
#cmakedefine FXLINK_DISABLE_ANSIESC
/* fxSDK version */ /* fxSDK version */
#define FXLINK_VERSION "@CMAKE_PROJECT_VERSION@" #define FXLINK_VERSION "@CMAKE_PROJECT_VERSION@"

View file

@ -12,7 +12,18 @@
#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
#ifdef min
# undef min
#endif
#ifdef max
# undef max
#endif
static inline int min(int x, int y) static inline int min(int x, int y)
{ {
@ -84,8 +95,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
// //
@ -295,6 +299,9 @@ struct fxlink_device_list {
libusb_context *ctx; libusb_context *ctx;
/* Callback handle */ /* Callback handle */
libusb_hotplug_callback_handle hotplug_handle; libusb_hotplug_callback_handle hotplug_handle;
/* Whether the hotplug callback could be installed. If not, refreshes
will be made manually. */
bool hotplug_supported;
/* Array of connected devices */ /* Array of connected devices */
struct fxlink_device *devices; struct fxlink_device *devices;
/* Number of elements in `devices` */ /* Number of elements in `devices` */

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));