crimsonland 0.1.0.dev12__py3-none-any.whl → 0.1.0.dev14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- crimson/assets_fetch.py +23 -8
- crimson/frontend/high_scores_layout.py +26 -0
- crimson/frontend/menu.py +22 -20
- crimson/frontend/panels/base.py +14 -26
- crimson/frontend/panels/controls.py +151 -62
- crimson/frontend/panels/credits.py +221 -0
- crimson/frontend/panels/databases.py +307 -0
- crimson/frontend/panels/options.py +4 -3
- crimson/frontend/panels/play_game.py +4 -4
- crimson/frontend/panels/stats.py +255 -296
- crimson/game.py +219 -81
- crimson/modes/quest_mode.py +10 -9
- crimson/modes/survival_mode.py +10 -9
- crimson/modes/tutorial_mode.py +10 -4
- crimson/ui/menu_panel.py +127 -0
- crimson/ui/perk_menu.py +54 -89
- crimson/ui/quest_results.py +24 -18
- crimson/views/perk_menu_debug.py +2 -2
- crimson/views/perks.py +2 -2
- crimsonland-0.1.0.dev14.dist-info/METADATA +197 -0
- {crimsonland-0.1.0.dev12.dist-info → crimsonland-0.1.0.dev14.dist-info}/RECORD +23 -19
- crimsonland-0.1.0.dev12.dist-info/METADATA +0 -9
- {crimsonland-0.1.0.dev12.dist-info → crimsonland-0.1.0.dev14.dist-info}/WHEEL +0 -0
- {crimsonland-0.1.0.dev12.dist-info → crimsonland-0.1.0.dev14.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: crimsonland
|
|
3
|
+
Version: 0.1.0.dev14
|
|
4
|
+
Requires-Dist: construct>=2.10.70
|
|
5
|
+
Requires-Dist: pillow>=12.1.0
|
|
6
|
+
Requires-Dist: platformdirs>=4.5.1
|
|
7
|
+
Requires-Dist: raylib>=5.5.0.4
|
|
8
|
+
Requires-Dist: typer>=0.21.1
|
|
9
|
+
Requires-Python: >=3.13
|
|
10
|
+
Project-URL: Documentation, https://crimson.banteg.xyz/
|
|
11
|
+
Project-URL: Repository, https://github.com/banteg/crimson
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# Crimsonland 1.9.93 decompilation + rewrite
|
|
15
|
+
|
|
16
|
+
This repository is a **reverse engineering + high‑fidelity reimplementation** of **Crimsonland 1.9.93 (2003)**.
|
|
17
|
+
|
|
18
|
+
- **Target build:** `v1.9.93` (GOG "Crimsonland Classic") — see [docs/provenance.md](docs/provenance.md) for exact hashes.
|
|
19
|
+
- **Rewrite:** a runnable reference implementation in **Python + raylib** under `src/`.
|
|
20
|
+
- **Analysis:** decompiles, name/type maps, and runtime evidence under `analysis/`.
|
|
21
|
+
- **Docs:** long-form notes and parity tracking under `docs/` (start at [docs/index.md](docs/index.md)).
|
|
22
|
+
|
|
23
|
+
The north star is **behavioral parity** with the original Windows build: timings, RNG, UI/layout quirks, asset decoding, and gameplay rules should match as closely as practical.
|
|
24
|
+
|
|
25
|
+
**[Read the full story](https://banteg.xyz/posts/crimsonland/)** of how this project came together: reverse engineering workflow, custom asset formats, AI-assisted decompilation, and game preservation philosophy.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick start
|
|
30
|
+
|
|
31
|
+
Install [uv](https://docs.astral.sh/uv/getting-started/installation/) package manager.
|
|
32
|
+
|
|
33
|
+
### Run the latest packaged build
|
|
34
|
+
|
|
35
|
+
If you just want to play the rewrite:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
uvx crimsonland@latest
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Run from a checkout
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
gh repo clone banteg/crimson
|
|
45
|
+
cd crimson
|
|
46
|
+
uv run crimson
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Keep runtime files local to the repo
|
|
50
|
+
|
|
51
|
+
By default, runtime files (e.g. `crimson.cfg`, `game.cfg`, highscores, logs, downloaded PAQs) live in your per-user data dir.
|
|
52
|
+
To keep everything under this checkout:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
export CRIMSON_RUNTIME_DIR="$PWD/artifacts/runtime"
|
|
56
|
+
mkdir -p artifacts/runtime
|
|
57
|
+
uv run crimson
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Assets + binaries
|
|
63
|
+
|
|
64
|
+
There are two separate “inputs” to this repo:
|
|
65
|
+
|
|
66
|
+
1. **Runtime assets for the rewrite** (PAQ archives)
|
|
67
|
+
2. **Original Windows binaries for reverse engineering** (`crimsonland.exe`, `grim.dll`, …)
|
|
68
|
+
|
|
69
|
+
We keep them out of git and expect a local layout like:
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
game_bins/
|
|
73
|
+
crimsonland/
|
|
74
|
+
1.9.93-gog/
|
|
75
|
+
crimsonland.exe
|
|
76
|
+
grim.dll
|
|
77
|
+
crimson.paq
|
|
78
|
+
music.paq
|
|
79
|
+
sfx.paq
|
|
80
|
+
artifacts/
|
|
81
|
+
runtime/ # optional: where you run the rewrite (cfg/status/paqs)
|
|
82
|
+
assets/ # optional: extracted PAQs for inspection/tools
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Running the rewrite
|
|
86
|
+
|
|
87
|
+
The rewrite loads the assets from original archives:
|
|
88
|
+
|
|
89
|
+
- `crimson.paq`
|
|
90
|
+
- `music.paq`
|
|
91
|
+
- `sfx.paq`
|
|
92
|
+
|
|
93
|
+
### Extracted assets
|
|
94
|
+
|
|
95
|
+
For inspection/diffs/tools, you can extract PAQs into a filesystem tree:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
uv run crimson extract crimsonland_1.9.93 artifacts/assets
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Same as the original, many loaders can work from either:
|
|
102
|
+
|
|
103
|
+
- **PAQ-backed assets** (preferred when available), or
|
|
104
|
+
- the **extracted filesystem layout** under `artifacts/assets/`.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## CLI cheat sheet
|
|
109
|
+
|
|
110
|
+
Everything is exposed via the `crimson` CLI (alias: `crimsonland`):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
uv run crimson # run the game (default command)
|
|
114
|
+
uv run crimson view ui # debug views / sandboxes
|
|
115
|
+
uv run crimson quests 1.1 # print quest spawn script
|
|
116
|
+
uv run crimson config # inspect crimson.cfg
|
|
117
|
+
uv run crimson extract <game_dir> artifacts/assets
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Useful flags:
|
|
121
|
+
|
|
122
|
+
- `--base-dir PATH` / `CRIMSON_RUNTIME_DIR=...` — where saves/config/logs live
|
|
123
|
+
- `--assets-dir PATH` — where `.paq` archives (or extracted assets) are loaded from
|
|
124
|
+
- `--seed N` — deterministic runs for parity testing
|
|
125
|
+
- `--demo` — enable shareware/demo paths
|
|
126
|
+
- `--no-intro` — skip logos/intro music
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Docs
|
|
131
|
+
|
|
132
|
+
Docs are authored in `docs/` and built as a static site at https://crimson.banteg.xyz/
|
|
133
|
+
|
|
134
|
+
For development, it's useful to have a live local build:
|
|
135
|
+
|
|
136
|
+
```
|
|
137
|
+
uv tool install zensical
|
|
138
|
+
zensical serve
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Development
|
|
144
|
+
|
|
145
|
+
### Tests
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
uv run pytest
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Lint / checks
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
uv run lint-imports
|
|
155
|
+
uv run python scripts/check_asset_loader_usage.py
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### `justfile` shortcuts
|
|
159
|
+
|
|
160
|
+
If you have `just` installed:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
just --list
|
|
164
|
+
just test
|
|
165
|
+
just docs-build
|
|
166
|
+
just ghidra-exe
|
|
167
|
+
just ghidra-grim
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Reverse engineering workflow
|
|
173
|
+
|
|
174
|
+
High level:
|
|
175
|
+
|
|
176
|
+
- **Static analysis is the source of truth.**
|
|
177
|
+
- Update names/types in [analysis/ghidra/maps/](analysis/ghidra/maps/).
|
|
178
|
+
- Treat [analysis/ghidra/raw/](analysis/ghidra/raw/) as generated output (regenerate; do not hand-edit).
|
|
179
|
+
- **Runtime tooling** (Frida / WinDbg) validates ambiguous behavior and captures ground truth.
|
|
180
|
+
- Evidence summaries live under [analysis/frida/](analysis/frida/).
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Contributing notes
|
|
185
|
+
|
|
186
|
+
- Keep changes small and reviewable (one subsystem/feature at a time).
|
|
187
|
+
- Prefer *measured parity* (captures/logs/deterministic tests) over “looks right”.
|
|
188
|
+
- When porting float constants from decompilation, prefer the intended value
|
|
189
|
+
(e.g. `0.6` instead of `0.6000000238418579` when it’s clearly a float32 artifact).
|
|
190
|
+
|
|
191
|
+
---
|
|
192
|
+
|
|
193
|
+
## Legal
|
|
194
|
+
|
|
195
|
+
This project is an independent reverse engineering and reimplementation effort for preservation, research, and compatibility.
|
|
196
|
+
|
|
197
|
+
No original assets or binaries are included. Use your own legally obtained copy.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
crimson/__init__.py,sha256=dij6OQ6Wctqur9P00ojTTZw6IaUNeZagPX4-2Qqr-Kw,367
|
|
2
|
-
crimson/assets_fetch.py,sha256=
|
|
2
|
+
crimson/assets_fetch.py,sha256=ScrxzSkbs0TkaUtIi-WLC4NN1nIL9J8RloSH_Uz4HGo,2356
|
|
3
3
|
crimson/atlas.py,sha256=hEcCHhPvguXAI6eH_G9Q8rpiX7M5akZ8fgJjMogmYrA,2401
|
|
4
4
|
crimson/audio_router.py,sha256=4lccGu5044WQ5sMz9yfZd4loSgEMDqXJWGvMmHyMGt0,5449
|
|
5
5
|
crimson/bonuses.py,sha256=owwYIRHRu1Kymtt4eEvpd62JwWAg8LOe20vDuPFB5SU,5094
|
|
@@ -19,27 +19,30 @@ crimson/effects_atlas.py,sha256=Ko1O7z-1jGkH_KSeb8RrR2EtAs4V8vfo70ofhqbFak4,2104
|
|
|
19
19
|
crimson/frontend/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
20
20
|
crimson/frontend/assets.py,sha256=JHxOID6Ti6bD2LercdRJ7sSSr0nRX3WWeuRPDQwwbsY,1343
|
|
21
21
|
crimson/frontend/boot.py,sha256=qZKJba3krNS-SODPAIk7Yl75hCzM0zLlC-Oxuy5ctcM,15334
|
|
22
|
-
crimson/frontend/
|
|
22
|
+
crimson/frontend/high_scores_layout.py,sha256=1HaeD8GghlOdmwChrJm_KDHJaepfElmn3lVY4Fvyvm4,793
|
|
23
|
+
crimson/frontend/menu.py,sha256=7s_0Pu9Y09Eh3I3wti8cxqODB--4GXXVh_GrLXtq3SI,26308
|
|
23
24
|
crimson/frontend/panels/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
24
|
-
crimson/frontend/panels/base.py,sha256=
|
|
25
|
-
crimson/frontend/panels/controls.py,sha256=
|
|
25
|
+
crimson/frontend/panels/base.py,sha256=c0A-vNlsnAxy-jz1cZtO-R2EpVEEL90zfKy6KVRpKcA,14862
|
|
26
|
+
crimson/frontend/panels/controls.py,sha256=Ve-xQ3tmJCzifIEMdqrVhPQ8mm2vNKX8YEV0lYlhr0E,11236
|
|
27
|
+
crimson/frontend/panels/credits.py,sha256=RlOG953MzqNU171MpjaH1tFZ_A4tunh9UT9Gfgpltmc,8429
|
|
28
|
+
crimson/frontend/panels/databases.py,sha256=T5IoAljC-UtJsf_aVc36H9fYa0og2G21qDhJ_783838,11603
|
|
26
29
|
crimson/frontend/panels/mods.py,sha256=Hw6JESTZqHB67KtRSixBtv8YyvTT9sMNW32ecxYJ3rU,4061
|
|
27
|
-
crimson/frontend/panels/options.py,sha256=
|
|
28
|
-
crimson/frontend/panels/play_game.py,sha256=
|
|
29
|
-
crimson/frontend/panels/stats.py,sha256=
|
|
30
|
+
crimson/frontend/panels/options.py,sha256=v-tEvifvCeb1_tw_sqoQxHrld1rd1gIYQMW1ZA-9Pro,16014
|
|
31
|
+
crimson/frontend/panels/play_game.py,sha256=BiO8oDhb6YQZqs3nZEJqUvajMeC6VRQ577doc50xwSY,24149
|
|
32
|
+
crimson/frontend/panels/stats.py,sha256=1-q9TezFVPADkTmPSAg_c_drkrlMOY3jYHjtAm3XGNE,12573
|
|
30
33
|
crimson/frontend/pause_menu.py,sha256=iM08blMUbgFnV-aGpTHxwieqSQzCnsS66WFMT3lr5vI,16365
|
|
31
34
|
crimson/frontend/transitions.py,sha256=-sAJUDqNZ943zXlqtvJ6jCg2YH8dSi8k7qK8caAfOKI,883
|
|
32
|
-
crimson/game.py,sha256
|
|
35
|
+
crimson/game.py,sha256=j8RI1-r67P81wV4_Wy9pKUtqHh8IZTiE-q3yH972z0s,99035
|
|
33
36
|
crimson/game_modes.py,sha256=qW7Tt97lSBmGrt0F17Ni5h8vRyngBzyS9XwWM1TFIEI,255
|
|
34
37
|
crimson/game_world.py,sha256=nfKGcm3LHChPGLHJsurDFAATrHmhRvTmgxcLzUN9m5I,25440
|
|
35
38
|
crimson/gameplay.py,sha256=UHsoxVj6jcdClVLdLM1q1o4NhwSTQqpHSQQ6GBPlT-s,90848
|
|
36
39
|
crimson/input_codes.py,sha256=PmSWFZIit8unTBWk3uwifpHWMuk0qMg1ueKX3MGC7D0,5379
|
|
37
40
|
crimson/modes/__init__.py,sha256=U4S_2y3zgLZVfMenHRaJFBW8yqh2mUBuI291LGQVOJ8,35
|
|
38
41
|
crimson/modes/base_gameplay_mode.py,sha256=0hAtdpXLYuhP304qC1GvbQ2rBAALpJTgScDgOs_nRwU,10190
|
|
39
|
-
crimson/modes/quest_mode.py,sha256=
|
|
42
|
+
crimson/modes/quest_mode.py,sha256=DUUH5pfACNmFbcT4F0_yhtyuyOZqx-rizKNx_sL3HDE,38322
|
|
40
43
|
crimson/modes/rush_mode.py,sha256=l4TAvjOvOA-Z-liMDXp_HGfszfghTmJUyVSkiPkfHQ0,11527
|
|
41
|
-
crimson/modes/survival_mode.py,sha256=
|
|
42
|
-
crimson/modes/tutorial_mode.py,sha256=
|
|
44
|
+
crimson/modes/survival_mode.py,sha256=ZIPjKf2plu_9CDrJp_WLRIGwUCmDo9_imDqa6h7zLD0,33612
|
|
45
|
+
crimson/modes/tutorial_mode.py,sha256=rWrVSCjM8G-fHn1_0iVWIzGTeLnCFSNktuoRNSX3cg4,27634
|
|
43
46
|
crimson/modes/typo_mode.py,sha256=G3zpg2J7WafXpIYsVV1LeO1gjCCmb40_cbxa_m2kx0U,17957
|
|
44
47
|
crimson/paths.py,sha256=JCKauCxHJnP4IIy5ocgs6tvbaSMkMUByQ76Zoz2UGZM,653
|
|
45
48
|
crimson/perks.py,sha256=JHNhKPOUq2w8h23gU7jpkx-erFKTO4Z8l8aHU8vrkO0,37068
|
|
@@ -79,8 +82,9 @@ crimson/ui/cursor.py,sha256=_6EJ7tnsW_Q4kPUrqBO5FInxhpHKUGGyVpDET5EG38I,2842
|
|
|
79
82
|
crimson/ui/demo_trial_overlay.py,sha256=yrxkpNYanQLaYOofFW01nelKE_bqqYFTunmHSpnbEgA,8818
|
|
80
83
|
crimson/ui/game_over.py,sha256=pkHDGE47yBraHY-BTnZzOFdRGUJ4ravF0cL1HBdA300,30267
|
|
81
84
|
crimson/ui/hud.py,sha256=sVJhh7iAmDISMAcB2AALw1tM0828mlddpAFUXJm8E8c,31123
|
|
82
|
-
crimson/ui/
|
|
83
|
-
crimson/ui/
|
|
85
|
+
crimson/ui/menu_panel.py,sha256=ko1NErvQ5Ystq4f-AL0_eB6FaWoT_n3uonX-X1Ya_6o,4578
|
|
86
|
+
crimson/ui/perk_menu.py,sha256=Idz7Ps8JzhBqUZQQH-n1dS_DviX5LDWRrhWFO0Qc9Ac,13787
|
|
87
|
+
crimson/ui/quest_results.py,sha256=lbd9uDNyCSNy-KZlNmrCv_S4-JVGioK3DLN65j63PWA,29152
|
|
84
88
|
crimson/ui/shadow.py,sha256=P6B8lZCu8W0YPhLcqi8H413D5oSNeJYwnroYAw4ZGYI,1090
|
|
85
89
|
crimson/views/__init__.py,sha256=1UWCzBSsgIeOtcKxqM4Vf12JEfPHKfb9KRZgl2TB84Q,1880
|
|
86
90
|
crimson/views/aim_debug.py,sha256=2ldQ1MJO8AeG0i9x4ZJ3YLyp1X-HY_nJ0E1mY8jFF7Q,10873
|
|
@@ -98,8 +102,8 @@ crimson/views/game_over.py,sha256=R7K7ENM7-ObcsZ5DqPHkrC8fuzAKLOFLZf3j7K5cvDE,40
|
|
|
98
102
|
crimson/views/ground.py,sha256=_QzsoFSPKA2qIj8OTvJFr2mqT_sM5_w05ucL4a9cCZQ,10226
|
|
99
103
|
crimson/views/lighting_debug.py,sha256=T9ce224ZrJtztKTSFUn1G29MY0KYuHVhNdcDU7hlrFc,45502
|
|
100
104
|
crimson/views/particles.py,sha256=Yp4OfuYAlDa0zB93OZm5gKBNIEeOGJ7kP5mSZ2wZXvc,10109
|
|
101
|
-
crimson/views/perk_menu_debug.py,sha256=
|
|
102
|
-
crimson/views/perks.py,sha256=
|
|
105
|
+
crimson/views/perk_menu_debug.py,sha256=aW_1Pvk96FSlxIsMcX8ZUdOGXjY9frqWwdS420_452c,17870
|
|
106
|
+
crimson/views/perks.py,sha256=iravMuB9QzZyrroyciFkTOB5Pnzt4vJz6AjTaOQd3-Y,15091
|
|
103
107
|
crimson/views/player.py,sha256=TYcWqNyat5Sl1kU8cYRdCey5R65UaBJpGoct57Oc6qI,16584
|
|
104
108
|
crimson/views/player_sprite_debug.py,sha256=DDU6kl9sfhZ2nVXzBbsPSUKdIutHf5YNs2DrNQPRb2Q,11158
|
|
105
109
|
crimson/views/projectile_fx.py,sha256=pmMiXm2hJ1XeGf40VtdPk2TbVJX56aATBYTCRekYOdU,23177
|
|
@@ -136,7 +140,7 @@ grim/sfx.py,sha256=cpn2Mmeio7BSDgbStSft-eZchO9Ot2MrK6iXJqxlLqU,7836
|
|
|
136
140
|
grim/sfx_map.py,sha256=FM5iBzKkG30Vtu78SRavVNgXMbGK7ZFcQ8i6lgMlzVw,4697
|
|
137
141
|
grim/terrain_render.py,sha256=EZ7ySYJyTZwXcrJx1mKbY3ewZtPi7Y270XnZgGJyZG8,31509
|
|
138
142
|
grim/view.py,sha256=oF4pHZehBqOxPjKMU28TDg3qATh_amMIRJp-vMQnpn4,334
|
|
139
|
-
crimsonland-0.1.0.
|
|
140
|
-
crimsonland-0.1.0.
|
|
141
|
-
crimsonland-0.1.0.
|
|
142
|
-
crimsonland-0.1.0.
|
|
143
|
+
crimsonland-0.1.0.dev14.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
|
|
144
|
+
crimsonland-0.1.0.dev14.dist-info/entry_points.txt,sha256=jzzcExxiE9xpt4Iw2nbB1lwTv2Zj4H14WJTIPMkAjoE,77
|
|
145
|
+
crimsonland-0.1.0.dev14.dist-info/METADATA,sha256=oXFIziqtI4gQTabCnabSQ9Q9omr3LkcdySpATsnsuqA,5262
|
|
146
|
+
crimsonland-0.1.0.dev14.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|