https://github.com/millertechnologyperu/swift-embedded-nintendo-64
Embedded Swift for Nintendo 64
https://github.com/millertechnologyperu/swift-embedded-nintendo-64
Last synced: 19 days ago
JSON representation
Embedded Swift for Nintendo 64
- Host: GitHub
- URL: https://github.com/millertechnologyperu/swift-embedded-nintendo-64
- Owner: MillerTechnologyPeru
- Created: 2026-06-27T01:06:23.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-06-27T04:14:57.000Z (about 1 month ago)
- Last Synced: 2026-06-27T06:14:00.331Z (about 1 month ago)
- Language: C
- Size: 6.84 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# swift-embedded-nintendo-64
Embedded Swift running on the Nintendo 64, targeting the VR4300 CPU (MIPS III).
Each example builds a working N64 ROM. The Swift code is compiled on the host
with a MIPS-enabled `swiftc`, lowered to a MIPS ELF object via `llc`, then
linked against C code compiled by the appropriate N64 GCC toolchain.
## Examples
### [nusys/](nusys/) — Calling Swift from C (NuSYS SDK)
3D rotating cube using the proprietary NuSYS / crashsdk toolchain. The graphics
pipeline (`gfx.swift`), scene stages (`stage0.swift`, `stage1.swift`), and
entry point (`lib.swift`) are all Swift. C handles static data and matrix math
that must call N64 SDK float functions.
Uses `@c @implementation` (Swift 6.3) to implement functions declared in C headers.

### [libdragon/](libdragon/) — Swift + libdragon
Animated color grid using the open-source [libdragon](https://github.com/DragonMinded/libdragon)
SDK and its `n64.mk` build system — a completely different toolchain from the
NuSYS example. Swift drives libdragon's `rdpq` fill API; C owns libdragon init
and the frame loop.

## Cross-toolchain gotchas
Two hard constraints apply to all examples:
**1. No floats across the Swift↔C boundary.**
LLVM (swiftc) and N64 GCC disagree on the o32 float-argument ABI: LLVM passes
trailing floats after a pointer in FP registers (`$f13`/`$f14`); GCC expects
them in GPRs (`$a1`/`$a2`). Pass IEEE-754 bit patterns as `UInt32`/`u32` instead
and reinterpret with a union on the C side.
**2. ≤4 register arguments per Swift↔C bridge call (libdragon only).**
libdragon uses `-mabi=o64` (8-byte stack slots); the Swift object is o32
(4-byte stack slots). Arguments beyond the first four spill to the stack and
are read at the wrong offset. Pack multiple values into a single `uint32_t`
to stay within four registers.
### Conditional moves (movn/movz) — fixed by llc flags
By default, LLVM lowers Swift `if`/ternary/`min`/`max` on integers to `select`
IR, which the MIPS backend emits as `movn`/`movz` — MIPS IV instructions the
VR4300 does not have. Executing them raises a Reserved Instruction exception.
The fix is two llc `-mattr` flags that disable the MIPS IV conditional-move
subset inherited by MIPS32:
```
-mattr=+mips3,+noabicalls,+gp64,+fpxx,+nooddspreg,-mips4_32,-mips4_32r2
```
Both `compile-swift.sh` scripts already include these flags. With them, Swift
conditionals compile to branches and there are no restrictions on using
`if`/`else`, ternaries, `min`, `max`, or `abs` in Swift code.
## Building
Each example has its own `build.sh`. Requirements:
- A MIPS-enabled Embedded Swift toolchain (`swiftc` + `llc`) — the standard
release toolchains do not include MIPS; you need a custom build or one that
ships MIPS embedded Swift modules.
- Docker — for the N64 GCC toolchain and SDK (pulled automatically on first run).
```bash
cd nusys && ./build.sh # → build/calling-swift-from-c.z64
cd libdragon && ./build.sh # → libdragon-swift.z64
```