Add claude docs
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
# Platform -- Dolphin (GameCube and Wii)
|
||||
|
||||
`DUSK_TARGET_SYSTEM`: `gamecube` / `wii`
|
||||
Source layer: `src/duskdolphin/`
|
||||
Renderer: libogc GX (native Nintendo hardware)
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
GameCube and Wii are collectively called the **Dolphin** targets. They
|
||||
share a single source layer (`src/duskdolphin/`) and a shared CMake base
|
||||
(`cmake/targets/dolphin.cmake`). Individual targets add `DUSK_GAMECUBE`
|
||||
or `DUSK_WII` on top.
|
||||
|
||||
Both are **big-endian** PowerPC platforms. They do **not** use SDL2 or
|
||||
OpenGL -- rendering and input go through `libogc` (the open-source
|
||||
GameCube/Wii SDK) and the GX hardware API directly.
|
||||
|
||||
---
|
||||
|
||||
## Hardware
|
||||
|
||||
| Attribute | GameCube | Wii |
|
||||
|-----------|---------|-----|
|
||||
| CPU | IBM PowerPC 750CL (Gekko), 485 MHz | IBM Broadway (Wii CPU), 729 MHz |
|
||||
| RAM | 24 MB (16 MB MEM1 + 8 MB ARAM) | 88 MB (24 MB MEM1 + 64 MB MEM2) |
|
||||
| GPU | ATI Flipper (GX) | ATI Hollywood (GX) |
|
||||
| Display | 640x480 (480p max) | 640x480 (480p/576i), 480p/1080i via component |
|
||||
| Storage | Memory Card (slots A/B), SD Gecko | SD card, USB, NAND |
|
||||
| Endian | Big-endian | Big-endian |
|
||||
|
||||
Treat the **GameCube 16 MB MEM1** as the worst-case RAM budget for data
|
||||
structures shared between both targets.
|
||||
|
||||
---
|
||||
|
||||
## Compile-time macros
|
||||
|
||||
| Macro | GameCube | Wii | Notes |
|
||||
|-------|---------|-----|-------|
|
||||
| `DUSK_DOLPHIN` | yes | yes | Set by `dolphin.cmake` |
|
||||
| `DUSK_GAMECUBE` | yes | no | |
|
||||
| `DUSK_WII` | no | yes | |
|
||||
| `DUSK_INPUT_GAMEPAD` | yes | yes | |
|
||||
| `DUSK_DISPLAY_WIDTH` | 640 | 640 | |
|
||||
| `DUSK_DISPLAY_HEIGHT` | 480 | 480 | |
|
||||
| `DUSK_THREAD_PTHREAD` | yes | yes | devkitPPC pthreads |
|
||||
| `DUSK_PLATFORM_ENDIAN_BIG` | yes | yes | Not set by cmake -- apply manually |
|
||||
| `DOL` | 1 | 1 | Build type token |
|
||||
| `ISO` | 2 | 2 | Build type token |
|
||||
| `DUSK_DOLPHIN_BUILD_TYPE` | `DOL` or `ISO` | `DOL` or `ISO` | |
|
||||
| `DUSK_DOLPHIN_BUILD_ISO` | if ISO mode | if ISO mode | |
|
||||
|
||||
No `DUSK_SDL2`, no `DUSK_OPENGL`, no `DUSK_INPUT_KEYBOARD`,
|
||||
no `DUSK_INPUT_POINTER`, no `DUSK_TIME_DYNAMIC`.
|
||||
|
||||
Attempting to use `DUSK_INPUT_KEYBOARD` or `DUSK_INPUT_POINTER` causes
|
||||
a compile-time `#error` in `inputdolphin.h`.
|
||||
|
||||
---
|
||||
|
||||
## Endianness
|
||||
|
||||
**Both GameCube and Wii are big-endian.** This is the most critical
|
||||
platform difference from all other targets.
|
||||
|
||||
- All binary asset data (`.dtf` tilesets, STL meshes, DTF headers, etc.)
|
||||
must be byte-swapped when read on Dolphin.
|
||||
- Use `endianLittleToHost32` / `endianLittleToHost16` etc. from
|
||||
`util/endian.h` when reading any multi-byte value from a file.
|
||||
- Save files are stored in little-endian order; the save stream handles
|
||||
this transparently via the `saveFile*` macros.
|
||||
- Network data likewise needs endian conversion.
|
||||
|
||||
See `.claude/util.md` (Endian section) for the full API.
|
||||
|
||||
---
|
||||
|
||||
## Display
|
||||
|
||||
- Fixed 640x480 resolution, driven by GX (the hardware rasteriser).
|
||||
- Uses double-buffered framebuffers:
|
||||
```c
|
||||
typedef struct {
|
||||
void *frameBuffer[2]; // double-buffered
|
||||
int_t whichFrameBuffer;
|
||||
GXRModeObj *screenMode;
|
||||
void *fifoBuffer; // GX command FIFO, 256 KB
|
||||
} displaydolphin_t;
|
||||
```
|
||||
- The GX pipeline uses display lists for efficient draw call batching --
|
||||
avoid immediate-mode GX calls in the hot path.
|
||||
- `CONF_GetAspectRatio()` returns `CONF_ASPECT_4_3` on GameCube (always)
|
||||
and the user's setting on Wii. Use `systemGetAspectRatioDolphin()`.
|
||||
|
||||
---
|
||||
|
||||
## Asset loading
|
||||
|
||||
Two modes are selected at CMake configure time via
|
||||
`DUSK_DOLPHIN_BUILD_TYPE`:
|
||||
|
||||
### DOL mode (default -- `DUSK_DOLPHIN_BUILD_TYPE=DOL`)
|
||||
|
||||
Assets are loaded from `dusk.dsk` on a FAT filesystem -- SD card on Wii
|
||||
(via SD slot), or SD Gecko / SD adapter on GameCube. The loader searches
|
||||
these paths in order:
|
||||
|
||||
```c
|
||||
"/", "/Dusk", "/dusk", "/DUSK",
|
||||
"/apps", "/apps/Dusk", "/apps/dusk", "/apps/DUSK",
|
||||
".", "./Dusk", "./dusk", ...
|
||||
```
|
||||
|
||||
Uses `libfat` for filesystem access.
|
||||
|
||||
### ISO mode (`DUSK_DOLPHIN_BUILD_TYPE=ISO`)
|
||||
|
||||
`dusk.dsk` is read directly off the DVD disc via the libogc DVD driver
|
||||
(`assetdolphindvd.c`). Reads are 32-byte aligned:
|
||||
|
||||
```c
|
||||
#define ASSET_DOLPHIN_DVD_ALIGN 32u
|
||||
```
|
||||
|
||||
The DVD FST (file-system table) is parsed at init to locate the data
|
||||
file. All reads go through `assetDolphinDVDRead(offset, size)` which
|
||||
returns an aligned heap buffer that the caller must free.
|
||||
|
||||
Post-build in ISO mode, `makedolphiniso.py` produces **three disc
|
||||
images** (NTSC-J, NTSC-U, PAL).
|
||||
|
||||
---
|
||||
|
||||
## Input
|
||||
|
||||
Uses libogc `PAD` API. Only GameCube controllers are supported (port 0
|
||||
by default; up to 4 via `PAD_CHANMAX`).
|
||||
|
||||
Available axes (6 total per controller):
|
||||
|
||||
| Axis | Enum |
|
||||
|------|------|
|
||||
| Left stick X/Y | `INPUT_GAMEPAD_AXIS_LEFT_X/Y` |
|
||||
| C-stick X/Y | `INPUT_GAMEPAD_AXIS_C_X/Y` |
|
||||
| L trigger | `INPUT_GAMEPAD_AXIS_TRIGGER_LEFT` |
|
||||
| R trigger | `INPUT_GAMEPAD_AXIS_TRIGGER_RIGHT` |
|
||||
|
||||
Axis values are normalised by dividing the raw 8-bit value by 128.0.
|
||||
Deadzone: 0.2 (hardcoded).
|
||||
|
||||
Default bindings set at init: D-pad/left stick = directional actions,
|
||||
A = ACCEPT, B = CANCEL, X = CONSOLE, Start = RAGEQUIT.
|
||||
|
||||
Wii Remote / Nunchuk / Classic Controller / Pro Controller are not yet
|
||||
implemented (noted as TODO in `inputdolphin.h`).
|
||||
|
||||
---
|
||||
|
||||
## Save system
|
||||
|
||||
Uses the libogc Memory Card API (`CARD_*`) to read/write save slots.
|
||||
|
||||
```c
|
||||
typedef struct {
|
||||
card_file cardFile;
|
||||
uint8_t cardBuffer[CARD_WORKAREA] __attribute__((aligned(32)));
|
||||
bool_t mounted;
|
||||
} savedolphin_t;
|
||||
```
|
||||
|
||||
- Default channel: `CARD_SLOTA` (Memory Card slot A).
|
||||
Override via `SAVE_DOLPHIN_CHANNEL`.
|
||||
- Sector size: 8192 bytes (`SAVE_DOLPHIN_SECTOR_SIZE`).
|
||||
- Buffers must be 32-byte aligned (enforced by `__attribute__((aligned(32)))`).
|
||||
- Game code: `DUSK` (4 chars, override via `SAVE_DOLPHIN_GAME_CODE`).
|
||||
- The card must be mounted before any read/write. `saveInitDolphin()`
|
||||
mounts slot A; failures are treated as "no save present".
|
||||
- Save stream handles little-endian encoding transparently -- all data
|
||||
stored little-endian on the card even though the CPU is big-endian.
|
||||
|
||||
---
|
||||
|
||||
## Network
|
||||
|
||||
### GameCube
|
||||
|
||||
`net_init()` is commented out. Networking is **non-functional** on
|
||||
GameCube in the current codebase. The BBA (Broadband Adapter) link
|
||||
library is in a commented `# bba` in `gamecube.cmake`.
|
||||
|
||||
### Wii
|
||||
|
||||
Uses `if_config()` from libogc which reads Wi-Fi settings saved in the
|
||||
Wii System Menu. The call **blocks** the main thread until DHCP
|
||||
completes or fails. Wii network is available only when `DUSK_WII` is
|
||||
defined; the GameCube path always fails immediately.
|
||||
|
||||
IPv6 is not supported on either Dolphin target.
|
||||
|
||||
---
|
||||
|
||||
## Time
|
||||
|
||||
- No `DUSK_TIME_DYNAMIC`. All ticks are fixed 16 ms steps.
|
||||
- Tick source: `__SYS_GetSystemTime()` returns PowerPC bus ticks.
|
||||
- Real time: ticks converted to microseconds via `ticks_to_microsecs()`,
|
||||
then offset from the GameCube epoch (2000-01-01 00:00:00) to the UNIX
|
||||
epoch (1970-01-01 00:00:00) by adding **946 684 800 seconds**.
|
||||
- Timezone: always returned as 0 -- no timezone data without network time.
|
||||
|
||||
---
|
||||
|
||||
## System
|
||||
|
||||
Language and aspect ratio queries:
|
||||
|
||||
```c
|
||||
// Language (used for locale selection):
|
||||
systemGetLanguageDolphin();
|
||||
// -> SYS_GetLanguage() on GameCube
|
||||
// -> CONF_GetLanguage() on Wii
|
||||
|
||||
// Aspect ratio:
|
||||
systemGetAspectRatioDolphin();
|
||||
// -> CONF_ASPECT_4_3 always on GameCube
|
||||
// -> CONF_GetAspectRatio() on Wii (4:3 or 16:9)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Build and toolchain
|
||||
|
||||
Requires [devkitPro](https://devkitpro.org/) with `devkitPPC` and
|
||||
`libogc` installed.
|
||||
|
||||
```sh
|
||||
# GameCube (SD card / DOL mode)
|
||||
cmake -B build \
|
||||
-DDUSK_TARGET_SYSTEM=gamecube \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/GameCube.cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
|
||||
# Wii (SD card / DOL mode)
|
||||
cmake -B build \
|
||||
-DDUSK_TARGET_SYSTEM=wii \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Wii.cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
|
||||
# Either target in ISO mode
|
||||
cmake -B build \
|
||||
-DDUSK_TARGET_SYSTEM=gamecube \
|
||||
-DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/GameCube.cmake \
|
||||
-DDUSK_DOLPHIN_BUILD_TYPE=ISO \
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build
|
||||
```
|
||||
|
||||
Post-build outputs (DOL mode): `Dusk.elf` + `Dusk.dol` (generated by
|
||||
`elf2dol`). Copy `Dusk.dol` and `dusk.dsk` to the SD card.
|
||||
|
||||
Post-build outputs (ISO mode): `Dusk.dol` + disc images in
|
||||
`NTSC-J/`, `NTSC-U/`, `PAL/` subdirectories.
|
||||
|
||||
Dependencies: libogc, devkitPPC, `fat` (DOL mode), cglm, zip, bz2,
|
||||
zstd, z, lzma, m.
|
||||
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Big-endian is the most common source of bugs** when porting code
|
||||
from Linux. Always use `endian.h` utilities for file I/O and network.
|
||||
- Memory is tight on GameCube -- 16 MB MEM1 must hold code, stack, heap,
|
||||
framebuffers (2x 640x480x2 bytes), and the GX FIFO (256 KB).
|
||||
- GX display lists are the correct rendering path; immediate-mode GX
|
||||
calls carry heavy CPU overhead on the short FIFO pipeline.
|
||||
- The GameCube has no FPU for integer paths. Avoid `double`; use
|
||||
`float_t` throughout.
|
||||
- `consoleInit` is shadowed to `consoleInitDolphin` to avoid conflicts
|
||||
with the devkitPPC console API.
|
||||
- On GameCube `CONF_GetAspectRatio()` is always 4:3; the macro is
|
||||
defined to return `CONF_ASPECT_4_3` unconditionally.
|
||||
- DVD reads must be 32-byte aligned and padded -- use
|
||||
`ASSET_DOLPHIN_DVD_ALIGN_UP(n)` when computing read sizes in ISO mode.
|
||||
Reference in New Issue
Block a user