Files
dusk/.claude/platform-linux.md
T
2026-06-16 10:15:59 -05:00

163 lines
4.1 KiB
Markdown

# Platform -- Linux and Knulli
`DUSK_TARGET_SYSTEM`: `linux` / `knulli`
Source layer: `src/dusklinux/`
Renderer: OpenGL (Linux) / OpenGL ES via EGL (Knulli)
---
## Overview
Linux is the primary development target. Knulli is a Linux-based handheld
OS (e.g. Anbernic devices); it shares the `src/dusklinux/` layer entirely
and differs only in the CMake target (OpenGL ES instead of desktop OpenGL,
EGL instead of GLX, and no backtrace support).
Both targets use SDL2 for windowing and input. The window is resizable on
both (`DUSK_DISPLAY_SIZE_DYNAMIC`).
---
## Compile-time macros
| Macro | Linux | Knulli |
|-------|-------|--------|
| `DUSK_LINUX` | yes | yes |
| `DUSK_KNULLI` | no | yes |
| `DUSK_SDL2` | yes | yes |
| `DUSK_OPENGL` | yes | yes |
| `DUSK_OPENGL_ES` | no | yes |
| `DUSK_DISPLAY_SIZE_DYNAMIC` | yes | yes |
| `DUSK_INPUT_KEYBOARD` | yes | yes |
| `DUSK_INPUT_POINTER` | yes | yes |
| `DUSK_INPUT_GAMEPAD` | yes | yes |
| `DUSK_TIME_DYNAMIC` | yes | yes |
| `DUSK_NETWORK_IPV6` | yes | no |
| `DUSK_THREAD_PTHREAD` | yes | yes |
| `DUSK_CONSOLE_POSIX` | yes | no |
---
## Display
- Default logical resolution: **640x480** (`DUSK_DISPLAY_WIDTH_DEFAULT` /
`DUSK_DISPLAY_HEIGHT_DEFAULT`); game content renders at
`DUSK_DISPLAY_SCREEN_HEIGHT=240`.
- Dynamic resize: the window can be resized at any time; the engine
letterboxes/scales the logical framebuffer to fit.
- Screen mode is configurable via `SCREEN.mode` (see
`.claude/display-core.md`).
- Knulli uses OpenGL ES (GLES2) linked via EGL. Avoid any desktop
OpenGL extensions that are not in the ES2 core.
---
## Asset loading
`dusk.dsk` is located by searching a list of paths relative to the
current working directory:
```c
static const char_t *ASSET_LINUX_SEARCH_PATHS[] = {
"%s",
"../%s",
"../../%s",
"data/%s",
"../data/%s",
NULL
};
```
The first path where `dusk.dsk` is found wins. No packaging step is
required on Linux -- run from the build directory or the project root.
---
## Input
All three input types are supported:
- **Keyboard** -- SDL scancode array via `SDL_GetKeyboardState()`.
- **Pointer** -- mouse position normalized to [0, 1], scroll axes.
- **Gamepad** -- first available `SDL_GameController`; axes normalized
to [-1, 1] with a 0.2 deadzone.
See `.claude/input.md` for the full action/button API.
---
## Save system
Save files are plain files written to disk.
- Path: `./saves/save_N.dat` (override `SAVE_LINUX_PATH` to change the
directory at CMake configure time).
- Format: `SAVE_LINUX_FILE_FORMAT = "%s/save_%u.dat"` where `%u` is the
slot index.
- No OS-level dialog blocking -- saves are synchronous filesystem calls.
- Endian: host byte order (little-endian on x86/ARM).
---
## Network
- Connection is detected automatically via `getifaddrs()`. No explicit
connect step is needed.
- `networkRequestConnection` immediately calls `onConnected` if any
non-loopback interface is up, `onFailed` otherwise.
- IPv4 and IPv6 supported (`DUSK_NETWORK_IPV6`).
---
## Time
- Tick source: `SDL_GetTicks64()`.
- Real time: `clock_gettime(CLOCK_REALTIME)`.
- Dynamic timestep enabled (`DUSK_TIME_DYNAMIC`).
---
## Threading
pthreads (`DUSK_THREAD_PTHREAD`). Thread-local storage via `__thread`.
---
## Build and toolchain
No cross-compiler needed -- use the host GCC/Clang.
```sh
# Debug build
cmake -B build -DDUSK_TARGET_SYSTEM=linux -DCMAKE_BUILD_TYPE=Debug
cmake --build build
# Knulli (cross-compile to aarch64)
cmake -B build \
-DDUSK_TARGET_SYSTEM=knulli \
-DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/aarch64-linux-gnu.cmake \
-DCMAKE_BUILD_TYPE=Release
cmake --build build
```
Dependencies: `SDL2`, `OpenGL` (Linux) or `GLES2` + `EGL` (Knulli),
`pthread`, `m`.
---
## Endianness
Little-endian. Detected at CMake configure time via `TestBigEndian` and
set as `DUSK_PLATFORM_ENDIAN_LITTLE` or `DUSK_PLATFORM_ENDIAN_BIG`.
---
## Gotchas
- `DUSK_CONSOLE_POSIX` enables POSIX-specific assert backtracing (Linux
only; Knulli does not set it).
- Knulli does not set `DUSK_NETWORK_IPV6` -- IPv6 may not be available
on handheld devices.
- `DUSK_TIME_DYNAMIC` is set, so physics/networking skip dynamic sub-steps
by checking `if(TIME.dynamicUpdate) return;`.