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.
@@ -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=z4vFH9h-RIwc2o6uKGzEtUaOdhUDSX6Art-WU6tNjd0,1864
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/menu.py,sha256=aA0zpCbuPobtC0fD5FsuZH55HV0HcUhTVVjfqBMlUAA,26179
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=HoZe-HSQcUPHcC1cM9IupTVdo-2yA4xvwBUp05S9LgA,15043
25
- crimson/frontend/panels/controls.py,sha256=APIf5liMj0jMTTSG3W0bS64lp3IIFhZRbvoSd4W8yTE,4680
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=d9DcmLBylilVrs7wnb-u4p1YdBx6RwDhXggKitiFXjk,15970
28
- crimson/frontend/panels/play_game.py,sha256=ZWosykIxPWi8ahIzpmg3fth8Zy5Jj-d9iKHK4WaF_nM,24131
29
- crimson/frontend/panels/stats.py,sha256=cC8-tPNo09QwVk2yoJ4lnFbsqZilIr1UMpJq-jQMzWg,12630
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=-1KbJmE4-VN_U4VuHNqqLY9aITBXLXKGAWph8awkJOk,92671
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=Jo4KdJqDdCeV6XGeCa0X9j0qy62YU7K8C0CvTzW9Zl4,38231
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=lr165K_byGbWym4eWDfBo6yea1ULc60AxDBKHB-PJPs,33521
42
- crimson/modes/tutorial_mode.py,sha256=YTUCfpgwrrgzfyRQ0BGcJKx8r825ni9PTQ_RQiV5AnQ,27217
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/perk_menu.py,sha256=8Litat_Kxax5U23IelaHFQ61faI0QlDnrQsQCzOTN2I,15362
83
- crimson/ui/quest_results.py,sha256=uQWPcNbE3MumLiIfcJMaWlBmwZ82NA9s8ld-eHfIpCk,28676
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=q4rn3R4tJASlep5jeAXwrBffj5_akJ4a4veq7FIpRiU,17831
102
- crimson/views/perks.py,sha256=Uac31DVvHZvjDmMrHpfvkg7LVpXw76xKL1BqwaLAsHU,15052
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.dev12.dist-info/WHEEL,sha256=fAguSjoiATBe7TNBkJwOjyL1Tt4wwiaQGtNtjRPNMQA,80
140
- crimsonland-0.1.0.dev12.dist-info/entry_points.txt,sha256=jzzcExxiE9xpt4Iw2nbB1lwTv2Zj4H14WJTIPMkAjoE,77
141
- crimsonland-0.1.0.dev12.dist-info/METADATA,sha256=_PTDJb4CgDU-60sxdEMFL3VEk0uOpzoKZL6E24hg7mM,244
142
- crimsonland-0.1.0.dev12.dist-info/RECORD,,
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,,
@@ -1,9 +0,0 @@
1
- Metadata-Version: 2.3
2
- Name: crimsonland
3
- Version: 0.1.0.dev12
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