testlevel chapters 2-31 overwrite game memory (coin counter and flag rows end after world 8: progress, language, options): level projects, play-tests and the arena use chapters 1 and 32-49, old settings migrate; level tally counts the level's own coins and secrets

This commit is contained in:
MineTec committed 2026-11-07 15:27:08 +01:00
1 parent 987b0104fa
commit d6b852a1b6
35 files changed
+1015 -175

No files matched your search

+75
View File
@@ -0,0 +1,75 @@
# TestLevel chapters: which ones are safe (2026-11-07)
World 9 ("TestLevel") has 49 chapter slots (table 0x572420), but the game's per-chapter arrays only
have rows for worlds 0–8. Indexing them with world 9 runs into other globals. Code:
`save/TestLevelChapters` (usable = chapter **1** and **32–49**).
## The arrays (index world·6 + chapter)
| Array | Where it is used |
|---|---|
| u32 coins 0x584F1C (coins << 12) | `levelRecord` (strat var 0xBE) get/set, HUD (FUN_00426bf0), tally (FUN_0040dd60), endLevel (FUN_0054d620: "all coins" check), **zeroed on every level start** (FUN_0041cba0), KSV keeps 54 entries as u16 |
| u8 flags 0x584EC8 (bit 0 collectible, bit 1 gold coin) | collectible picked up (HUD, strat var 0xFA rising) → \|=1; endLevel → \|=2 when coins == static total 0x5722F4[world·5 + chapter] (garbage for world 9, often 0) or cheat 0x584710&8 → \|=3; gold count FUN_0041cd70 (worlds 1–8 only) |
Coin total table 0x5722F4 and the selection map only know worlds 1–8 (map shows garbage targets
for world 9 – cosmetic).
## What world-9 chapter c hits
Coin slot 0x584FF4 + 4c, flag byte 0x584EFE + c (Ghidra references 0x584EF0–0x585240):
| c | coin slot | flag byte |
|---|---|---|
| 0 | 0x584FF4 counter var 0xC0 (HUD) | free |
| **1** | 0x584FF8 free (only cleared by new game) | free |
| 2 | 0x584FFC counter var 0xBF (HUD icon 0x150) | free |
| 3 | 0x585000 HUD flag (FUN_00427c40) | free |
| 4 | 0x585004 var 0x80 | free |
| 5–8 | 0x585008–14 last played tribe/world/chapter/map (strat vars 0xAB–0xAE, KSV +0x3E–41) | free |
| 6–9 | | 0x584F04 **language index** (u32; \|=2 → text table out of range) |
| 9 | 0x585018 **furthest progress** (world, chapter bytes; KSV +0x42/43) | |
| 10–13 | 0x58501C/20 free | 0x584F08 option (KSV +0xD6) |
| 12 | 0x585024 start of byte table (var 0x93, tribe 0) | |
| 14–21 | 0x585028–48 free | 0x584F0C / 0x584F10 (var 0x5B) |
| 22–25 | 0x58504C–58 table 0x585024, tribe 1 (read by var 0x93 in original levels) | free |
| 26–29 | table, tribe 1 | 0x584F18 option (KSV +0xD8) |
| 30–31 | table, tribe 1 (world 8/9) | coin slots of world 0 (never read) |
| **32–49** | table, tribes 2/3 (never used: tribe is 1, 4 only in the attract demo) | coin slots of world 0 |
## Verified in game (apptest :24, 2026-11-07)
* **Chapter 9** (arena test mod, 1 alligator, 2 coins collected): pause → "Beenden und zur
Auswahlkarte" → the selection map shows world "°p", "Kapitel 0", coin target 14384: furthest
progress 0x585018 was replaced by the coin counter (2 << 12 → world 0, chapter 32).
![chapter 9: broken map](img/mods/testlevel_ch9_map_broken.jpg)
* **Chapter 49** (same run): tally "Münzen gesammelt 2 / 12, Geheimnisse 0 / 0" (LNFO recounted),
save written with progress (9, 50) – the map caps the cursor at chapter 49, no crash; map fine.
![chapter 49 tally](img/mods/testlevel_ch49_tally.jpg)
* Before (arena on chapter 8, arena agent): tally "0 / 55": the collected value is the coin slot
after endLevel copied the level ids into 0x585008–14 (chapter 8 = last played map = 0), the total
is LNFO of the Village base.
## Tally totals (LNFO)
Chunk LNFO = u32 coins, u32 secrets → 0x5FF070 / 0x5FF060 (FUN_0042AB10; the tally shows the values
of the level just finished, kept in 0x5FF064 / 0x5FF06C). Originals: e.g. t1l3m004 40 = 20 Coin +
4 Coin5·5; levels with CoinLine/CoinCircle/enemies count those too. `mods/levels/LevelTally` recounts
Coin (1) + Coin5 (5) and Secret strats for new level projects and the Test World (20 coins, 0
secrets); the arena adds its dynamic coins (alligator hit/death coins + 5 exit bonus).
## Migration
* Level projects: stored chapter 1 or 32–49 kept (first file wins), others get the first free of
32–49; more than 18 projects share chapters (only one of them can be on – apply error otherwise).
Play-tests/exports of an old project: `migrate` (2..19 → 32..49, 20..31 → 32..43).
* The chapter options are choices (level: 1, 32–49; arena: 32–49, default 49); a stored old value is
invalid and falls back to the default (ModOptions).
* Editor: New level / Level settings spinners only offer usable chapters.
![chapter option](img/mods/testlevel_chapter_option.jpg)
## Not fixed
* The map lets the player pick any unlocked world-9 chapter; empty ones are linked to an installed
world-9 WAD (ModManager), so playing e.g. chapter 9 from the map still clobbers progress. Unlocking
chapter 32+ unlocks 2–31 on the map too.