From ff491de7bc003297ec8b86d35f0f22618e5790ce Mon Sep 17 00:00:00 2001 From: Ewan Croft Date: Fri, 10 Jul 2026 02:41:32 +0100 Subject: [PATCH] feat(platform): extend to Nintendo Wii U, 3DS, and Windows --- .devdeps/3ds.cmake | 52 ++++++++++++++++ .devdeps/linux-aarch64.cmake | 34 ++++++++++ .devdeps/wiiu.cmake | 53 ++++++++++++++++ .devdeps/windows.cmake | 40 ++++++++++++ CMakeLists.txt | 89 ++++++++++++++++++--------- include/wolfram/platform.h | 17 ++++- src/platform/3ds_platform.c | 106 ++++++++++++++++++++++++++++++++ src/platform/wiiu_platform.c | 105 +++++++++++++++++++++++++++++++ src/platform/windows_platform.c | 71 +++++++++++++++++++++ 9 files changed, 536 insertions(+), 31 deletions(-) create mode 100644 .devdeps/3ds.cmake create mode 100644 .devdeps/linux-aarch64.cmake create mode 100644 .devdeps/wiiu.cmake create mode 100644 .devdeps/windows.cmake create mode 100644 src/platform/3ds_platform.c create mode 100644 src/platform/wiiu_platform.c create mode 100644 src/platform/windows_platform.c diff --git a/.devdeps/3ds.cmake b/.devdeps/3ds.cmake new file mode 100644 index 0000000..53e82e0 --- /dev/null +++ b/.devdeps/3ds.cmake @@ -0,0 +1,52 @@ +# 3ds.cmake — CMake toolchain file for Nintendo 3DS cross-compilation. +# +# Usage: +# cmake -DCMAKE_TOOLCHAIN_FILE=.devdeps/3ds.cmake \ +# -DWOLFRAM_BUILD_3DS=ON \ +# -B build-3ds +# +# Requires devkitPro with devkitARM and libctru installed: +# dkp-pacman -S 3ds-dev +# +# Set DEVKITPRO=/opt/devkitpro before invoking cmake. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm) +set(CMAKE_SYSTEM_VERSION 1) + +# ARM is little-endian +set(CMAKE_C_BYTE_ORDER LITTLE_ENDIAN) +set(CMAKE_CXX_BYTE_ORDER LITTLE_ENDIAN) + +# devkitPro paths +if(DEFINED ENV{DEVKITPRO}) + set(DEVKITPRO $ENV{DEVKITPRO}) +else() + set(DEVKITPRO /opt/devkitpro) +endif() + +set(DEVKITARM ${DEVKITPRO}/devkitARM) +set(LIBCTRU ${DEVKITPRO}/libctru) +set(PORTLIBS ${DEVKITPRO}/portlibs/3ds) + +# Compilers (ARM) +set(CMAKE_C_COMPILER ${DEVKITARM}/bin/arm-none-eabi-gcc) +set(CMAKE_CXX_COMPILER ${DEVKITARM}/bin/arm-none-eabi-g++) +set(CMAKE_ASM_COMPILER ${DEVKITARM}/bin/arm-none-eabi-gcc) +set(CMAKE_AR ${DEVKITARM}/bin/arm-none-eabi-ar) +set(CMAKE_RANLIB ${DEVKITARM}/bin/arm-none-eabi-ranlib) +set(CMAKE_OBJCOPY ${DEVKITARM}/bin/arm-none-eabi-objcopy) +set(CMAKE_OBJDUMP ${DEVKITARM}/bin/arm-none-eabi-objdump) + +# 3DS flags: ARM11 (ARMv6), hard-float, VFP +set(CMAKE_C_FLAGS_INIT "-march=armv6k -mtune=arm1176jzf-s -mfloat-abi=hard -mfpu=vfp -ffunction-sections -fdata-sections -Wno-error=incompatible-pointer-types") +set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}") + +set(CMAKE_EXE_LINKER_FLAGS_INIT "-march=armv6k -L${LIBCTRU}/lib -L${PORTLIBS}/lib") + +# Don't search host paths for libraries/headers +set(CMAKE_FIND_ROOT_PATH ${DEVKITARM} ${LIBCTRU} ${PORTLIBS}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/.devdeps/linux-aarch64.cmake b/.devdeps/linux-aarch64.cmake new file mode 100644 index 0000000..0cc6b3d --- /dev/null +++ b/.devdeps/linux-aarch64.cmake @@ -0,0 +1,34 @@ +# linux-aarch64.cmake — CMake toolchain file for Linux AArch64 cross-compilation. +# +# Usage: +# cmake -DCMAKE_TOOLCHAIN_FILE=.devdeps/linux-aarch64.cmake \ +# -B build-linux-arm64 +# +# Requires the AArch64 cross-compiler: +# macOS: brew install aarch64-elf-gcc (or use a Docker-based sysroot) +# Linux: apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu +# +# Produces a statically-linked Linux ELF binary for AArch64 (e.g. Raspberry Pi, +# AWS Graviton, etc.). For native x86_64 Linux, no toolchain file is needed. + +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) +set(CMAKE_SYSTEM_VERSION 1) + +set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) +set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++) + +# AArch64 is little-endian +set(CMAKE_C_BYTE_ORDER LITTLE_ENDIAN) +set(CMAKE_CXX_BYTE_ORDER LITTLE_ENDIAN) + +set(CMAKE_C_FLAGS_INIT "-O2 -ffunction-sections -fdata-sections") +set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}") +set(CMAKE_EXE_LINKER_FLAGS_INIT "-Wl,--gc-sections") + +# Don't search host paths for libraries/headers +set(CMAKE_FIND_ROOT_PATH /usr/aarch64-linux-gnu) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/.devdeps/wiiu.cmake b/.devdeps/wiiu.cmake new file mode 100644 index 0000000..5c61aec --- /dev/null +++ b/.devdeps/wiiu.cmake @@ -0,0 +1,53 @@ +# wiiu.cmake — CMake toolchain file for Nintendo Wii U cross-compilation. +# +# Usage: +# cmake -DCMAKE_TOOLCHAIN_FILE=.devdeps/wiiu.cmake \ +# -DWOLFRAM_BUILD_WIIU=ON \ +# -B build-wiiu +# +# Requires devkitPro with devkitPPC and the wut SDK installed: +# dkp-pacman -S wiiu-dev +# +# Set DEVKITPRO=/opt/devkitpro before invoking cmake. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR powerpc) +set(CMAKE_SYSTEM_VERSION 1) + +# PowerPC is big-endian +set(CMAKE_C_BYTE_ORDER BIG_ENDIAN) +set(CMAKE_CXX_BYTE_ORDER BIG_ENDIAN) + +# devkitPro paths +if(DEFINED ENV{DEVKITPRO}) + set(DEVKITPRO $ENV{DEVKITPRO}) +else() + set(DEVKITPRO /opt/devkitpro) +endif() + +set(DEVKITPPC ${DEVKITPRO}/devkitPPC) +set(WUT ${DEVKITPRO}/wut) +set(PORTLIBS ${DEVKITPRO}/portlibs/wiiu) + +# Compilers (same devkitPPC as Wii, different flags) +set(CMAKE_C_COMPILER ${DEVKITPPC}/bin/powerpc-eabi-gcc) +set(CMAKE_CXX_COMPILER ${DEVKITPPC}/bin/powerpc-eabi-g++) +set(CMAKE_ASM_COMPILER ${DEVKITPPC}/bin/powerpc-eabi-gcc) +set(CMAKE_AR ${DEVKITPPC}/bin/powerpc-eabi-ar) +set(CMAKE_RANLIB ${DEVKITPPC}/bin/powerpc-eabi-ranlib) +set(CMAKE_OBJCOPY ${DEVKITPPC}/bin/powerpc-eabi-objcopy) +set(CMAKE_OBJDUMP ${DEVKITPPC}/bin/powerpc-eabi-objdump) + +# Wii U flags: Espresso CPU (tri-core PowerPC 750CL), big-endian +# -D__WIIU__ is defined by the wut headers, not here. +set(CMAKE_C_FLAGS_INIT "-mwiiu -mcpu=750 -meabi -mhard-float -ffunction-sections -fdata-sections -Wno-error=incompatible-pointer-types") +set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}") + +set(CMAKE_EXE_LINKER_FLAGS_INIT "-mwiiu -L${WUT}/lib -L${PORTLIBS}/lib") + +# Don't search host paths for libraries/headers +set(CMAKE_FIND_ROOT_PATH ${DEVKITPPC} ${WUT} ${PORTLIBS}) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/.devdeps/windows.cmake b/.devdeps/windows.cmake new file mode 100644 index 0000000..3b5b22b --- /dev/null +++ b/.devdeps/windows.cmake @@ -0,0 +1,40 @@ +# windows.cmake — CMake toolchain file for Windows cross-compilation (MinGW-w64). +# +# Usage: +# cmake -DCMAKE_TOOLCHAIN_FILE=.devdeps/windows.cmake \ +# -DWOLFRAM_BUILD_WINDOWS=ON \ +# -B build-windows +# +# Requires MinGW-w64: +# macOS: brew install mingw-w64 +# Linux: apt install mingw-w64 +# +# Cross-compiles from Linux/macOS to produce a Windows .exe/.dll. +# For native Windows builds, use the standard MSVC or MinGW toolchain +# directly — no toolchain file needed. + +set(CMAKE_SYSTEM_NAME Windows) +set(CMAKE_SYSTEM_PROCESSOR x86_64) +set(CMAKE_SYSTEM_VERSION 10) + +set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) +set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) +set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) +set(CMAKE_AR x86_64-w64-mingw32-ar) +set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib) + +# Windows is little-endian +set(CMAKE_C_BYTE_ORDER LITTLE_ENDIAN) +set(CMAKE_CXX_BYTE_ORDER LITTLE_ENDIAN) + +# MinGW flags +set(CMAKE_C_FLAGS_INIT "-O2 -ffunction-sections -fdata-sections") +set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}") +set(CMAKE_EXE_LINKER_FLAGS_INIT "-static -Wl,--gc-sections") + +# Don't search host paths for libraries/headers +set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/CMakeLists.txt b/CMakeLists.txt index 124382e..4a631fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,16 +16,35 @@ endif() add_compile_options(-Wall -Wextra -Wpedantic) -# Wii cross-compilation target. When ON, desktop-specific dependencies -# (libcurl, OpenSSL, pthreads) are replaced with platform stubs. +# Console/embedded cross-compilation targets. When any is ON, desktop-specific +# dependencies (libcurl, OpenSSL, pthreads) are replaced with platform stubs. option(WOLFRAM_BUILD_WII "Build for Nintendo Wii (devkitPPC/libogc)" OFF) +option(WOLFRAM_BUILD_WIIU "Build for Nintendo Wii U (devkitPPC/wut)" OFF) +option(WOLFRAM_BUILD_3DS "Build for Nintendo 3DS (devkitARM/libctru)" OFF) -if(NOT WOLFRAM_BUILD_WII) +# Windows cross-compilation (MinGW-w64). Uses Win32 APIs instead of POSIX. +option(WOLFRAM_BUILD_WINDOWS "Build for Windows (MinGW-w64 cross-compilation)" OFF) + +# Derived: true for any embedded/console target +if(WOLFRAM_BUILD_WII OR WOLFRAM_BUILD_WIIU OR WOLFRAM_BUILD_3DS) + set(WOLFRAM_BUILD_EMBEDDED ON) +else() + set(WOLFRAM_BUILD_EMBEDDED OFF) +endif() + +# Derived: true for any non-POSIX target (embedded or Windows) +if(WOLFRAM_BUILD_EMBEDDED OR WOLFRAM_BUILD_WINDOWS) + set(WOLFRAM_BUILD_NON_POSIX ON) +else() + set(WOLFRAM_BUILD_NON_POSIX OFF) +endif() + +if(NOT WOLFRAM_BUILD_NON_POSIX) find_package(CURL REQUIRED) find_package(OpenSSL REQUIRED) find_package(Threads REQUIRED) endif() -if(NOT WOLFRAM_BUILD_WII) +if(NOT WOLFRAM_BUILD_EMBEDDED) find_package(PkgConfig QUIET) if(PkgConfig_FOUND) pkg_check_modules(SECP256K1 libsecp256k1) @@ -71,12 +90,12 @@ set_target_properties(cbor PROPERTIES POSITION_INDEPENDENT_CODE ON) add_library(wolfram # Transport - $,src/transport/xrpc_wii.c,src/transport/xrpc.c> - $,src/transport/websocket_wii.c,src/transport/websocket.c> + $,src/transport/xrpc_wii.c,src/transport/xrpc.c> + $,src/transport/websocket_wii.c,src/transport/websocket.c> # Identity src/identity/identity.c # Crypto - $,src/crypto/crypto_wii.c,src/crypto/crypto.c> + $,src/crypto/crypto_wii.c,src/crypto/crypto.c> # Repository (DAG-CBOR, CID, CAR, MST, commit, record, diff, sync) src/repo/cbor.c src/repo/cid.c @@ -91,9 +110,9 @@ add_library(wolfram src/repo/cbor_map_find.c # Session src/session/session.c - $<$>:src/session/auth_client.c> + $<$>:src/session/auth_client.c> # OAuth (metadata, PKCE, DPoP, PAR, state, callback, flow) - $<$>: + $<$>: src/session/oauth/util.c src/session/oauth/meta.c src/session/oauth/pkce.c @@ -104,7 +123,7 @@ add_library(wolfram src/session/oauth/flow.c > # OAuth resource-server verification (Bearer + DPoP) - $<$>:src/oauth/verify.c> + $<$>:src/oauth/verify.c> # Jetstream src/jetstream/jetstream.c # Label subscriptions @@ -114,9 +133,9 @@ add_library(wolfram # Syntax validation src/syntax/syntax.c # TID generation clock - $,src/platform/wii_tid.c,src/tid.c> + $,src/platform/wii_tid.c,src/tid.c> # Lexicon validation - $<$>:src/validate/validate.c> + $<$>:src/validate/validate.c> # High-level agent API src/agent/agent.c src/agent/post.c @@ -158,7 +177,7 @@ add_library(wolfram src/agent/chat_typed.c src/admin_typed.c src/sync_typed.c - $<$>:src/server_typed.c> + $<$>:src/server_typed.c> src/agent/lexicon_typed.c src/agent/threadgate_postgate.c src/agent/moderation_actions.c @@ -186,9 +205,9 @@ src/agent/push_endpoint.c # Generated lexicon endpoint wrappers src/atproto_lex.c # Server account management (PDS server-side) - $<$>:src/server/server.c> + $<$>:src/server/server.c> # Service-auth (service JWT) token issuance + verification - $<$>:src/server/service_auth.c> + $<$>:src/server/service_auth.c> # DID PLC operation build / sign / submit helpers src/plc/plc.c # New utilities and embed support @@ -209,24 +228,36 @@ src/agent/push_endpoint.c src/image.c ) -# Wii platform support +# Embedded/console platform support if(WOLFRAM_BUILD_WII) - target_sources(wolfram PRIVATE - src/platform/wii_platform.c - src/openssl_compat.c - ) + target_sources(wolfram PRIVATE src/platform/wii_platform.c src/openssl_compat.c) target_compile_definitions(wolfram PUBLIC WOLFRAM_WII) - # Make #include resolve to our shim headers target_include_directories(wolfram PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) - # Wii: skip server, examples, tests (no curl/OpenSSL/pthreads) + message(STATUS "Building for Nintendo Wii (WOLFRAM_BUILD_WII=ON)") +elseif(WOLFRAM_BUILD_WIIU) + target_sources(wolfram PRIVATE src/platform/wiiu_platform.c src/openssl_compat.c) + target_compile_definitions(wolfram PUBLIC WOLFRAM_WIIU) + target_include_directories(wolfram PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) + message(STATUS "Building for Nintendo Wii U (WOLFRAM_BUILD_WIIU=ON)") +elseif(WOLFRAM_BUILD_3DS) + target_sources(wolfram PRIVATE src/platform/3ds_platform.c src/openssl_compat.c) + target_compile_definitions(wolfram PUBLIC WOLFRAM_3DS) + target_include_directories(wolfram PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src) + message(STATUS "Building for Nintendo 3DS (WOLFRAM_BUILD_3DS=ON)") +elseif(WOLFRAM_BUILD_WINDOWS) + target_sources(wolfram PRIVATE src/platform/windows_platform.c) + target_compile_definitions(wolfram PUBLIC WOLFRAM_WINDOWS) + target_link_libraries(wolfram PUBLIC ws2_32 bcrypt) + message(STATUS "Building for Windows (WOLFRAM_BUILD_WINDOWS=ON)") +else() + target_sources(wolfram PRIVATE src/platform/posix_platform.c) +endif() + +if(WOLFRAM_BUILD_EMBEDDED) + # Embedded targets: skip server, examples, tests (no curl/OpenSSL/pthreads) set(WOLFRAM_BUILD_SERVER OFF CACHE BOOL "" FORCE) set(WOLFRAM_BUILD_TESTS OFF CACHE BOOL "" FORCE) set(WOLFRAM_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) - message(STATUS "Building for Nintendo Wii (WOLFRAM_BUILD_WII=ON)") -else() - target_sources(wolfram PRIVATE - src/platform/posix_platform.c - ) endif() # XRPC server module (optional, requires libmicrohttpd) @@ -295,7 +326,7 @@ target_include_directories(wolfram ${SECP256K1_INCLUDE_DIRS} ) -if(NOT WOLFRAM_BUILD_WII) +if(NOT WOLFRAM_BUILD_EMBEDDED) target_link_libraries(wolfram PUBLIC CURL::libcurl cjson OpenSSL::Crypto Threads::Threads) else() target_link_libraries(wolfram PUBLIC cjson) @@ -467,7 +498,7 @@ endif() # Always built (not gated on WOLFRAM_BUILD_EXAMPLES) so the CLI is part of the # default build. The target is named wolfram_cli because the wolfram library # already owns the `wolfram` target name; OUTPUT_NAME keeps the binary `wolfram`. -if(NOT WOLFRAM_BUILD_WII) +if(NOT WOLFRAM_BUILD_EMBEDDED) add_executable(wolfram_cli src/cli/main.c) target_link_libraries(wolfram_cli PRIVATE wolfram) target_include_directories(wolfram_cli PRIVATE ${cjson_SOURCE_DIR} ${cjson_BINARY_DIR}) diff --git a/include/wolfram/platform.h b/include/wolfram/platform.h index ecd5983..07de800 100644 --- a/include/wolfram/platform.h +++ b/include/wolfram/platform.h @@ -6,7 +6,7 @@ * (Linux/macOS) and embedded targets (Nintendo Wii via devkitPPC/libogc). * * On desktop, these map to POSIX APIs. On Wii, they map to libogc primitives. - * The public API is identical across platforms. + * On Windows, they map to Win32 APIs. The public API is identical across platforms. */ #ifndef WOLFRAM_PLATFORM_H @@ -23,8 +23,21 @@ extern "C" { /* ── Platform detection ──────────────────────────────────────────────── */ -#if defined(__WII__) +/* + * Platform macros are set via target_compile_definitions in CMakeLists.txt: + * WOLFRAM_WII, WOLFRAM_WIIU, WOLFRAM_3DS, WOLFRAM_WINDOWS + * + * Compiler-provided macros (__APPLE__, __linux__) are used as fallbacks. + */ + +#if defined(WOLFRAM_WII) #define WOLFRAM_PLATFORM_WII 1 +#elif defined(WOLFRAM_WIIU) + #define WOLFRAM_PLATFORM_WIIU 1 +#elif defined(WOLFRAM_3DS) + #define WOLFRAM_PLATFORM_3DS 1 +#elif defined(WOLFRAM_WINDOWS) || defined(_WIN32) + #define WOLFRAM_PLATFORM_WINDOWS 1 #elif defined(__APPLE__) #define WOLFRAM_PLATFORM_MACOS 1 #define WOLFRAM_PLATFORM_POSIX 1 diff --git a/src/platform/3ds_platform.c b/src/platform/3ds_platform.c new file mode 100644 index 0000000..1ec69db --- /dev/null +++ b/src/platform/3ds_platform.c @@ -0,0 +1,106 @@ +/** + * 3ds_platform.c — Nintendo 3DS platform implementation (libctru stubs). + * + * Maps platform abstractions to libctru primitives. + * Currently contains stub implementations; TODO comments indicate what + * needs to be filled in when the 3DS integration is built out. + * + * Build with devkitARM: arm-none-eabi-gcc, linked against libctru. + */ + +#include "wolfram/platform.h" + +#include +#include + +/* TODO: #include <3ds.h> — master libctru header */ +/* TODO: #include <3ds/services/soc.h> — for BSD socket API */ +/* TODO: #include <3ds/synchronization.h> — for LightLock */ +/* TODO: #include <3ds/os.h> - for osGetTime */ + +/* ── Init / shutdown ────────────────────────────────────────────────── */ + +wf_status wf_platform_init(void) { + /* + * TODO: Implement when building the 3DS integration: + * 1. gfxInitDefault() — GPU/Graphics + * 2. socInit() — BSD socket API over soc:u service + * 3. httpcInit() — HTTPC service for HTTPS + * 4. Initialise SSL context (via mbedtls or httpc SSL) + */ + return WF_OK; +} + +void wf_platform_shutdown(void) { + /* + * TODO: Implement when building the 3DS integration: + * 1. httpcExit() + * 2. socExit() + * 3. gfxExit() + */ +} + +/* ── Mutex ──────────────────────────────────────────────────────────── */ + +/* + * TODO: Replace with libctru LightLock: + * #include <3ds/synchronization.h> + * + * struct wf_platform_mutex { LightLock lock; }; + * + * wf_platform_mutex *wf_platform_mutex_new(void) { + * wf_platform_mutex *m = calloc(1, sizeof(*m)); + * if (!m) return NULL; + * LightLock_Init(&m->lock); + * return m; + * } + * + * void wf_platform_mutex_lock(wf_platform_mutex *m) { + * if (m) LightLock_Lock(&m->lock); + * } + * + * void wf_platform_mutex_unlock(wf_platform_mutex *m) { + * if (m) LightLock_Unlock(&m->lock); + * } + * + * void wf_platform_mutex_free(wf_platform_mutex *m) { + * if (!m) return; + * LightLock_Destroy(&m->lock); + * free(m); + * } + */ + +struct wf_platform_mutex { int dummy; }; + +wf_platform_mutex *wf_platform_mutex_new(void) { + return calloc(1, sizeof(wf_platform_mutex)); +} + +void wf_platform_mutex_lock(wf_platform_mutex *m) { + (void)m; +} + +void wf_platform_mutex_unlock(wf_platform_mutex *m) { + (void)m; +} + +void wf_platform_mutex_free(wf_platform_mutex *m) { + free(m); +} + +/* ── Time ───────────────────────────────────────────────────────────── */ + +/* + * TODO: Replace with libctru timer: + * #include <3ds/os.h> + * + * uint64_t wf_platform_time_micros(void) { + * // osGetTime() returns milliseconds since 2000-01-01 + * return (uint64_t)osGetTime() * 1000u; + * } + */ + +uint64_t wf_platform_time_micros(void) { + /* Stub: return 0 until libctru timer is wired up. */ + return 0; +} diff --git a/src/platform/wiiu_platform.c b/src/platform/wiiu_platform.c new file mode 100644 index 0000000..29f526d --- /dev/null +++ b/src/platform/wiiu_platform.c @@ -0,0 +1,105 @@ +/** + * wiiu_platform.c — Nintendo Wii U platform implementation (wut stubs). + * + * Maps platform abstractions to wut (Wii U Toolchain) primitives. + * Currently contains stub implementations; TODO comments indicate what + * needs to be filled in when the Wii U integration is built out. + * + * Build with devkitPPC: powerpc-eabi-gcc, linked against wut. + */ + +#include "wolfram/platform.h" + +#include +#include + +/* TODO: #include — for OSJoinThread, OSSemaphore */ +/* TODO: #include — for OSGetTime */ +/* TODO: #include — for socket (BSD-like) */ +/* TODO: #include — for SSL context */ + +/* ── Init / shutdown ────────────────────────────────────────────────── */ + +wf_status wf_platform_init(void) { + /* + * TODO: Implement when building the Wii U integration: + * 1. FSInit() — filesystem + * 2. socketInit() — networking + * 3. Initialise SSL/TLS context + * 4. Initialise AX audio (if needed) + */ + return WF_OK; +} + +void wf_platform_shutdown(void) { + /* + * TODO: Implement when building the Wii U integration: + * 1. socketShutdown() + * 2. FSShutdown() + */ +} + +/* ── Mutex ──────────────────────────────────────────────────────────── */ + +/* + * TODO: Replace with wut OSSemaphore: + * #include + * + * struct wf_platform_mutex { OSSemaphore sem; }; + * + * wf_platform_mutex *wf_platform_mutex_new(void) { + * wf_platform_mutex *m = calloc(1, sizeof(*m)); + * if (!m) return NULL; + * OSSemaphoreInit(&m->sem, 1); + * return m; + * } + * + * void wf_platform_mutex_lock(wf_platform_mutex *m) { + * if (m) OSSemaphoreAcquire(&m->sem, 1); + * } + * + * void wf_platform_mutex_unlock(wf_platform_mutex *m) { + * if (m) OSSemaphoreRelease(&m->sem); + * } + * + * void wf_platform_mutex_free(wf_platform_mutex *m) { + * if (!m) return; + * OSSemaphoreDestroy(&m->sem); + * free(m); + * } + */ + +struct wf_platform_mutex { int dummy; }; + +wf_platform_mutex *wf_platform_mutex_new(void) { + return calloc(1, sizeof(wf_platform_mutex)); +} + +void wf_platform_mutex_lock(wf_platform_mutex *m) { + (void)m; +} + +void wf_platform_mutex_unlock(wf_platform_mutex *m) { + (void)m; +} + +void wf_platform_mutex_free(wf_platform_mutex *m) { + free(m); +} + +/* ── Time ───────────────────────────────────────────────────────────── */ + +/* + * TODO: Replace with wut timer: + * #include + * + * uint64_t wf_platform_time_micros(void) { + * // OSGetTime() returns ticks since boot; OSTicksToMicroseconds() converts + * return OSTicksToMicroseconds(OSGetTime()); + * } + */ + +uint64_t wf_platform_time_micros(void) { + /* Stub: return 0 until wut timer is wired up. */ + return 0; +} diff --git a/src/platform/windows_platform.c b/src/platform/windows_platform.c new file mode 100644 index 0000000..42df8cd --- /dev/null +++ b/src/platform/windows_platform.c @@ -0,0 +1,71 @@ +/** + * windows_platform.c — Windows platform implementation (MinGW / Win32). + * + * Maps platform abstractions to Win32 APIs. Used when building for Windows + * natively (MSVC/MinGW) or cross-compiling from Linux/macOS via MinGW-w64. + */ + +#ifdef _WIN32 + +#include "wolfram/platform.h" + +#include +#include +#include +#include + +/* ── Init / shutdown ────────────────────────────────────────────────── */ + +wf_status wf_platform_init(void) { + WSADATA wsa; + return (WSAStartup(MAKEWORD(2, 2), &wsa) == 0) ? WF_OK : WF_ERR_NETWORK; +} + +void wf_platform_shutdown(void) { + WSACleanup(); +} + +/* ── Mutex ──────────────────────────────────────────────────────────── */ + +struct wf_platform_mutex { + CRITICAL_SECTION cs; +}; + +wf_platform_mutex *wf_platform_mutex_new(void) { + wf_platform_mutex *m = calloc(1, sizeof(*m)); + if (!m) return NULL; + InitializeCriticalSection(&m->cs); + return m; +} + +void wf_platform_mutex_lock(wf_platform_mutex *m) { + if (m) EnterCriticalSection(&m->cs); +} + +void wf_platform_mutex_unlock(wf_platform_mutex *m) { + if (m) LeaveCriticalSection(&m->cs); +} + +void wf_platform_mutex_free(wf_platform_mutex *m) { + if (!m) return; + DeleteCriticalSection(&m->cs); + free(m); +} + +/* ── Time ───────────────────────────────────────────────────────────── */ + +uint64_t wf_platform_time_micros(void) { + /* QueryPerformanceCounter provides sub-microsecond resolution. */ + static LARGE_INTEGER freq = {0}; + static int have_freq = 0; + LARGE_INTEGER now; + + if (!have_freq) { + QueryPerformanceFrequency(&freq); + have_freq = 1; + } + QueryPerformanceCounter(&now); + return (uint64_t)now.QuadPart * 1000000u / (uint64_t)freq.QuadPart; +} + +#endif /* _WIN32 */ -- 2.51.2