macrosoft3dpinball/CLAUDE.md
m3ultra 2ca67bb28b Add Godot 4.7 physics testbed: Box3D/Jolt/GodotPhysics A/B pinball table
Playable table (hinge-motor flippers, plunger, bumper, drain) plus a headless
probe harness that measured, per engine: tunneling of a fast ball through a
1 cm wall with CCD off/on, and hinge-motor drive. Findings in godot/README.md:
Box3D never tunnels even with CCD off, but its hinge motor sign is inverted
vs Jolt/GodotPhysics, and Jolt blows through angular limits that Box3D holds.
Ships a from-source macOS arm64 libgodot-box3d.dylib (upstream has no
releases). Also gitignore the remaining Microsoft media at repo root.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-06 05:33:07 +10:00

78 lines
4.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# macrosoft3dpinball
`3D Pinball for Windows Space Cadet` on macOS. Two halves:
- The vendored decompilation (below) — the faithful original.
- `godot/` — a Godot 4.7 pinball testbed whose real job is A/B-ing 3D physics
backends (Box3D vs Jolt vs GodotPhysics) on CCD, hinge-motor flippers, and joint
limits. See `godot/README.md` for the probe harness and current findings (Box3D
never tunnels with CCD off but has an inverted hinge-motor sign vs Jolt).
Vendored copy of
[k4zmu2a/SpaceCadetPinball](https://github.com/k4zmu2a/SpaceCadetPinball) (MIT) at upstream
commit `cb9b7b8`, not a submodule — patch it in place, pull upstream by re-vendoring.
## Build (Apple Silicon)
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES=arm64 \
-DCMAKE_PREFIX_PATH="$(brew --prefix sdl2);$(brew --prefix sdl2_mixer)"
cmake --build build -j8
```
Binary lands in `bin/SpaceCadetPinball`. Needs `brew install sdl2 sdl2_mixer`.
Do **not** use upstream `build-mac-app.sh` — it downloads SDL2 `.framework` DMGs and builds a
signed universal `.app`+`.dmg`. Unnecessary here; brew SDL2 is already installed.
## Gotchas
- `CMakeLists.txt` line ~27 upstream hard-set `CMAKE_OSX_ARCHITECTURES "arm64;x86_64"`, which
silently overrode the `-D` flag the README tells you to pass. Universal linking then fails
because brew SDL2 is arm64-only. Patched to only set the default when not given on the
command line. Re-apply this when re-vendoring upstream.
- Homebrew resolves `sdl2` to `sdl2-compat` (SDL2 API on top of SDL3). Links and runs fine.
- Deployment target is 10.11, so the link emits "built for newer version 26.0" warnings against
the brew dylibs. Harmless.
## Game data (not in this repo)
The engine ships no assets. It needs the original data files, which are Microsoft's and are
**not redistributable** — supply them from your own media (Windows XP or earlier install disc
for `PINBALL.DAT`; the retail `Full Tilt! Pinball` CD for `CADET.DAT`). `.DAT`/`.MID` are
gitignored so they never land in a commit.
Drop them in any of these; first match wins in the order `CADET.DAT`, `PINBALL.DAT`, `DEMO.DAT`:
- the working directory, or `bin/` next to the binary
- `~/Library/Application Support/SpaceCadetPinball/` ← preferred, keeps the repo clean
Without them the binary exits with "Could not load game data" and lists these paths.
## The other two Full Tilt tables (Dragon's Keep, Pirate's Cove)
The retail CD carries `DRAGON.DAT` and `PIRATES.DAT` alongside `CADET.DAT`. **They do not play, and
making them play is a months-long reverse-engineering project per table — not a loader fix.**
Investigated 2026-07-28; evidence, so nobody re-derives it:
- The container format is shared (`PARTOUT(4.0)RESOURCE`) and all three tables use the same five
component type ids (200, 201, 202, 300, 400). So the DAT *parses* fine. That is the easy half.
- Only ~35 of Dragon's 278 named components and ~36 of Pirate's 355 match Cadet's names. The
88-entry `control::score_components` table in `control.cpp` binds behaviour to those names, and
`control.cpp` is 4600 lines of Cadet-specific rules (missions, ranks, wormholes, Gravity Well).
Each table needs its own equivalent written from scratch.
- Both tables use float attributes the engine has no semantics for: `409`, `1306`, `1406`,
`1600``1604` (plus `604`, `704``706` for Dragon, `1405` for Pirate). These are hard errors, not
missing-value errors — e.g. `loader::kicker` accepts only 401406 and calls `error(10, 20)` on
anything else. Dragon's kickers carry `409`, meaning unknown.
- Upstream will not do it. Maintainer k4zmu2a, issue #148: the effort is "comparable to doing the
whole process all over again, once per table", and issue #20: "I most likely will not be adding
support for DRAGON and PIRATE tables." Cadet was reversed with the aid of the *public PDB symbols*
shipped for XP's `pinball.exe`; no equivalent symbols exist for the Full Tilt table binaries.
Four issues have requested it (#20, #148, #160, #256); none has ever produced a PR.
If someone does take it on, `tools/datdump.py` dumps and diffs DAT structure, and
[DatPartoutExplorer](https://github.com/belaw/DatPartoutExplorer) has a `Resource Identifiers.txt`
mapping attribute ids to object types — including entries flagged as unused in Cadet, which is the
obvious first place to look up what `1600``1604` mean.