From ff415e837424e3715b9c4402a64cb4bb52a50f8d Mon Sep 17 00:00:00 2001 From: Gabriel Scarcella Date: Sat, 24 Oct 2026 20:18:08 -0300 Subject: [PATCH 1/2] README: features first, then using it from a game and developing; a contributing guide and code owners The README opens with what the stack bundles (Features, by area, each pointing at its doc), a table of contents, how a game uses it, and a Developing section (setup, tests, layout, docs, contributing); the history moves to the end and the status is v0.3.16. CONTRIBUTING.md gives the ground rules, the gates and the pull request steps; .github/CODEOWNERS names the owner as reviewer. Co-Authored-By: Claude Opus 5.5 --- .github/CODEOWNERS | 2 + CONTRIBUTING.md | 85 +++++++++++++++++ README.md | 232 +++++++++++++++++++++++++++++++++++++++------ 3 files changed, 289 insertions(+), 30 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 CONTRIBUTING.md diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..86c6752 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,2 @@ +# Who reviews what (https://docs.github.com/articles/about-code-owners). The owner reviews and merges every pull request. +* @gascarcella diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b13a775 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,85 @@ +# Contributing to psxstack + +psxstack is a reusable stack for PC ports of decompiled PlayStation games. A change here reaches every game that +builds on it, so the rules below keep the stack generic, legal and reviewable. Read `README.md` first, then +`docs/GAME_CONTRACT.md`: what a game provides and what the stack provides. + +## Ground rules + +### No game code, no game data, no Psy-Q SDK +Nothing from a game's `src/`, its disc or its extracted files comes here. The Psy-Q declarations the shim compiles +against are the stack's own (`include/psxstack/psyq/`), written from the games' use of the API under Sony's names, +with no SDK file (docs/DECISIONS.md "Psy-Q declarations: the stack's"). The shim never decompiles Sony's code; it +reimplements the libraries' behavior over the hardware models. Anything borrowed is recorded in +`docs/THIRD_PARTY.md`. + +### No fact about a game in the stack +No address, file ID, overlay name, disc hash, serial, title or directory name. They come from the game's `game.json` +(generated into `psxstack_game_gen.h` at configure time by `tools/game_gen.py`) or from the game's adapter behind +`include/psxstack/game.h`. + +### The contract first +A change to what a game must supply, or to a hook macro's meaning, is a change to `docs/GAME_CONTRACT.md` first. An +incompatible one bumps `PSXSTACK_API` (`include/psxstack/game.h`). The hook macro names (`PLATFORM_WAIT`, +`OVERLAY_COPY`, `SLOT_FUNC`, …) are stable API: games have hundreds of sites. + +### Reproducible +Setup steps go in `scripts/` or `docs/`, never only in shell history. A new pinned tool is a `scripts/setup.sh` step +into `tools/`, a `.gitignore` line (without a trailing slash) and a line in `docs/THIRD_PARTY.md`. Nothing +installs system-wide or needs sudo. + +## Getting set up +```sh +git clone https://github.com/gascarcella/psxstack && cd psxstack +scripts/setup.sh # SDL3 and Dear ImGui into tools/, no sudo +python3 tests/hello_test.py # the smoke test +``` +`README.md` "Setup" lists the other tools (DXC for the hardware renderer, llvm-mingw for Windows) and "Tests" every +test the stack runs on its own. + +## Making a change + +### Branch and pull request +1. Open or pick an [issue](https://github.com/gascarcella/psxstack/issues): problems and plans live there. +2. Branch from `main`; a large change goes in phases, each one reviewable on its own. +3. Open a pull request to `main`. Its description says what was done and lists the gates that ran. +4. CI must be green (`.github/workflows/ci.yml`; a change to Markdown or `LICENSE` alone runs nothing). A code owner + (`.github/CODEOWNERS`) reviews and merges. + +### Gates +- **Always:** the tests in `README.md` "Tests" that touch what changed; `python3 -m py_compile tools/*.py + tools/mcp/*.py tools/replay/*.py tests/*.py` for Python. +- **`runtime/`, `psyq/`, `cmake/` or the contract:** also a real game. `examples/hello` exercises little; the gate + is the first game: in a [dw2003recomp](https://github.com/gascarcella/dw2003recomp) checkout, + `cmake -S port -B build/port -G Ninja -DPSXSTACK_DIR=/path/to/psxstack` and its `scripts/test.sh` (it needs the + game's disc; its README says how). A contributor without one says so in the pull request, and the owner runs it. +- **The launcher:** its self-test (`launcher/README.md`). +- **Windows:** the cross-build and the tests under Wine when the change touches platform code + (`runtime/platform.c`, `cmake/windows-x86_64.cmake`, `windows/`). + +Don't claim something works until it has run; when unsure, say so in the pull request. + +### Docs +- Update the docs that describe how things are (`docs/`, `README.md`) when the state changes. +- Record a decision in `docs/DECISIONS.md` only when it changes how the stack works: a few lines, what and why. +- Docs cite each other as `docs/X.md "Heading"`, so keep headings stable. They are lean: how things are and why, no + logs. Leftover work becomes an issue, not a doc. + +### Code style +Write code that reads like the code around it. The naming: +- the runtime's API the game's C calls is `port_*` (`include/psxstack/hooks.h`); +- the adapter functions a game implements are `game_*` (`include/psxstack/game.h`); +- CMake is `psxstack_*` functions and `PSXSTACK_*` options; +- the generated description macros are `PSXSTACK_GAME_*` and `PORT_SLOT_*`; +- environment variables derive from the game's `env_prefix` (`_PORT_*`, `_CONFIG_DIR`); +- Psy-Q names stay Sony's. + +### Commits +Commit messages say what and why in plain words. One topic per commit. + +## Releases +Releases are semver tags (`vMAJOR.MINOR.PATCH`), cut by the owner. A game pins a tag, so a change here reaches it as +a reviewable pin bump (docs/GAME_CONTRACT.md "Compatibility and versions"). + +## License +By contributing you agree that your contribution is licensed under the MIT license (`LICENSE`). diff --git a/README.md b/README.md index 017c3dd..ebca364 100644 --- a/README.md +++ b/README.md @@ -5,26 +5,164 @@ interrupt pump, software and hardware rendering, SPU, input, memory cards, setti save states), a Psy-Q shim, a launcher (SDL3, Dear ImGui) with mod manifests, and the build and packaging scripts. A game repo (a matching decompilation) adds a small adapter and gets a Linux and Windows port, a launcher and a release. -It grew out of the [Digimon World 2003 decompilation](https://github.com/gascarcella/dw2003recomp)'s `port/` and -`launcher/`, which consume it as a git submodule since `v0.1.0`. +The stack contains no game code and no game data; `docs/GAME_CONTRACT.md` is the line between the two. The first +consumer is [dw2003recomp](https://github.com/gascarcella/dw2003recomp), the Digimon World 2003 decompilation. + +## Features + +### Runtime +- **Memory and overlays:** an arena that keeps the PS1's distances between the game's memory slots, an N-slot overlay + manager with data reset and address tables, an optional heap (docs/PORT.md "Memory arena", "Overlays"). +- **Timing:** the interrupt pump at the game's nominal rate (50 PAL, 60 NTSC), root counters, vblank handlers + (docs/PORT.md "Interrupts, the pump and timing"). +- **Fibers:** a game's own tasks on host stacks of the runtime's, switched where its scheduler says and preempted at + the end of a vsync tick (docs/PORT.md "Fibers"). +- **Disc, memory cards and movies:** the disc image with a SHA-1 check against the game's known discs, memory cards + as files, MDEC movies and XA audio at the drive's rate (docs/PORT.md "Disc, memory cards and movies"). +- **Save states:** save and load anywhere, F5/F9 in the window, `--save-state`/`--load-state` on the command line + (docs/RUNTIME.md "Save states"). +- **Crash reports:** the build, the overlays, the game's state, the log's last lines and the stack, a minidump on + Windows (docs/PORT.md "Crash report"). +- **Debug channel** and an MCP server over it, for driving and inspecting a running game (`tools/mcp/README.md`). + +### Rendering +- **The software GPU:** the PS1's picture pixel for pixel, headless or in a window. +- **The hardware renderer** on SDL_GPU (Vulkan; Direct3D 12 on Windows): internal resolution up to 8x, sub-pixel + precision from the GTE's fractions, optional perspective-correct texturing (docs/PORT.md "Rendering", + "Sub-pixel precision"). +- **Present filters:** sharp bilinear, scanlines, CRT, xBR (docs/RUNTIME.md "The window"). +- **Screen fit:** fit, integer or stretch scaling; a wide 16:9 canvas a game's mod can turn on for the scenes that + widen. +- **Texture dumps and texture packs**, keyed by content (docs/RUNTIME.md "Texture dump", "Texture packs"). + +### Sound and input +- **The SPU core** and the audio device over SDL3, a WAV dump for tests (docs/RUNTIME.md "The SPU core", "Audio"). +- **Input:** keyboard and gamepads with rebindable buttons and hotkeys, a second player on a second gamepad + (docs/LAUNCHER.md "Input bindings"). +- **Input scripts:** replays a script drives frame by frame, the same grammar in the emulator and on the port + (docs/RUNTIME.md "The replay runners"). + +### The Psy-Q shim +- Sony's libraries reimplemented over hardware models (`gpu.c`, `gte.c`, `mdec.c`, `xa.c`), never decompiled: + LIBAPI, LIBC2, LIBCARD, LIBCD, LIBETC, LIBGPU, LIBGS, LIBGTE, LIBMCRD, LIBPAD, LIBPRESS, LIBSND, LIBSPU (docs/PORT.md "The Psy-Q shim"). +- The stack's own Psy-Q declarations (`include/psxstack/psyq/`), checked against a game's (`tools/psyq_decls.py`). + +### Launcher and in-game menu +- **The launcher:** disc check, video, audio, memory card, controls and mods settings, the game's crash report; every + string from the game's description (docs/LAUNCHER.md, `launcher/README.md`). +- **Updates:** a check against the game's GitHub releases, Update now and the launcher's own update + (docs/LAUNCHER.md "Updates"). +- **Add to Steam:** the game as a non-Steam shortcut with its artwork, for Steam's library, Game Mode on the Steam + Deck and its controller configuration (docs/LAUNCHER.md "Steam"). +- **The in-game menu:** the launcher's Settings, Controls and Mods inside the game's window on Escape or Back+Start, + applied live (docs/LAUNCHER.md "In-game menu"). + +### Mods +- Mod manifests with generated settings pages, code mods in the game, data mods from a mods directory, a load order + (docs/LAUNCHER.md "Mod manifest", "Data mods", "Mod runtime"). +- The stack's own mods, which every game has: `fast_forward` (hold Tab) and `fast_loading`. + +### Build, platforms and tools +- **One CMake call:** `psxstack_add_game()` (`cmake/psxstack.cmake`) builds the game's C for a 64-bit host, with + section renaming, post-link checks and a version stamp from the game's tags. +- **Platforms:** Linux, and Windows cross-built from Linux with llvm-mingw (tested under Wine); release packages an + AppImage and a Windows zip. +- **Gates:** the host-compile inventory (`tools/port_inventory.py`), sanitizer and `-m32` builds, the replay runners + against PCSX-Redux (`tools/replay/`), the launcher's self-test. +- **Reproducible tools:** `scripts/setup.sh` pins SDL3, Dear ImGui, DXC, llvm-mingw and CMake into `tools/`, no sudo. + +## Contents +- [Features](#features): [Runtime](#runtime) · [Rendering](#rendering) · [Sound and input](#sound-and-input) · + [The Psy-Q shim](#the-psy-q-shim) · [Launcher and in-game menu](#launcher-and-in-game-menu) · [Mods](#mods) · + [Build, platforms and tools](#build-platforms-and-tools) +- [Using it from a game](#using-it-from-a-game): [What a game provides](#what-a-game-provides) · + [Adding the stack](#adding-the-stack) · [Building the port](#building-the-port) · + [Building the launcher](#building-the-launcher) · [Versions and releases](#versions-and-releases) +- [Developing](#developing): [Setup](#setup) · [Tests](#tests) · [Layout](#layout) · [Docs](#docs) · + [Contributing](#contributing) +- [Background](#background): [Status](#status) · [How it got here](#how-it-got-here) +- [License](#license) -**Status: `v0.3.13`** (Add to Steam: the launcher puts the game in the player's Steam library as a non-Steam shortcut and takes it out again, `launcher.steam`, the optional artwork `launcher.steam_art` in game.json; v0.3.12 the in-game menu fitted to the screen, its Menu size, a Mods page that fits 640x480; v0.3.11 the launcher checks the game's GitHub releases and updates itself: `launcher.updates` in game.json, Update now, `--no-update-check`; v0.3.10 the mods' `stop` callback and `applies` in force, for the in-game menu's live switch; v0.3.9 the in-game menu: the launcher's Settings, Controls and Mods inside the game's window on Escape or Back+Start, applied live, `PSXSTACK_MENU`; v0.3.8 faster loading: the `fast_loading` mod, movies at the drive's rate; v0.3.7 quick save and load hotkeys, F5/F9; v0.3.6 a `write_mem` script step, a clean fiber stack under ASan; v0.3.5 a game that needs its disc says so in game.json; v0.3.4 the launcher self-test's rate, the GPU's known differences; v0.3.3 LIBC2's rand and the nominal rates; v0.3.2 a checkpoint without an image; v0.3.1 brought the second game's shim: LIBGTE, LIBGPU, LIBGS, LIBAPI, LIBCD, LIBSND, LIBCARD; v0.3.0 brought -an optional heap, the stack's own Psy-Q declarations, fibers for a game's tasks, the replay runners; v0.2.0 brought the hardware renderer on D3D12, sub-pixel precision, filters, -texture packs, a wide canvas and save states). Everything a game needs is here: the contract (`docs/GAME_CONTRACT.md`), the game description -and its generator (`schema/game.schema.json`, `tools/game_gen.py`), the runtime and the Psy-Q shim (`runtime/`, -`psyq/`), the build (`cmake/psxstack.cmake`), the launcher (`launcher/`), the tools and the docs. One game builds on -it so far; the second will widen the shim and the contract (releases follow semver, `PSXSTACK_API` counts -incompatible contract changes). +## Using it from a game + +### What a game provides +A matching decompilation whose C also compiles for a 64-bit host, plus a small adapter (`docs/GAME_CONTRACT.md` +"What the game provides"): +1. **`game.json`**, the game description (`schema/game.schema.json`): its id, title, discs, rate, memory slots, + optional updates repository and Steam artwork. It is generated into a header at configure time; nothing reads it + at run time. +2. **A hook header** holding the PS1 side of every hook macro and including `` under `PC_PORT`, so + the matching build never depends on the stack. +3. **The hooks in its C** (`PLATFORM_WAIT`, `OVERLAY_COPY`, `SLOT_FUNC`, …). +4. **Adapter units** implementing ``, and its own mods. +5. **The build inputs:** the unit list, the overlay list, its symbol files. +6. **Its tests:** the goldens, the replay scripts and the emulator's probes. +### Adding the stack +The stack is a git submodule pinned at a release tag: ```sh -scripts/setup.sh sdl3 imgui # or scripts/dev_link_tools.sh ../dw2003recomp/tools to reuse built tools -cmake -S launcher -B build/launcher -G Ninja [-DPSXSTACK_GAME_JSON=path/to/game.json] && cmake --build build/launcher +git submodule add https://github.com/gascarcella/psxstack psxstack +git -C psxstack checkout v0.3.16 +``` + +### Building the port +```cmake +include(psxstack/cmake/psxstack.cmake) # the submodule, pinned at a tag +psxstack_add_game(mygame GAME_JSON port/game/game.json UNITS build/gen/units.txt MAIN_UNIT src/main.c + OVERLAYS build/gen/overlays.txt INCLUDE_DIRS include . ADAPTER port/game/state.c ...) +``` +`cmake/psxstack.cmake` documents every argument and docs/RUNTIME.md "Build and run" the options and the command line. +The consumers to copy from: +- `examples/hello`, the smallest: one unit, no overlays, no disc; +- `examples/tasks`, the same with its work in tasks on the stack's fibers; +- dw2003recomp's `port/CMakeLists.txt`, the first real one. + +### Building the launcher +The launcher is its own CMake project, branded from the game's description: +```sh +cmake -S psxstack/launcher -B build/launcher -G Ninja -DPSXSTACK_GAME_JSON=... -DPSXSTACK_VERSION_ROOT=... +cmake --build build/launcher +``` +`launcher/README.md` has the rest, the Windows build and the self-test among it. + +### Versions and releases +Releases are semver tags; a game pins one, so a change here reaches it as a reviewable pin bump. `PSXSTACK_API` +(`include/psxstack/game.h`) counts incompatible contract changes. A game's release packages are named so the +launcher's update check finds them (docs/GAME_CONTRACT.md "Compatibility and versions", "Releases"). + +## Developing + +### Setup +`scripts/setup.sh` builds the pinned tools into `tools/` (gitignored, no sudo, idempotent): +```sh +scripts/setup.sh # sdl3 imgui link: enough for the launcher and the tests +scripts/setup.sh dxc llvm-mingw sdl3-windows # the hardware renderer's shaders, the Windows cross-build +scripts/dev_link_tools.sh ../dw2003recomp/tools # or reuse a game checkout's built tools +scripts/setup.sh link # in a git worktree: link the main checkout's +``` +A desktop window needs SDL3 built with the X11/Wayland `-dev` headers present (docs/RUNTIME.md "The window"). + +### Tests +None needs a disc or a game: +```sh +python3 tests/hello_test.py [--menu] [--gpu] # the smoke test: examples/hello built through psxstack_add_game() +python3 tests/tasks_test.py [--sanitize|--m32] # the fibers, with save states +python3 tests/shim_test.py [--sanitize|--m32] # the shim's deterministic pieces on their own +python3 tests/psyq_test.py [--sanitize] # the shim's LIBGTE and LIBGPU +python3 tests/game_gen_test.py # the description generator +python3 tests/sha256_test.py # runtime/sha256.c +python3 tests/replay_test.py # the replay runners against a fake emulator +python3 tools/mcp/selftest.py # the MCP server against a fake game +psyq/check.sh --compile # the shim with -Werror against the stack's declarations +cmake -S launcher -B build/launcher -G Ninja && cmake --build build/launcher SDL_VIDEO_DRIVER=offscreen build/launcher/dw2003-launcher --self-test build/selftest -python3 tests/game_gen_test.py # the description generator's test -python3 tests/psyq_test.py [--sanitize] # the shim's LIBGTE and LIBGPU functions on their own ``` +CI (`.github/workflows/ci.yml`) runs these on Linux and the Windows cross-build under Wine. A change to `runtime/`, +`psyq/`, `cmake/` or the contract is also tested against a real game: in a dw2003recomp checkout, +`cmake -S port -B build/port -G Ninja -DPSXSTACK_DIR=/path/to/psxstack` and its `scripts/test.sh` (it needs the +game's disc). -## Layout +### Layout | Path | Contents | |---|---| @@ -41,25 +179,59 @@ python3 tests/psyq_test.py [--sanitize] # the shim's LIBGTE and LIBGPU function | `schema/` | `game.schema.json`: the game description | | `examples/` | `dw2003.game.json` (the first game's description); `hello/`, a disc-free Psy-Q program built through the stack: its smoke test; `tasks/`, the same with its work in tasks on the stack's fibers | | `docs/` | `GAME_CONTRACT.md`, `PORT.md`, `RUNTIME.md`, `LAUNCHER.md`, `DECISIONS.md`, `THIRD_PARTY.md` | -| `tests/` | The stack's own tests: `hello_test.py`, `tasks_test.py` (the fibers, with save states), `game_gen_test.py`, `psyq_test.py` (the shim's LIBGTE and LIBGPU, its C in `tests/psyq/`), `shim_test.py` (the shim's deterministic pieces on their own: events, the memory card's BIOS calls, `CdSearchFile`; its C in `tests/shim/`), the launcher's fixtures (`launcher --self-test`, `tools/mcp/selftest.py`) | +| `tests/` | The stack's own tests: `hello_test.py`, `tasks_test.py` (the fibers, with save states), `game_gen_test.py`, `psyq_test.py` (the shim's LIBGTE and LIBGPU, its C in `tests/psyq/`), `shim_test.py` (the shim's deterministic pieces on their own: events, the memory card's BIOS calls, `CdSearchFile`; its C in `tests/shim/`), `sha256_test.py`, `replay_test.py`, the launcher's fixtures (`launcher --self-test`, `tools/mcp/selftest.py`) | -## Using it from a game -```cmake -include(psxstack/cmake/psxstack.cmake) # the submodule, pinned at a tag -psxstack_add_game(mygame GAME_JSON port/game/game.json UNITS build/gen/units.txt MAIN_UNIT src/main.c - OVERLAYS build/gen/overlays.txt INCLUDE_DIRS include . ADAPTER port/game/state.c ...) -``` -`cmake/psxstack.cmake` documents every argument; `docs/GAME_CONTRACT.md` what the game provides; `examples/hello` is -the smallest consumer (`examples/tasks` the same with its work in tasks on the stack's fibers), dw2003recomp's -`port/CMakeLists.txt` the first real one. The launcher is its own project: -`cmake -S psxstack/launcher -B build/launcher -DPSXSTACK_GAME_JSON=... -DPSXSTACK_VERSION_ROOT=...`. +### Docs +| Doc | What it covers | +|---|---| +| `docs/GAME_CONTRACT.md` | What a game provides and what the stack provides | +| `docs/PORT.md` | The runtime's design: hook macros, arena, overlays, pump, shim, rendering, sound, crash report | +| `docs/RUNTIME.md` | Building, running, options and formats | +| `docs/LAUNCHER.md` | The launcher/game contract, the settings file, mod manifests, updates, Steam, the in-game menu | +| `docs/DECISIONS.md` | The decisions and why | +| `docs/THIRD_PARTY.md` | Borrowings and pinned tools | +| `tools/mcp/README.md` | The MCP server | +| `launcher/README.md` | Building the launcher and its self-test | + +### Contributing +`CONTRIBUTING.md` has the ground rules (no game code, no game data, no Psy-Q SDK; no fact about a game in the stack; +the contract first), the gates a change runs and how a pull request is made. Problems and plans are +[GitHub issues](https://github.com/gascarcella/psxstack/issues); `.github/CODEOWNERS` names who reviews. -## How it got here +## Background -Built in five phases out of dw2003recomp's port (its `docs/DECISIONS.md` "The port stack lives in psxstack"): the -contract first, the port split in place behind it, the runtime and the launcher moved here against a scratch copy -of the game, the game converged on the submodule, then `v0.1.0`. `docs/DECISIONS.md` has the decisions. +### Status +**`v0.3.16`.** One game builds on it so far; the second will widen the shim and the contract. The recent releases: +- **v0.3.16:** the picture fits the screen (`video.scaling`, fit by default), the wide canvas at the window's aspect. +- **v0.3.15:** the in-game menu on the hardware renderer; unmuting a game started muted opens the audio device. +- **v0.3.14:** the launcher's self-test inside an AppImage. +- **v0.3.13:** Add to Steam (`launcher.steam`, the optional artwork `launcher.steam_art`). +- **v0.3.12:** the in-game menu fitted to the screen, its Menu size, a Mods page that fits 640x480. +- **v0.3.11:** the launcher checks the game's GitHub releases and updates itself (`launcher.updates`, Update now, + `--no-update-check`). +- **v0.3.10:** the mods' `stop` callback and `applies`, for the in-game menu's live switch. +- **v0.3.9:** the in-game menu: the launcher's Settings, Controls and Mods inside the game's window, applied live + (`PSXSTACK_MENU`). +- **v0.3.8:** faster loading: the `fast_loading` mod, movies at the drive's rate. +- **v0.3.7:** quick save and load hotkeys, F5/F9. +- **v0.3.6:** a `write_mem` script step, a clean fiber stack under ASan. +- **v0.3.5:** a game that needs its disc says so in game.json. +- **v0.3.4:** the launcher self-test's rate, the GPU's known differences. +- **v0.3.3:** LIBC2's rand and the nominal rates. +- **v0.3.2:** a checkpoint without an image. +- **v0.3.1:** the second game's shim: LIBGTE, LIBGPU, LIBGS, LIBAPI, LIBCD, LIBSND, LIBCARD. +- **v0.3.0:** an optional heap, the stack's own Psy-Q declarations, fibers for a game's tasks, the replay runners. +- **v0.2.0:** the hardware renderer on D3D12, sub-pixel precision, filters, texture packs, a wide canvas and save + states. + +### How it got here +It grew out of the [Digimon World 2003 decompilation](https://github.com/gascarcella/dw2003recomp)'s `port/` and +`launcher/`, which consume it as a git submodule since `v0.1.0`. It was built in five phases out of dw2003recomp's +port (its `docs/DECISIONS.md` "The port stack lives in psxstack"): the contract first, the port split in place behind +it, the runtime and the launcher moved here against a scratch copy of the game, the game converged on the submodule, +then `v0.1.0`. `docs/DECISIONS.md` has the decisions. ## License -MIT (`LICENSE`). The stack contains no game code and no game data. +MIT (`LICENSE`). The stack contains no game code and no game data; `docs/THIRD_PARTY.md` lists what it borrows and the +tools it pins. From 8d08054e94040d6d6619474a10f7c7d5c156bf92 Mon Sep 17 00:00:00 2001 From: Gabriel Scarcella Date: Sat, 24 Oct 2026 20:19:01 -0300 Subject: [PATCH 2/2] CI: a change to .github/CODEOWNERS alone runs nothing, like Markdown and LICENSE No step reads it. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/ci.yml | 6 ++++-- CLAUDE.md | 2 +- CONTRIBUTING.md | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e432fd..d049b82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,8 +6,8 @@ # 24.04 (SDL3 and Dear ImGui at their pins through scripts/setup.sh; the built tools cached on the pins, # scripts/setup.sh --pins, not on the script's text), and the Windows cross-build with its self-test under Wine. On pull # requests, pushes to main and by hand; a newer push to a pull request cancels the older run. Not on changes that touch -# only documentation (paths-ignore: Markdown and LICENSE; no step reads them, and main's ruleset requires no check, so -# such a pull request merges without a run). A change with any other file runs everything. +# only documentation (paths-ignore: Markdown, LICENSE and .github/CODEOWNERS; no step reads them, and main's ruleset +# requires no check, so such a pull request merges without a run). A change with any other file runs everything. name: CI on: push: @@ -16,11 +16,13 @@ on: - "docs/**" - "**/*.md" - "LICENSE" + - ".github/CODEOWNERS" pull_request: paths-ignore: - "docs/**" - "**/*.md" - "LICENSE" + - ".github/CODEOWNERS" workflow_dispatch: permissions: diff --git a/CLAUDE.md b/CLAUDE.md index 7944582..b342f7c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -55,7 +55,7 @@ The first consumer is [dw2003recomp](https://github.com/gascarcella/dw2003recomp | `examples/` | `dw2003.game.json` (the first game's description, a copy; the game's own is the source), `hello/` (a disc-free Psy-Q program built through the stack; `steam/` its Steam artwork, drawn by `make_art.py`), `tasks/` (the same with its work in tasks on the stack's fibers, preempted by a root counter 3 event) | | `tests/` | `hello_test.py`, `tasks_test.py` (the fibers, with save states), `shim_test.py` and `shim/` (the shim's deterministic pieces, no runtime), `game_gen_test.py`, `sha256_test.py` (runtime/sha256.c against FIPS 180-4 and hashlib), `fixtures/` (the launcher self-test's mod manifests and GitHub's release answers; `mods/multipliers`, the menu test's large page; `steam/`, a `shortcuts.vdf` and a `loginusers.vdf` from its `make_fixtures.py`) | | `docs/` | See below | -| `.github/workflows/ci.yml` | Jobs: `game-gen`, `hello` (hello and tasks, the latter also under the sanitizers; SHA-256, tests/sha256_test.py), `mcp`, `launcher` (build + self-test; hello with the in-game menu, its input self-test; hello's own launcher, its Steam artwork embedded), `windows` (cross-build + self-test under Wine, hello and tasks too); no disc, no game; not run for a change to Markdown or LICENSE alone | +| `.github/workflows/ci.yml` | Jobs: `game-gen`, `hello` (hello and tasks, the latter also under the sanitizers; SHA-256, tests/sha256_test.py), `mcp`, `launcher` (build + self-test; hello with the in-game menu, its input self-test; hello's own launcher, its Steam artwork embedded), `windows` (cross-build + self-test under Wine, hello and tasks too); no disc, no game; not run for a change to Markdown, LICENSE or CODEOWNERS alone | ## Commands ```sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b13a775..1e0ab2b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -43,7 +43,7 @@ test the stack runs on its own. 1. Open or pick an [issue](https://github.com/gascarcella/psxstack/issues): problems and plans live there. 2. Branch from `main`; a large change goes in phases, each one reviewable on its own. 3. Open a pull request to `main`. Its description says what was done and lists the gates that ran. -4. CI must be green (`.github/workflows/ci.yml`; a change to Markdown or `LICENSE` alone runs nothing). A code owner +4. CI must be green (`.github/workflows/ci.yml`; a change to Markdown, `LICENSE` or `.github/CODEOWNERS` alone runs nothing). A code owner (`.github/CODEOWNERS`) reviews and merges. ### Gates