{"id":51544918,"url":"https://github.com/millertechnologyperu/swift-embedded-ps1","last_synced_at":"2026-07-09T17:01:39.206Z","repository":{"id":367682911,"uuid":"1281874120","full_name":"MillerTechnologyPeru/swift-embedded-ps1","owner":"MillerTechnologyPeru","description":"Embedded Swift for PS1","archived":false,"fork":false,"pushed_at":"2026-07-06T18:18:32.000Z","size":167,"stargazers_count":9,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-06T20:07:54.991Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MillerTechnologyPeru.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":"Support/boot.S","governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-27T03:06:27.000Z","updated_at":"2026-07-06T18:19:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/MillerTechnologyPeru/swift-embedded-ps1","commit_stats":null,"previous_names":["millertechnologyperu/swift-embedded-ps1"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MillerTechnologyPeru/swift-embedded-ps1","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MillerTechnologyPeru%2Fswift-embedded-ps1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MillerTechnologyPeru%2Fswift-embedded-ps1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MillerTechnologyPeru%2Fswift-embedded-ps1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MillerTechnologyPeru%2Fswift-embedded-ps1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MillerTechnologyPeru","download_url":"https://codeload.github.com/MillerTechnologyPeru/swift-embedded-ps1/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MillerTechnologyPeru%2Fswift-embedded-ps1/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35306717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-09T17:01:38.124Z","updated_at":"2026-07-09T17:01:39.170Z","avatar_url":"https://github.com/MillerTechnologyPeru.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# swift-embedded-ps1\n\nEmbedded Swift running on the PlayStation 1, using **PSn00bSDK** as the C hardware layer.\n\nWorking examples, all targeting `mipsel-none-none-elf` (MIPS-I R3000A):\n\n| Example | Output | Description |\n|---------|--------|-------------|\n| `hello` | `hello.psexe` | Debug font \"Hello from Swift on PS1!\" on a 320×240 display |\n| `balls` | `balls.psexe` | 1024 bouncing textured sprites + sine-wave snake — port of PSn00bSDK `examples/graphics/balls` |\n| `rgb24` | `rgb24.psexe` | 24-bit RGB image display — port of PSn00bSDK `examples/graphics/rgb24` |\n| `tiles` | `tiles.psexe` | Scrollable tile-map renderer — port of PSn00bSDK `examples/graphics/tilesasm` |\n| `arraytests` / `arraytests-llc` | `arraytests.psexe` / `arraytests-llc.psexe` | On-screen `Array`/`Dictionary` regression tests — **currently fail**, see [KNOWN_ISSUES.md](KNOWN_ISSUES.md) |\n---\n\n## Screenshots\n\n**hello** — 320×240, double-buffered, `FntSort` + ordering table\n\u003cimg width=\"828\" height=\"689\" alt=\"Screenshot 2026-06-27 at 10 55 16 AM\" src=\"https://github.com/user-attachments/assets/adf5ce1a-370c-4f3e-986f-30dfe77e4df2\" /\u003e \n\n**balls** — 640×480 interlaced, 1024 `SPRT_16` sprites + GTE sin/cos snake  \n\u003cimg width=\"830\" height=\"693\" alt=\"Screenshot 2026-06-27 at 10 54 33 AM\" src=\"https://github.com/user-attachments/assets/459fe645-9e98-4fbd-8681-2ccf4d77166d\" /\u003e\n\n**rgb24** — 640×480 interlaced 24-bit RGB texture uploaded to VRAM\n\u003cimg width=\"828\" height=\"689\" alt=\"Screenshot 2026-06-27 at 10 55 34 AM\" src=\"https://github.com/user-attachments/assets/cd44e39b-13f0-4a98-b7d9-85c3ae1a29bd\" /\u003e\n\n---\n\n## Project layout\n\n```\nswift-embedded-ps1/\n├── Makefile                         # Builds all examples; make / make hello / make balls\n├── Sources/\n│   ├── PSn00bSDK/include/           # Bridging header + module.modulemap\n│   ├── HelloPS1/\n│   │   ├── Main.swift               # Text rendering in Swift\n│   │   └── shim.c                   # POSIX stubs + FntSort render context\n│   ├── Balls/\n│   │   ├── Main.swift               # 1024 balls + snake in Swift\n│   │   ├── shim.c                   # POSIX stubs + SPRT_16/DR_TPAGE macro wrappers\n│   │   ├── BridgingHeader.h         # Imports the PSn00bSDK sub-headers\n│   │   ├── BallTypes.h              # BALL struct definition\n│   │   ├── ball16c.S                # .incbin embeds ball16c.tim into .rodata\n│   │   └── ball16c.tim              # 4-bit CLUT texture (16×16 px, 192 bytes)\n│   └── RGB24/\n│       ├── Main.swift               # 24-bit RGB display in Swift\n│       ├── shim.c                   # POSIX stubs + TIM data pointer\n│       ├── tim.S                    # .incbin embeds bunpattern.tim into .rodata\n│       └── bunpattern.tim           # 24-bit RGB texture (256×256 px)\n│   └── Tiles/\n│       ├── Main.swift               # Entry point; drives the C tiles_main()\n│       ├── shim.c                   # main.c verbatim (POSIX stubs + heap init)\n│       ├── drawtiles.s              # GAS DrawTiles routine (verbatim)\n│       ├── tim.S                    # .incbin embeds tiles_256.tim as tim_tileset\n│       └── tiles_256.tim            # 4-bit CLUT tileset (256×256 px)\n└── Support/\n    ├── boot.S                       # MIPS _start: init $gp, zero BSS, jalr swift_main\n    ├── psexe.ld                     # Linker script (load at 0x80010000)\n    └── elf2psexe.py                 # Adds the 2 KB PS-X EXE header\n```\n\n---\n\n## Build\n\n```bash\n# First-time: extract PSn00bSDK headers + libs from Docker\nmake setup-sdk\n\n# Build all examples\nmake\n\n# Or build individually\nmake hello\nmake balls\nmake rgb24\nmake tiles\nmake arraytests       # Array/Dictionary regression tests -- see KNOWN_ISSUES.md\nmake arraytests-llc   # same tests, alternate compile pipeline (-emit-ir + llc)\n```\n\nEach example builds independently into `build/\u003cname\u003e/` and produces its own `.psexe`.\n\nBuild steps per example:\n\n```\nswiftc (WMO)     →  build/\u003cname\u003e/main.swift.o   (Embedded Swift → mipsel-none-none-elf)\nclang            →  build/\u003cname\u003e/boot.o          (MIPS _start stub)\nclang            →  build/\u003cname\u003e/shim.o          (C macro wrappers + POSIX stubs)\nld.lld           →  build/\u003cname\u003e/out.elf         (linked with PSn00bSDK .a libs)\nllvm-objcopy     →  build/\u003cname\u003e/out.bin         (raw binary)\nelf2psexe.py     →  \u003cname\u003e.psexe                 (PS-X EXE with 2 KB header)\n```\n\n---\n\n## Prerequisites\n\n| Tool | Purpose |\n|------|---------|\n| `swiftc` (patched) | Embedded Swift targeting `mipsel-none-none-elf` |\n| `clang` / `ld.lld` / `llvm-objcopy` | Compile boot stub + link |\n| `libswiftEmbeddedPlatformPOSIX.a` | Swift runtime for POSIX-like embedded targets |\n| Docker (first run) | Extracts PSn00bSDK headers + `.a` libs via `make setup-sdk` |\n| Python 3 | `elf2psexe.py` PS-X EXE header wrapper |\n| Emulator | DuckStation / PCSX-Redux / no$psx |\n\nThe toolchain paths are configured at the top of the `Makefile` (`TOOLCHAIN`, `SWIFTC`, `CLANG`, `LLD`).\n\n---\n\n## Run\n\nLoad any `.psexe` in a PS1 emulator:\n\n- **DuckStation** — File → Load EXE\n- **PCSX-Redux** — File → Load Archive\n- **no$psx** — drag and drop\n\n---\n\n## Architecture\n\n### Why a shim.c per example?\n\nPSn00bSDK's GPU drawing API is almost entirely **C macros** (`setTile`, `setSprt16`, `setXY0`, `setRGB0`, `addPrim`, `getTPage`, `setDrawTPage`, …). Macros can't be imported into Swift, so each example's `shim.c` provides thin C wrappers that Swift calls via `@_silgen_name`.\n\nEverything else — game state, rendering logic, the main loop — lives in Swift.\n\n### boot.S — two critical requirements\n\n1. **`$gp` must be initialized before any C/Swift call.** PSn00bSDK and `libswiftEmbeddedPlatformPOSIX` are compiled with O32 abicalls (GOT-relative data access). `_gp` is the linker-computed GOT anchor; without it every global variable access faults.\n\n2. **`swift_main` must be called via `la $t9 / jalr $t9`.** O32 abicalls prologues compute `$gp` from `$t9 + _gp_disp`. Using plain `jal` leaves `$t9` stale and breaks any abicalls function called transitively from Swift.\n\n### Linker script — small data layout\n\nPSn00bSDK accesses many of its internal statics via `R_MIPS_GPREL16` (GP-relative), which has a ±32 KB range from `_gp`. The linker script places `.got → .sdata → .sbss` together so all GP-relative references stay in range, and puts the large primitive buffers (up to 128 KB) in `.bss` afterward where GP-relative addressing isn't used.\n\n### Embedded Swift flags\n\n```\n-target mipsel-none-none-elf\n-enable-experimental-feature Embedded\n-wmo  -Osize\n-Xcc -march=mips1 -Xcc -mabi=o32 -Xcc -mno-abicalls -Xcc -fno-pic\n-Xcc -msoft-float  -Xcc -G0\n-Xllvm -mattr=+noabicalls  -Xllvm -relocation-model=static\n```\n\n`-mno-abicalls` / `-relocation-model=static` prevent the Swift LLVM backend from emitting GOT-indirect calls. PSn00bSDK libs are abicalls but our Swift code is static — they coexist because `boot.S` sets `$gp` before any call.\n\n### LLVM/lld patches\n\nThe build requires a patched Swift/LLVM toolchain. Patches applied:\n\n| File | Change |\n|------|--------|\n| `clang/lib/Basic/CodeGenOptions.cpp` | Don't reset relocation model to PIC during PCH emission |\n| `llvm/lib/Target/Mips/MipsSubtarget.cpp` | Don't fatal-error on PIC+no-abicalls during PCH (no real code emitted) |\n| `llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp` | Drop `MipsISD::Sync` on MIPS-I (R3000A has no SYNC instruction) |\n| `llvm/lib/MC/MCSymbolELF.cpp` | Return `STB_LOCAL` for temporary symbols even when used in a reloc (MIPS O32 JALR-hint `$tmp` labels) |\n| `lld/ELF/InputFiles.cpp` | Warn instead of error for LOCAL symbol after GLOBAL (old mipsel-gcc PSn00bSDK artefact) |\n| `lld/ELF/Arch/MipsArchTree.cpp` | Warn instead of error for n64/o32 ABI mismatch and soft/double-float mismatch (old PSn00bSDK artefact) |\n\n---\n\n## Known issues\n\n`Array`/`Dictionary` are broadly unreliable on this target beyond the narrowest patterns (a\nsingle allocation, populate, read) — growing past capacity, and even\n`removeAll(keepingCapacity:)` on an empty array, can hang with no crash or log. See\n[KNOWN_ISSUES.md](KNOWN_ISSUES.md) for the full writeup, a minimal reproduction\n(`make arraytests` / `make arraytests-llc`), and what's been ruled out so far. This blocks\nporting any non-trivial `Array`-heavy Swift codebase to this target until it's fixed upstream.\n\n## See also\n\n- [swift-embedded-nds](https://github.com/MillerTechnologyPeru/swift-embedded-nds) — NDS sibling project this was modeled on\n- [PSn00bSDK](https://github.com/Lameguy64/PSn00bSDK) — PS1 homebrew C SDK\n- [psx-spx](https://psx-spx.consoledev.net/) — PS1 hardware reference\n- [DuckStation](https://github.com/stenzek/duckstation) — recommended emulator\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmillertechnologyperu%2Fswift-embedded-ps1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmillertechnologyperu%2Fswift-embedded-ps1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmillertechnologyperu%2Fswift-embedded-ps1/lists"}