From 386a06006d99c017bec602e1cd34b901517dfa7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sat, 7 Nov 2026 14:12:49 +0100 Subject: [PATCH] strats: custom types stay editable after importing object types (custom code kept last), references between custom types by name, edit can change where fields come from, opcode aliases with clearer names, script view gotos 400 -> 31 (labeled break/continue, condition chains, jumps to return), script language 2: event handlers, switch, short-circuit && ||, constant folding, schema parameter names, plain numbers in cells --- docs/manual/22-strats.md | 36 +- notes/img/mods/strats2_edit_type.jpg | Bin 0 -> 188768 bytes notes/img/mods/strats2_game_import.jpg | Bin 0 -> 65933 bytes notes/strat-language.md | 115 ++-- notes/strat-opcodes.md | 17 +- .../editor/tools/catalog/CrossImport.java | 39 +- .../editor/tools/strats/StratEdits.java | 229 +++++++- .../editor/tools/strats/TypeDialog.java | 53 +- .../editor/tools/strats/TypeEdits.java | 16 +- .../llamamod/format/strat/OpTable.java | 18 +- .../llamamod/format/strat/StratAssembler.java | 26 +- .../llamamod/format/strat/StratCompiler.java | 543 ++++++++++++++---- .../llamamod/format/strat/StratListing.java | 15 +- .../llamamod/format/strat/StratPseudo.java | 431 ++++++++++++-- .../llamamod/format/strat/op-aliases.tsv | 5 + .../llamamod/format/strat/ops.tsv | 8 +- .../editor/tools/strats/StratEditsTest.java | 138 +++++ .../editor/tools/strats/StratsGameLevel.java | 93 +++ .../editor/tools/strats/StratsTour.java | 9 +- .../format/strat/StratCompilerTest.java | 171 +++++- .../format/strat/StratPseudoTest.java | 61 +- 21 files changed, 1771 insertions(+), 252 deletions(-) create mode 100644 notes/img/mods/strats2_edit_type.jpg create mode 100644 notes/img/mods/strats2_game_import.jpg create mode 100644 src/main/resources/com/eliasmueller/llamamod/format/strat/op-aliases.tsv diff --git a/docs/manual/22-strats.md b/docs/manual/22-strats.md index 6fe027e..c225f12 100644 --- a/docs/manual/22-strats.md +++ b/docs/manual/22-strats.md @@ -36,7 +36,9 @@ one, and how many objects of it are placed. meaning, the script uses its name (`snapToFloor`). * `g12` is a global variable shared by all scripts. * Numbers are in game units: `1.0` = one cell (or "true"), angles are written like `5.625deg`. - Speeds and turn rates are **per frame** (the game runs at 30 frames per second). + Speeds and turn rates are **per frame** (the game runs at 30 frames per second). Small raw + numbers have an `r`: `204r` is 204/4096 of a cell (about 0.05). +* `break name` / `continue name` leave or repeat the outer loop labelled `name:`. * `yield` ends the object's turn for this frame; a `loop { … yield }` runs once per frame. * `onEvent` installs a handler, for example "when the player touches me" (event type 4). * `spawn<…>(…)` creates another object, `address model:5` names a 3D model of the level. @@ -55,7 +57,7 @@ can be edited show a tooltip; edited lines turn **orange**. * It applies to **every object of that type** in the level, also to objects other scripts spawn. * It is saved in the project and written into the level when you build or play. -Example: in the Coin's script, `self.y = self.floorHeight + 204` puts snapping coins just above +Example: in the Coin's script, `self.y = self.floorHeight + 204r` puts snapping coins just above the floor. Changing `204` to `1.5` makes them float one and a half cells high: ![Original and edited Coin script in the game](img/strat_coin_constant_ab.jpg) @@ -70,7 +72,8 @@ empty template) opens the type editor: 1. **Name** – the name of the new type (letters, digits, `_`). 2. **Entry label** – where the script starts (for clones: the renamed strat). 3. **Type fields / parameters from** – which existing type's settings (parameters, waypoints, - flags) new objects of this type start with. + flags) new objects of this type start with. In a script you can use that type's parameter + names (for a Coin: `snapToFloor` for parameter 0). 4. Edit the source. **Check** assembles it and verifies the result; errors name the line. 5. **Create type**. The type appears in **Assets → Objects** and can be placed like any other. @@ -83,7 +86,9 @@ Select an object of a custom type (or pick the type in the Script panel's *Type* * **Edit type…** (Script panel or the Inspector's *Script* section) opens the type editor with its script. Change it, **Check**, then **Apply**. Objects of the type that are already placed - keep their place and run the new script. **Ctrl+Z** undoes the change. + keep their place and run the new script. **Ctrl+Z** undoes the change. *Type fields / + parameters from* can be changed here too: new objects start with the other type's settings, + placed ones keep theirs. * **Delete type…** removes the type. If objects in the level use it, the editor tells you how many and deletes them together with the type (also undoable). @@ -113,12 +118,19 @@ strat Pulser { ``` * Statements: `x = value`, `x += value`, `if (…) { } else { }`, `while (…) { }`, `loop { }`, - `do { } while (…)`, `break`, `continue`, `yield`, `end`, `call name` (for `sub name { … }`). + `do { } while (…)`, `switch (…) { case 1: … break default: … }`, `break`, `continue`, `yield`, + `end`, `call name` (for `sub name { … }`). +* `on touched { … }` runs its block when the player touches the object (the object needs + `collisionOn<0x20000>()` and `collRadius(…)`, like a coin); `on event(type, param) { … }` for + other events. The block ends like a sub (`remove` deletes the object). +* `a && b` and `a || b` in conditions stop as soon as the answer is known. * Any instruction can be called by name with its values in brackets: `turnLeft(4deg)`, `scale(size)`; values that are part of the instruction go in `<>`: `collisionOn<0x8000>()`. * Places: `v0`… (or a name given with `alias`), globals `g12`, properties `self.y`, `player.x`… -* Numbers mean the same as in the assembly: write `10.0` for ten (a plain `10` is ten 1/4096 - steps), angles as `90deg`. +* Numbers: `10` and `10.0` both mean ten cells, angles are written `90deg`. For a raw value (as + the Script view shows them) add `r`: `215r` = 215/4096; hex like `0x8000` is raw too. Values + inside `<…>` are raw. Scripts written before this rule start with `use rawNumbers` when you open + them, so they keep working. * **Check** compiles and verifies; errors name the line. Switching *Language* back to *Assembly* shows the generated instructions. The full reference is in `notes/strat-language.md`. @@ -138,11 +150,11 @@ in one test level below: on the left the waypoint way, on the right the script w 1. Import Bucky (**Assets → All worlds**, search "Bucky", drag it into the level). 2. Select it and open the **Script** panel. The script shows `wpFirst()`, `wpNext()` and - `wpTurnToY(v1)` / `moveForwardQ(215)`: Bucky **runs along its waypoint chain**, turning + `wpTurnToY(v1)` / `moveForwardQ(215r)`: Bucky **runs along its waypoint chain**, turning with the rate in parameter 1 and moving 215/4096 cells per frame. 3. At every node it reads `self.wpParam` (the node's field **+26**): the low part chooses run (`0`) or jump (`1.0`, `2.0`), the high part `128.0` means "run on", `64.0` "wait until the - player comes close". At the end: `if (!(!v0 && (self.wpEndFlags & 2))) goto …` – with + player comes close". At the end: `} while (!(!v0 && (self.wpEndFlags & 2r)))` – with **parameter 0** set the chain repeats instead of ending. ### Way 1: a circular waypoint chain (no script change) @@ -182,15 +194,13 @@ circle: ## Limits -* Custom types can't be edited or deleted right after importing object types from another level - in the same session – save and reopen the project first. * Big structural changes are up to you: the editor checks that the code is well-formed and that every model/animation/code reference points somewhere valid, not that the object behaves well. * Names of rarely used instructions are educated guesses (the opcode list shows a confidence for each). * Small constants stored as short numbers only accept −8.0 … 7.99 (see *Changing numbers*). * The Script view shows `while`, `do … while`, `switch`, `break` and `continue` where it can and - `goto` where the original jumps don't form nested blocks (a few hundred places in the whole - game); the Assembly view is always exact. + `goto` where the original jumps don't form nested blocks (31 places in the whole game, all in + the llama's script); the Assembly view is always exact. * In the clone dialog, renaming the type doesn't yet rename the entry label or the name inside the script text – edit those by hand if you want them to match. diff --git a/notes/img/mods/strats2_edit_type.jpg b/notes/img/mods/strats2_edit_type.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ee3e0fa27ae65f05d5639f1bf54b35fea61fb10 GIT binary patch literal 188768 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

@e0($NH;ll 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 Ad;kCd literal 0 HcmV?d00001 diff --git a/notes/img/mods/strats2_game_import.jpg b/notes/img/mods/strats2_game_import.jpg new file mode 100644 index 0000000000000000000000000000000000000000..915d71c63d7f023b0a530d52f921d82aeec247df GIT binary patch literal 65933 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: `spawn<3, 6, 0, 0, 0>(10.0, 204, 450, unit:35+0x28)`. +| jump out of an outer loop (to its end / head) | `break name` / `continue name`, the loop shown as `name: loop {` (`while`, `do`) | +| jump to a `return` / `end` / `remove` | `return` / `end` / `remove` (the same instruction) | +| conditional jumps separated only by expression code, to a common false target / the body | one condition with `&&` / `||` (short-circuit; also what the compiler generates) | +| `if (a) { if (b) {…} }` with nothing else in the outer block | `if (a && b) {…}`; leading `if (c) break` lines of a loop → `while (!c && …)` | + +Everything else stays `goto label`. Over all 1461 units: **11 019 → 400 → 31 gotos** (2026-11-07, +second pass; 138 labeled break/continue). The 31 left are one pattern in the Llama strat of every +level: a jump from inside a then-part into the else part (`if (a) { call; if (!b) goto else; … } +else {…}`); earlier versions showed these as a nested `if` without the else, which was wrong +(`fits` now refuses an inner if that targets the outer if's else label). Guarded by +`StratPseudoTest` (balanced blocks, every goto has its label, every `break name` names a loop). +Inline operands in `<>`: `spawn<3, 6, 0, 0, 0>(10.0, 204r, 450r, unit:35+0x28)`. Raw integers +pushed on the stack are written with an `r` suffix (`204r`), as in the script language (below); +`1.0`-style and `deg` values as in the assembly. Example (Coin): ``` strat Coin: setModel(model:5) -collRadius(409) +collRadius(409r) onEvent ev_0000, 0 // event type 4 → L_0084 if (v1) { collisionOn<32768>() ... } if (v0) { if (self.floorMaterial == -1.0) { skipArgs … } else { - self.y = self.floorHeight + 204 + self.y = self.floorHeight + 204r self.rotY = rnd(4096.0) } } @@ -132,10 +143,15 @@ loop { turnLeft(5.625deg); yield } ## Script language (`StratCompiler`) – writing NEW behaviour A small structured language in the style of the script view, compiled to the assembly above (so -everything the assembler checks still applies). Implemented slice (2026-11-07): strats, subroutines, -aliases, assignments, expressions, if/else if/else, while, loop, do-while, break/continue, yield, -calls of any opcode by name. Tests: `StratCompilerTest`; verified in game (village 1: -`img/mods/strats_script_game.jpg`). +everything the assembler checks still applies). Language version 2 (2026-11-07): strats, subs, +aliases, parameter names, assignments, expressions with constant folding, short-circuit `&&`/`||`, +if/else if/else, while, loop, do-while, switch, break/continue, yield, event handlers, calls of any +opcode by name. Tests: `StratCompilerTest`. In game (village 1, apptest, 2026-11-07): version 1 +scripts `img/mods/strats_script_game.jpg`; version 2 (`StratsGameLevel … v2`: a custom type, then +an imported Spider in the same session, the custom type edited afterwards, compiled Toucher/Ticker +with `on touched` / `on event(0x40, 30)`, switch, `&&`/`||`) loads and plays without errors +(`img/mods/strats2_game_import.jpg`); the handlers' visible effect was not confirmed (the test +objects were out of the camera's view under the slow harness). ``` // bobs one cell up and down and turns @@ -143,8 +159,11 @@ strat Bobber { alias base = v0 // .alias base = v0 alias phase = v1 setModel(model:5) // any opcode: name(stack arguments) - base = self.y + 1.0 + base = self.y + 1 // 1 = one cell phase = 0 + on touched { // event handler (type 4), runs as a subroutine + soundPlay(sound:6) + } loop { phase = phase + 4deg self.y = base + sin(phase) @@ -160,26 +179,44 @@ sub wobble { // called with "call wobble", ends with return | Construct | Compiles to | |---|---| -| `strat Name { … }` | `.string "Name"`, label `Name:`, `debugName "Name"`, body, `end` unless the body cannot fall through | +| `strat Name { … }` | `.string "Name"`, label `Name:`, `debugName "Name"`, body, `end` unless the body cannot fall through; event handler code behind it | | `sub name { … }` / `call name` / `return` | label, body, `return` / `call name` / `return` | -| `x = e`, `x += e` (`-=`, `*=`, `/=`) | e, pop op of x; `x += 1.0` / `x -= 1.0` → address + `inc`/`dec` | -| places | `vN`, alias, `gN`, `self.prop`, `player.prop`, `parent.prop`, `parent.vN`, `camera.`/`target.`/`target2.`/`boss.`/`dialog.prop` (props.tsv names or `propN`) | -| literals | as in the assembly: `10.0` = ten, `10` = 10 raw units (1/4096), `90deg`, `0x10`; 16-bit values use `pushShort`, others `push` | -| references | `model:N`, `anim:N`, `unit:N` (`address`), `sound:N` (`soundAddress`), `tex:N` (`push`) | -| operators (low → high) | `||` `|` (or) · `&&` (and) · `&` · `==` `!=` · `<` `>` `<=` `>=` · `<<` `>>` · `+` `-` · `*` `/` · unary `-` `!` | -| `op(e1, e2)` | e1, e2, `op a, b`; the argument count must match the opcode's pops; a value-returning op used as a statement is followed by `pop` | -| `if (c) {…} else if … else {…}` | `c; jz else; …; jmp end; else: …` | -| `while (c) {…}` / `loop {…}` | head label, `c; jz end`, body, `jmp`/`jmpYield head` | -| `do {…} while (c)` | body, `c; jnz head` | +| `x = e`, `x += e` (`-=`, `*=`, `/=`) | e, pop op of x; `x += 1` / `x -= 1` (= 1.0) → address + `inc`/`dec` | +| places | `vN`, alias, parameter name, `gN`, `self.prop`, `player.prop`, `parent.prop`, `parent.vN`, `camera.`/`target.`/`target2.`/`boss.`/`dialog.prop` (props.tsv names or `propN`) | +| numbers | plain integer = game units: `10` = 10.0 (40960 raw); `1.5`, `90deg` as in the assembly; **raw words**: `215r` or hex `0x10` | +| references | `model:N`, `anim:N`, `unit:N` / `unit:Name` (`address`), `sound:N` (`soundAddress`), `tex:N` (`push`) | +| operators (low → high) | `||` · `&&` · `|` · `&` · `==` `!=` · `<` `>` `<=` `>=` · `<<` `>>` · `+` `-` · `*` `/` · unary `-` `!` | +| constant folding | operators over constants are computed with the VM's rules (20.12 `*` = a·b>>12, `/` = (a<<8)/b<<4, shifts by b>>12, comparisons 0/1): `2 * 3 + 0.5` → `pushShort 6.5` | +| `op(e1, e2)` | e1, e2, `op a, b`; the argument count must match the opcode's pops; a value-returning op used as a statement is followed by `pop`. Inline operands `<…>` are raw words as in the assembly | +| conditions (`if`, `while`, `do … while`) | **short-circuit**: `a && b` → `a; jz F; b; jz F`, `a || b` → `a; jnz T; b; jz F; T:`; `!` swaps the jump; constant conditions need no code. In a value (`x = a && b`) both sides are evaluated (`and`/`or` opcodes) | +| `if (c) {…} else if … else {…}` | `c → else; …; jmp end; else: …` | +| `while (c) {…}` / `loop {…}` | head label, `c → end`, body, `jmp`/`jmpYield head` | +| `do {…} while (c)` | body, `c → head` | +| `switch (e) { case 1: … break … default: … }` | `e; switch tab; jmp default/end`, case bodies in order (C rules: fall through, `break` leaves the switch, `continue` the enclosing loop); table `.switch n` + `.case [imm] v, label` (short form when v fits 16 bits). Case values are constants | +| `on touched { … }` / `on event(type[, param]) [slot n] { … }` | `onEvent ev, slot` where it stands (slots 0, 1, … in order unless given); entry `.event type, param, handler`; the handler body (ends with `return`; `remove`/`end` allowed) behind the strat. type/param/slot are raw words; type 4 = touched (`collisionOn` + `collRadius` needed, like Coin), 0x40 = timer, 0x80/0x100 = player distance | | `break` / `continue` / `yield` / `end` | `jmp end` / `jmp head` (do: the condition) / `jmpYield next` / `end` | +| `use rawNumbers` | the version-1 number rule (plain integers are raw words) for the rest of the script | + +Layout: event entries and switch tables go to the **start** of the unit (like the original code): +data behind a terminating instruction would be decoded as dead code by `StratCode`'s +terminator-follower pass and break the listing. + +**Parameter names**: `StratCompiler.compile(src, names)` takes predefined names → `vN`; the editor +passes the parameter names of the object schema of the type the custom type's fields come from +(`StratEdits.paramNames`, the same names as the script view's aliases, e.g. `snapToFloor` = v0 +for Coin). The script's own `alias` wins. + +**Numbers, compatibility**: language version 1 (before 2026-11-07) read `10` as 10 raw units. The +compiler now writes the marker line `; script language 2` behind the embedded source; +`embeddedSource` of older output (no marker) puts `use rawNumbers` in front of the script, so an +old type opened with *Edit type…* compiles to the same code. Stored types are assembly anyway +(the script is a comment), so loading never recompiles. The generated assembly starts with the script as `;| ` comment lines, so the editor can show the script again (*Edit type…*). Comments: `//`, `/* */`; `;` and newlines separate statements. -**Next steps (not implemented)**: event handlers (`on touched { … }` → `.event` table + `onEvent`), -`switch`, `spawn` with typed arguments, local names for parameters from the object schema, `for`, -constant folding, typed numbers (int vs fixed) instead of the assembly's literal rules, -short-circuit `&&`/`||` (now: both sides are evaluated, like the original `and`/`or` opcodes). +**Not implemented**: `for`, `spawn` with typed arguments, typed variables (int vs fixed), a view of +event handlers as `on … { }` (the script view shows `onEvent` + the handler label). ## Editing in the level editor (`editor.tools.strats`) @@ -197,7 +234,8 @@ short-circuit `&&`/`||` (now: both sides are evaluated, like the original `and`/ source text (the cloned unit's listing with the strat renamed, or a template), entry label, type fields/parameters taken from an existing type. *Check* assembles and verifies; *Create* appends the unit at the end of the STPC code region (nothing else moves), adds the type to the - catalogue (Assets → Objects), stores `stratEdits.types` `{name, basedOn, entry, source, proto}`. + catalogue (Assets → Objects), stores `stratEdits.types` `{name, basedOn, entry, source, proto + [, fieldsFrom]}` (`fieldsFrom` = type of the fields/parameter names when it differs from basedOn). Verification: the merged STPC is disassembled again (no decode errors, entry decoded, every `address` operand of the new unit hits a model, animation set or code, and the new unit's listing re-assembles to the same words). @@ -206,8 +244,20 @@ short-circuit `&&`/`||` (now: both sides are evaluated, like the original `and`/ custom units (`TypeEdits.edit`, one undo step) and the placed objects move to the new entry. Delete warns with the number of objects that use the type and removes them with it (`TypeEdits.delete`: `Edits.delete` of the users + the type list change, one undo step). - Creating is undoable too (`TypeEdits.create`), except when imported types follow the custom - block (then appended as before). + Creating is undoable too (`TypeEdits.create`). In edit mode *Type fields / parameters from* can + be switched to another type (new placements start with its fields; placed objects keep theirs); + `(keep current fields)` is the default. Renaming a type also renames `unit:Old` in the other + custom types. +* **References between custom types**: `unit:N` operands that point at a custom type are stored + as `unit:TypeName` (`StratEdits.symbolic` on create/edit; on load for older projects, with the + saved `session.firstUnit`); the assembler resolves names through `Layout.withUnitNames`, the + listing prints them (`Names.unitName`). Deleting a referenced type is refused ("unknown unit + name"). +* **Imports in the same session** (CrossImport `CodeHook`): the merge is computed on the code + without the custom units (`mergeBase`), and the commit cuts the custom units off, merges, and + appends them again behind the imported code (`StratEdits.aroundImport`; objects follow by type + index and offset from the entry) – the same order as on load, so editing/deleting/undoable + creating keep working without reopening. (Imports themselves still clear the undo history.) * **Language** (dialog): *Assembly* or *Script* (compiled by `StratCompiler`, see above); switching Script → Assembly shows the generated code. * **Load order** (`ProjectIO.LoadHook.order()`): constants of base units (−10) → imported types @@ -218,10 +268,9 @@ short-circuit `&&`/`||` (now: both sides are evaluated, like the original `and`/ ## Limits * Custom types are edited and deleted as a whole list: the custom units are cut off the code and - appended again (objects follow their type's new entry). Not possible while object types imported - after the custom ones sit behind them in the code (save and reopen the project first; on load the - custom types always come last). A custom type that addresses another custom type's unit with - `unit:N` breaks when that index changes. Constants of custom types are changed through their source. + appended again (objects follow their type's new entry). Projects saved by older versions with + imports behind the custom types are reordered on load as before. Constants of custom types are + changed through their source. * `pushShort` holds only −8.0…7.99; bigger values need a source edit (`push`). * The script view is a reading aid (gotos where blocks do not nest; expressions assume the documented pop/push counts; ops with variable stack use are shown raw). diff --git a/notes/strat-opcodes.md b/notes/strat-opcodes.md index c20ce17..0fd3d0e 100644 --- a/notes/strat-opcodes.md +++ b/notes/strat-opcodes.md @@ -21,8 +21,13 @@ properties). Language/syntax: `notes/strat-language.md`. Disassembler/assembler: registered with 0x113; 0x14a is a no-op (FUN_004268c0 only acts for 0); 0x9c's value is dead; 0x18a/0x18b set the pending particle settings consumed by the next spawnParticle; 0x1a9's top value is the rain texture and the others are wind x, amount, wind z; all no-op/drop stubs verified. - Still low: 0x34 and 0xf2 (no reader of their flag bits found). Names unchanged (stored sources use - them); see the table for the new descriptions. + Still low: 0x34 and 0xf2 (no reader of their flag bits found); see the table for the new descriptions. +* **Renamed opcodes (aliases)**: placeholder names whose meaning the review established got clear + names – 0x2f `flagEC10000` → `freezeOffCamera`, 0x31 `flagEC2` → `touchable`, 0x33 `flagEC100` → + `noFloorPhysics`, 0x14a `hudReset2` → `hudResetNoop`. The old names stay valid mnemonics + (resource `op-aliases.tsv`, `OpTable.alias`), so stored sources still assemble; listings and the + compiler use the new names. Names of flags without a known reader (0x32, 0x34, 0x141–0x144, + 0x14b) keep their address-style names. * **252 opcodes matched to Argonaut names** (column *ref*: Croc 2 PSX demo jump table / Croc 1 handler names), by handler behaviour and table position. 99 slots are no-ops, error stubs or pop-only stubs (dropped Croc features). @@ -120,11 +125,11 @@ ops = operands (inline words for long ops, the 16-bit argument for short ops); p | 0x2c | `nop_0x2c` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x2d | `nop_0x2d` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x2e | `nop_0x2e` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | -| 0x2f | `flagEC10000` | imm | 0 | 0 | 1888 | medium | - | arg!=0 sets, 0 clears +0xEC bit 0x10000 = "freeze when off-camera": the camera pass (FUN_00436190) sets +0xEC 0x8000 when the strat is outside the camera range; with both bits set the frame loop (0x54c603) and the strat-vs-strat collision loop (0x54cc1a) skip it. Used by ~1350 strats (pickups, triggers, enemies). 54f720 | +| 0x2f | `freezeOffCamera` (was `flagEC10000`) | imm | 0 | 0 | 1888 | medium | - | arg!=0 sets, 0 clears +0xEC bit 0x10000 = "freeze when off-camera": the camera pass (FUN_00436190) sets +0xEC 0x8000 when the strat is outside the camera range; with both bits set the frame loop (0x54c603) and the strat-vs-strat collision loop (0x54cc1a) skip it. Used by ~1350 strats (pickups, triggers, enemies). 54f720 | | 0x30 | `trackPlayer` | imm | 0 | 0 | | medium | - | If no player yet: re-executes itself next frame (pc-=4, yield); else arg sets/clears +0xEC bit 0x4000 = update distance to player each frame (+0x148). 54fa80 | -| 0x31 | `flagEC2` | imm | 0 | 0 | 410 | medium | - | arg sets/clears +0xEC bit 2 = "others can stand on / touch me": in the strat collision loop (0x54cc96) a strat touching a strat with this bit gets +0xE8 0x400000 (and 0x800000 when it moves) = properties 32/33; also readable as property 0x1f. Set by Llama, Coin, Jar, EnemyCoin, RubyIdol. 54e090 | +| 0x31 | `touchable` (was `flagEC2`) | imm | 0 | 0 | 410 | medium | - | arg sets/clears +0xEC bit 2 = "others can stand on / touch me": in the strat collision loop (0x54cc96) a strat touching a strat with this bit gets +0xE8 0x400000 (and 0x800000 when it moves) = properties 32/33; also readable as property 0x1f. Set by Llama, Coin, Jar, EnemyCoin, RubyIdol. 54e090 | | 0x32 | `flagE8_80000000` | imm | 0 | 0 | | medium | - | arg sets/clears +0xE8 bit 31; no reader of the bit found in the exe (scan of all +0xE8 flag tests); unused in the levels. 54dd90 | -| 0x33 | `flagEC100` | imm | 0 | 0 | 60 | medium | - | arg sets/clears +0xEC bit 0x100; the collision response (0x4044f7) skips the floor/slope handling when it is set. Used by LlamaSpit, DropObject, RollerCoaster, KuscoTurtle (objects that move by script, not by floor physics). 54dd30 | +| 0x33 | `noFloorPhysics` (was `flagEC100`) | imm | 0 | 0 | 60 | medium | - | arg sets/clears +0xEC bit 0x100; the collision response (0x4044f7) skips the floor/slope handling when it is set. Used by LlamaSpit, DropObject, RollerCoaster, KuscoTurtle (objects that move by script, not by floor physics). 54dd30 | | 0x34 | `flagEC200000` | imm | 0 | 0 | 50 | low | - | arg sets/clears +0xEC bit 0x200000; no direct test of the bit found in the exe (all +0xEC flag tests scanned). Used by Llama, RiverCroc, RiverLog, Rock, river NPCs (river/canoe level objects). 54dd60 | | 0x35 | `nop_0x35` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | | 0x36 | `nop_0x36` | - | 0 | 0 | | high | - | No-op (shared empty handler); unused. 426500 | @@ -403,7 +408,7 @@ ops = operands (inline words for long ops, the 16-bit argument for short ops); p | 0x147 | `nop_0x147` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | | 0x148 | `gotoLevel4_1` | - | 0 | 0 | | medium | - | Hardcoded level change: next level (0x584EB4/EB8/EBC/EC0) = 4/1/1/0, previous level (0x585008..14) = 4/1/4/0, game state 0x584638 = 7 (load level). 54e430 | | 0x149 | `nop_0x149` | - | 0 | 0 | | high | - | Empty handler FUN_00426500 (shared no-op); does nothing. 426500 | -| 0x14a | `hudReset2` | - | 0 | 0 | | high | - | Calls FUN_004268c0(2), which returns at once for any argument other than 0 (verified in the assembly): a no-op. Unused. 54f700 | +| 0x14a | `hudResetNoop` (was `hudReset2`) | - | 0 | 0 | | high | - | Calls FUN_004268c0(2), which returns at once for any argument other than 0 (verified in the assembly): a no-op. Unused. 54f700 | | 0x14b | `setGlobal5fd086` | imm | 0 | 0 | | medium | - | Stores the low 16 bits of the inline word in global 0x5FD086 (never read elsewhere; dead leftover). 54e890 | | 0x14c | `removeCollPoint` | - | 1 | 0 | 49 | medium | stSetCollPoint (inverse) | pops id (fixed, >>12); removes the collision point with that id from the strat's collision point list (+0xC8 array of 4-byte entries, count +0xC6). Counterpart of 0xc6 (add/set collision point). 54e720 | | 0x14d | `setFlagEC_400000` | flags | 0 | 0 | | high | - | Inline word: nonzero sets, zero clears bit 0x400000 of strat flags2 (+0xEC); the bit selects which height constant own property 0xF2 returns. 54f780 | diff --git a/src/main/java/com/eliasmueller/llamamod/editor/tools/catalog/CrossImport.java b/src/main/java/com/eliasmueller/llamamod/editor/tools/catalog/CrossImport.java index a6a3fc0..096a98d 100644 --- a/src/main/java/com/eliasmueller/llamamod/editor/tools/catalog/CrossImport.java +++ b/src/main/java/com/eliasmueller/llamamod/editor/tools/catalog/CrossImport.java @@ -56,6 +56,23 @@ public final class CrossImport { /** Makes sure the load hook is registered. */ public static void init() {} + /** + * Lets the custom strat types (editor.tools.strats) step aside during an import: the merge + * runs on mergeBase (the code without them, null = unchanged) and the commit inside around, + * which takes them off and appends them again behind the imported code. + */ + public interface CodeHook { + byte[] mergeBase(Scene s); + + void around(Project p, Runnable commit); + } + + private static volatile CodeHook codeHook; + + public static void setCodeHook(CodeHook h) { + codeHook = h; + } + /** One imported type: source level, type name and its code entry in the source STPC. */ public record TypeRef(String level, String type, int code) { Map json() { @@ -172,8 +189,16 @@ public final class CrossImport { int pages = ref.pages().size(), tex = ref.textures().size(), anims = ref.textureAnims().size(); - apply(o, ref, false, -1, -1, -1); - apply(o, cur, true, pages, tex, anims); + Runnable merge = () -> { + apply(o, ref, false, -1, -1, -1); + apply(o, cur, true, pages, tex, anims); + }; + CodeHook h = codeHook; + if (h != null) { + h.around(p, merge); + } else { + merge.run(); + } @SuppressWarnings("unchecked") List l = p.extra().get(KEY) instanceof List x ? (List) x : new ArrayList<>(); List nl = new ArrayList<>(l); @@ -326,12 +351,16 @@ public final class CrossImport { if (c == null) { throw new IllegalStateException("the level has no STPC chunk"); } + return analysis(s, c.data()); + } + + private static StpcMerge.Analysis analysis(Scene s, byte[] stpc) { Set roots = new TreeSet<>(); for (Strat x : s.strats()) { roots.add(x.code()); } roots.addAll(s.catalog().names().keySet()); - StpcImage img = new StpcImage(c.data(), s.settings().wfpc()); + StpcImage img = new StpcImage(stpc, s.settings().wfpc()); roots.removeIf(o -> o < img.codeStart || img.unitOf(o) < 0); return new StpcMerge.Analysis(img, roots); } @@ -361,7 +390,9 @@ public final class CrossImport { /** Merges a batch into (a copy of) the scene's level data; the scene is not changed. */ public static Outcome compute(Scene s, List batch, Bases cd) throws IOException { - StpcMerge.Analysis tgt = analysis(s); + CodeHook h = codeHook; + byte[] base = h == null ? null : h.mergeBase(s); + StpcMerge.Analysis tgt = base == null ? analysis(s) : analysis(s, base); TextMerge.Textures tex = textures(s); int p0 = tex.pages.size(), e0 = tex.entries.size(), a0 = tex.anims.size(); RawChunk sm = chunk(s, "SMPC"); diff --git a/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/StratEdits.java b/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/StratEdits.java index 0261140..f13946d 100644 --- a/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/StratEdits.java +++ b/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/StratEdits.java @@ -8,6 +8,7 @@ import com.eliasmueller.llamamod.editor.model.Scene; import com.eliasmueller.llamamod.editor.model.SceneEvent; import com.eliasmueller.llamamod.editor.model.Strat; import com.eliasmueller.llamamod.editor.model.StratCatalog; +import com.eliasmueller.llamamod.editor.tools.catalog.CrossImport; import com.eliasmueller.llamamod.editor.tools.objects.ParamSchema; import com.eliasmueller.llamamod.editor.tools.objects.Schemas; import com.eliasmueller.llamamod.format.Bytes; @@ -64,14 +65,32 @@ public final class StratEdits { /** * A custom type: name, source text, the entry label in the source, type fields (MAP record - * prototype), and where it came from. + * prototype), where it came from (basedOn, the cloned type) and the type its fields and + * parameter names are taken from (fieldsFrom). */ public record CustomType( - String name, String basedOn, String entryLabel, String source, StratCatalog.Variant proto) { + String name, + String basedOn, + String entryLabel, + String source, + StratCatalog.Variant proto, + String fieldsFrom) { + /** A type whose fields come from the type it is based on. */ + public CustomType(String name, String basedOn, String entryLabel, String source, StratCatalog.Variant proto) { + this(name, basedOn, entryLabel, source, proto, basedOn); + } + + public CustomType withSource(String src) { + return new CustomType(name, basedOn, entryLabel, src, proto, fieldsFrom); + } + Map json() { Map m = new LinkedHashMap<>(); m.put("name", name); m.put("basedOn", basedOn == null ? "" : basedOn); + if (fieldsFrom != null && !fieldsFrom.isEmpty() && !fieldsFrom.equals(basedOn)) { + m.put("fieldsFrom", fieldsFrom); + } m.put("entry", entryLabel); m.put("source", source); Map p = new LinkedHashMap<>(); @@ -129,12 +148,14 @@ public final class StratEdits { params, List.copyOf(chain), "custom"); + String based = (String) m.get("basedOn"); return new CustomType( (String) m.get("name"), - (String) m.get("basedOn"), + based, (String) m.get("entry"), (String) m.get("source"), - v); + v, + m.get("fieldsFrom") instanceof String ff ? ff : based); } } @@ -181,6 +202,8 @@ public final class StratEdits { boolean edited; int firstCustom = -1; final List customEntries = new ArrayList<>(); + final List customNames = new ArrayList<>(); + final List customFields = new ArrayList<>(); } private static final Map STATE = Collections.synchronizedMap(new WeakHashMap<>()); @@ -217,6 +240,20 @@ public final class StratEdits { /** Makes sure the load hooks are registered. */ public static void init() {} + static { + CrossImport.setCodeHook(new CrossImport.CodeHook() { + @Override + public byte[] mergeBase(Scene s) { + return importBase(s); + } + + @Override + public void around(Project p, Runnable commit) { + aroundImport(p, commit); + } + }); + } + private static int num(Map m, String k) { return ((Number) m.get(k)).intValue(); } @@ -247,7 +284,24 @@ public final class StratEdits { return; } int startBefore = codeEnd(cur); - for (CustomType t : r.types) { + Map ses = json.get(KEY) instanceof Map m && m.get("session") instanceof Map x ? x : null; + // unit:N operands of older projects that point at custom types → unit:Name + int savedFirst = ses != null && ses.get("firstUnit") instanceof Number n ? n.intValue() : units(cur); + List names = r.types.stream().map(CustomType::name).toList(); + List stored = json.get(KEY) instanceof Map m && m.get("types") instanceof List l + ? List.copyOf(l) + : List.of(); + for (int i = 0; i < r.types.size(); i++) { + CustomType t = r.types.get(i); + String src = symbolic(t.source, savedFirst, names.subList(0, i)); + if (!src.equals(t.source)) { + t = t.withSource(src); + if (i < stored.size() && stored.get(i) instanceof Map sm) { + @SuppressWarnings("unchecked") + Map w = (Map) sm; + w.put("source", src); + } + } try { appendType(ref, t, false); appendType(cur, t, false); @@ -255,7 +309,7 @@ public final class StratEdits { warnings.add("custom strat type " + t.name + " could not be assembled: " + e.getMessage()); } } - if (json.get(KEY) instanceof Map m && m.get("session") instanceof Map ses) { + if (ses != null) { int cs = num(ses, "start"), ce = num(ses, "end"); int b = startBefore - cs; if (b != 0) { @@ -359,6 +413,10 @@ public final class StratEdits { if (n == null) { n = com.eliasmueller.llamamod.format.Strats.name(a.img.data, code, a.img.codeStart); } + int k = customIndex(s, a.img.unitOf(code)); + if (k >= 0 && state(s).customFields.get(k) != null) { + n = state(s).customFields.get(k); // parameter names of the type the fields come from + } ParamSchema.TypeSchema ts = Schemas.of(n); ParamSchema.ParamDef d = ts == null ? null : ts.param(i); return d == null ? null : ident(d.name()); @@ -368,9 +426,30 @@ public final class StratEdits { public String entry(int code) { return cat.nameOf(code); } + + @Override + public String unitName(int u) { + int k = customIndex(s, u); + return k >= 0 ? state(s).customNames.get(k) : null; + } }); } + /** Script names of a type's parameters from its object schema: name → "vN" (empty if unknown). */ + public static Map paramNames(String type) { + Map m = new LinkedHashMap<>(); + ParamSchema.TypeSchema ts = type == null ? null : Schemas.of(type); + if (ts != null) { + for (ParamSchema.ParamDef d : ts.params()) { + String n = ident(d.name()); + if (n != null && !m.containsKey(n)) { + m.put(n, "v" + d.index()); + } + } + } + return m; + } + static String ident(String label) { StringBuilder b = new StringBuilder(); boolean up = false; @@ -519,14 +598,28 @@ public final class StratEdits { /** Assembles a type's source as a new unit appended to the scene's code and verifies it. */ public static Built build(Scene s, CustomType t) { Analysis a = analysis(s); - return build(a.img.data, s.settings().wfpc(), a.entries, t); + return build(a.img.data, s.settings().wfpc(), a.entries, t, customUnits(s)); } - /** Assembles a type's source as a new unit appended to the STPC data old and verifies it. */ - static Built build(byte[] old, int wfpc, Set entries, CustomType t) { + /** Unit index of each custom type of the scene by name (for unit:Name operands). */ + static Map customUnits(Scene s) { + State st = state(s); + Map m = new LinkedHashMap<>(); + for (int i = 0; i < st.customNames.size(); i++) { + m.put(st.customNames.get(i), st.firstCustom + i); + } + return m; + } + + /** + * Assembles a type's source as a new unit appended to the STPC data old and verifies it; + * names = unit index of the custom types before it (unit:Name). + */ + static Built build(byte[] old, int wfpc, Set entries, CustomType t, Map names) { StpcImage img0 = new StpcImage(old, wfpc); int base = old.length + 4; - StratAssembler.Result r = StratAssembler.assemble(t.source, StratListing.layout(img0, base)); + StratAssembler.Result r = StratAssembler.assemble( + t.source, StratListing.layout(img0, base).withUnitNames(names)); Integer e = r.labels().get(t.entryLabel); if (e == null) { throw new IllegalArgumentException("entry label " + t.entryLabel + " not found in the source"); @@ -628,11 +721,14 @@ public final class StratEdits { st.firstCustom = unit; } st.customEntries.add(b.entry); + st.customNames.add(t.name); + st.customFields.add(t.fieldsFrom); return b.entry; } /** Adds a custom type to an open project (reference + scene) and records it. Returns the entry code. */ public static int addType(Project p, CustomType t) { + t = t.withSource(symbolic(p.scene(), t.source)); appendType(p.reference(), t, false); int code = appendType(p.scene(), t, true); Records r = Records.of(p.extra()); @@ -642,6 +738,36 @@ public final class StratEdits { return code; } + private static final java.util.regex.Pattern UNIT_REF = java.util.regex.Pattern.compile("\\bunit:(\\d+)\\b"); + + /** Source with unit:N operands that point at custom types written as unit:TypeName (survives reordering). */ + public static String symbolic(Scene s, String src) { + State st = state(s); + return symbolic(src, st.firstCustom, st.customNames); + } + + static String symbolic(String src, int first, List names) { + if (first < 0 || names.isEmpty()) { + return src; + } + java.util.regex.Matcher m = UNIT_REF.matcher(src); + StringBuilder b = new StringBuilder(); + while (m.find()) { + int k = Integer.parseInt(m.group(1)) - first; + String rep = k >= 0 && k < names.size() ? "unit:" + names.get(k) : m.group(); + m.appendReplacement(b, java.util.regex.Matcher.quoteReplacement(rep)); + } + m.appendTail(b); + return b.toString(); + } + + /** Source with unit:Old operands renamed to unit:New. */ + static String renameUnitRefs(String src, String oldName, String newName) { + return src.replaceAll( + "\\bunit:" + java.util.regex.Pattern.quote(oldName) + "(?![\\w])", + java.util.regex.Matcher.quoteReplacement("unit:" + newName)); + } + /** Why the custom types of a scene cannot be rebuilt in place (null = they can). */ public static String rebuildBlocker(Scene s) { State st = state(s); @@ -678,9 +804,19 @@ public final class StratEdits { Set entries = new TreeSet<>(analysis(s).entries); entries.removeIf(o -> o >= d.length); byte[] cur = d; + int unit = new StpcImage(d, s.settings().wfpc()).units.size(); + Map names = new LinkedHashMap<>(); for (int i = 0; i < types.size(); i++) { CustomType t = types.get(i); - Built x = build(cur, s.settings().wfpc(), entries, t); + Built x; + try { + x = build(cur, s.settings().wfpc(), entries, t, names); + } catch (StratAssembler.AsmException e) { + if (i == index) { + throw e; + } + return List.of(t.name + ": " + e.getMessage()); + } if (!x.problems.isEmpty()) { return x.problems.stream().map(m -> t.name + ": " + m).toList(); } @@ -691,6 +827,7 @@ public final class StratEdits { for (int v : x.asm.strats().values()) { entries.add(x.base + v); } + names.put(t.name, unit + i); cur = x.stpc; } return null; @@ -709,7 +846,7 @@ public final class StratEdits { } } for (Scene s : List.of(p.reference(), p.scene())) { - Runnable r = () -> rebuild(s, types, remap); + Runnable r = () -> append(s, types, remap, cut(s)); if (s == p.scene()) { s.bulk(r); } else { @@ -720,20 +857,24 @@ public final class StratEdits { new Records(rec.constants, List.copyOf(types)).store(p.extra(), session(p.scene())); } - private static void rebuild(Scene s, List types, int[] remap) { + /** Objects of the custom types while their code is cut off: custom type index and old code; old entries. */ + private record Detached(Map objects, List entries) {} + + /** Cuts the custom units off a scene's code and removes them from the catalog (objects keep code 0). */ + private static Detached cut(Scene s) { State st = state(s); List oldEntries = new ArrayList<>(st.customEntries); Analysis a = analysis(s); int from = st.firstCustom < 0 ? a.img.data.length : a.img.units.get(st.firstCustom).start() - 4; - int to = a.img.data.length; - List oldUnitOf = new ArrayList<>(), oldCode = new ArrayList<>(); + int to = st.firstCustom < 0 + ? a.img.data.length + : a.img.units.get(st.firstCustom + st.customEntries.size() - 1).end(); + Map objects = new java.util.IdentityHashMap<>(); for (Strat x : s.strats()) { - boolean custom = x.code() >= from && x.code() < to; - oldUnitOf.add(custom ? a.img.unitOf(x.code()) - st.firstCustom : -1); - oldCode.add(x.code()); - if (custom) { + if (x.code() >= from && x.code() < to) { + objects.put(x, new int[] {a.img.unitOf(x.code()) - st.firstCustom, x.code()}); s.set(x, "code", 0); // keep stale codes out of the analysis roots while appending } } @@ -751,28 +892,61 @@ public final class StratEdits { chunk(s).setRaw("data", cut); st.firstCustom = -1; st.customEntries.clear(); + st.customNames.clear(); + st.customFields.clear(); + return new Detached(objects, oldEntries); + } + + /** Appends types to a scene whose custom units were cut off; objects of old type k follow type remap[k]. */ + private static void append(Scene s, List types, int[] remap, Detached old) { + State st = state(s); for (CustomType t : types) { appendType(s, t, false); } - List strats = List.copyOf(s.strats()); - for (int i = 0; i < strats.size(); i++) { - int k = oldUnitOf.get(i); - if (k < 0) { + for (Strat x : s.strats()) { + int[] o = old.objects.get(x); + if (o == null) { continue; } - Strat x = strats.get(i); - int nk = k < remap.length ? remap[k] : -1; + int k = o[0]; + int nk = k >= 0 && k < remap.length ? remap[k] : -1; if (nk < 0 || nk >= st.customEntries.size()) { throw new IllegalStateException(x.id() + " still uses a removed custom type"); } - int oldEntry = oldEntries.get(k); + int oldEntry = old.entries.get(k); // objects placed at the entry follow the entry; other codes keep their offset in the unit - int c0 = oldCode.get(i); + int c0 = o[1]; int code = c0 == oldEntry ? st.customEntries.get(nk) : c0 - oldEntry + st.customEntries.get(nk); s.set(x, "code", code); } } + /** + * Runs an import of object types (CrossImport) with the custom units cut off first and + * appended again afterwards, so that they stay the last units (as on load) and can still be + * edited and deleted. + */ + static void aroundImport(Project p, Runnable commit) { + List types = records(p).types; + if (state(p.scene()).firstCustom < 0 || types.isEmpty() || rebuildBlocker(p.scene()) != null) { + commit.run(); + return; + } + Detached r = cut(p.reference()); + Detached[] sc = new Detached[1]; + p.scene().bulk(() -> sc[0] = cut(p.scene())); + commit.run(); + int[] id = TypeEdits.identity(types.size()); + append(p.reference(), types, id, r); + p.scene().bulk(() -> append(p.scene(), types, id, sc[0])); + updateSession(p); + } + + /** STPC data an import merges into: the code without the custom units (null = the scene's own). */ + static byte[] importBase(Scene s) { + return state(s).firstCustom < 0 || rebuildBlocker(s) != null ? null : withoutCustom(s); + } + /** Objects of the scene whose code lies in custom type index k's unit. */ public static List users(Scene s, int k) { State st = state(s); @@ -802,6 +976,7 @@ public final class StratEdits { m.put("start", (long) (a.img.units.get(st.firstCustom).start() - 4)); m.put("end", (long) a.img.units.get(Math.min(last, a.img.units.size() - 1)).end()); + m.put("firstUnit", (long) st.firstCustom); return m; } diff --git a/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeDialog.java b/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeDialog.java index bf35c9a..c880118 100644 --- a/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeDialog.java +++ b/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeDialog.java @@ -83,7 +83,7 @@ final class TypeDialog { open(ctx, "New object type from script", freeName(s, "MyStrat"), TEMPLATE, base, "MyStrat", false, -1); } - /** Edits custom type k in place: its name, entry label and source (type fields are kept). */ + /** Edits custom type k in place: its name, entry label, source and (optionally) where its type fields come from. */ static void showEdit(EditorContext ctx, int k) { if (ctx.document() == null) { return; @@ -105,7 +105,7 @@ final class TypeDialog { "Edit object type " + t.name(), t.name(), t.source(), - t.basedOn(), + t.fieldsFrom(), t.entryLabel(), t.basedOn() != null && !t.basedOn().isEmpty(), k); @@ -170,6 +170,13 @@ final class TypeDialog { return n; } + static final String KEEP = "(keep current fields)"; + + /** Parameter names (from the object schema) the script may use for the chosen fields type. */ + private static java.util.Map names(String fieldsType) { + return StratEdits.paramNames(fieldsType); + } + private static void open( EditorContext ctx, String title, @@ -183,14 +190,19 @@ final class TypeDialog { JTextField nameField = new JTextField(name, 18); JTextField entryField = new JTextField(entry, 14); JComboBox from = new JComboBox<>(); - ctx.scene().catalog().types().forEach(t -> from.addItem(t.name())); - from.setSelectedItem(fieldsFrom); boolean editing = editIndex >= 0; String oldName = editing ? name : null; if (editing) { - from.setEnabled(false); - from.setToolTipText("An edited type keeps its type fields and parameters"); + from.addItem(KEEP); + from.setToolTipText("New objects of the type start with these type fields and parameters;" + + " objects already placed keep theirs"); } + ctx.scene().catalog().types().forEach(t -> { + if (!t.name().equals(oldName)) { + from.addItem(t.name()); + } + }); + from.setSelectedItem(editing ? KEEP : fieldsFrom); String script = StratCompiler.embeddedSource(source); JTextArea text = new JTextArea(script != null ? script : source, 30, 90); JComboBox lang = new JComboBox<>(new String[] {"Assembly", "Script"}); @@ -206,8 +218,9 @@ final class TypeDialog { top.add(entryField); top.add(new JLabel("Language")); top.add(lang); - top.add(new JLabel("Type fields / parameters from")); - top.add(from); + JPanel fieldsRow = new JPanel(new FlowLayout(FlowLayout.LEADING)); + fieldsRow.add(new JLabel("Type fields / parameters from")); + fieldsRow.add(from); JButton check = new JButton("Check"); JButton create = new JButton(editing ? "Apply" : "Create type"); JButton cancel = new JButton("Cancel"); @@ -228,7 +241,10 @@ final class TypeDialog { : "") + "Syntax: notes/strat-language.md (manual chapter “Strat scripts”). The new code is appended to the level and verified by disassembling it again.")); JPanel north = new JPanel(new BorderLayout()); - north.add(top, BorderLayout.NORTH); + JPanel rows = new JPanel(new java.awt.GridLayout(2, 1)); + rows.add(top); + rows.add(fieldsRow); + north.add(rows, BorderLayout.NORTH); north.add(help, BorderLayout.SOUTH); d.getContentPane().add(north, BorderLayout.NORTH); d.getContentPane().add(new JScrollPane(text), BorderLayout.CENTER); @@ -243,7 +259,8 @@ final class TypeDialog { String cur = text.getText(); if (to == 0) { try { - text.setText(StratCompiler.compile(cur)); + String ft = (String) from.getSelectedItem(); + text.setText(StratCompiler.compile(cur, names(KEEP.equals(ft) ? fieldsFrom : ft))); } catch (StratCompiler.CompileException ex) { result.setText("⚠ " + ex.getMessage() + " – fix the script before switching to assembly"); highlight(text, ex.line); @@ -281,9 +298,11 @@ final class TypeDialog { return; } String src = text.getText(); + String chosen = (String) from.getSelectedItem(); + String fieldsType = KEEP.equals(chosen) ? fieldsFrom : chosen; if (lang.getSelectedIndex() == 1) { try { - src = StratCompiler.compile(src); + src = StratCompiler.compile(src, names(fieldsType)); } catch (StratCompiler.CompileException e) { result.setText("⚠ " + e.getMessage()); highlight(text, e.line); @@ -294,12 +313,18 @@ final class TypeDialog { entryField.setText(first); } } - StratCatalog.Type ft = s.catalog().type((String) from.getSelectedItem()); + StratCatalog.Type ft = s.catalog().type(chosen); if (editing) { StratEdits.CustomType old = StratEdits.records(ctx.document().project()).types().get(editIndex); + boolean keep = KEEP.equals(chosen) || ft == null; StratEdits.CustomType t = new StratEdits.CustomType( - n, old.basedOn(), entryField.getText().trim(), src, old.proto()); + n, + old.basedOn(), + entryField.getText().trim(), + src, + keep ? old.proto() : ft.variant(0), + keep ? old.fieldsFrom() : chosen); List all = new java.util.ArrayList<>( StratEdits.records(ctx.document().project()).types()); all.set(editIndex, t); @@ -330,7 +355,7 @@ final class TypeDialog { return; } StratEdits.CustomType t = new StratEdits.CustomType( - n, clone ? fieldsFrom : null, entryField.getText().trim(), src, ft.variant(0)); + n, clone ? fieldsFrom : null, entryField.getText().trim(), src, ft.variant(0), chosen); try { StratEdits.Built b = StratEdits.build(s, t); if (!b.problems().isEmpty()) { diff --git a/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeEdits.java b/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeEdits.java index cea072a..24e7a6c 100644 --- a/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeEdits.java +++ b/src/main/java/com/eliasmueller/llamamod/editor/tools/strats/TypeEdits.java @@ -44,16 +44,26 @@ final class TypeEdits { static Command create(Project p, StratEdits.CustomType t) { List before = StratEdits.records(p).types(); List after = new ArrayList<>(before); - after.add(t); + after.add(t.withSource(StratEdits.symbolic(p.scene(), t.source()))); return new SetTypes( p, "Create object type " + t.name(), before, after, identity(before.size()), identity(before.size())); } - /** Replaces custom type k by t (objects of the type stay and use the new code). */ + /** + * Replaces custom type k by t (objects of the type stay and use the new code); a new name is + * also changed in the unit:Name references of the other types. + */ static Command edit(Project p, int k, StratEdits.CustomType t) { List before = StratEdits.records(p).types(); List after = new ArrayList<>(before); - after.set(k, t); + after.set(k, t.withSource(StratEdits.symbolic(p.scene(), t.source()))); + String oldName = before.get(k).name(); + if (!oldName.equals(t.name())) { + for (int i = 0; i < after.size(); i++) { + StratEdits.CustomType x = after.get(i); + after.set(i, x.withSource(StratEdits.renameUnitRefs(x.source(), oldName, t.name()))); + } + } return new SetTypes( p, "Edit object type " + t.name(), before, after, identity(before.size()), identity(before.size())); } diff --git a/src/main/java/com/eliasmueller/llamamod/format/strat/OpTable.java b/src/main/java/com/eliasmueller/llamamod/format/strat/OpTable.java index 405685b..e97cfa9 100644 --- a/src/main/java/com/eliasmueller/llamamod/format/strat/OpTable.java +++ b/src/main/java/com/eliasmueller/llamamod/format/strat/OpTable.java @@ -34,6 +34,9 @@ public final class OpTable { private final Op[] ops = new Op[StratOps.COUNT]; private final Map byName = new HashMap<>(); + /** Former mnemonics (lower case) that still assemble (resource op-aliases.tsv). */ + private final Map aliases = new HashMap<>(); + private final Map props = new HashMap<>(); private final Map propsByName = new HashMap<>(); private final Map globals = new HashMap<>(); @@ -64,6 +67,14 @@ public final class OpTable { byName.put(name, ops[i]); } } + for (String[] f : rows("op-aliases.tsv")) { + Op op = f.length < 2 ? null : byName.get(lc(f[1].trim())); + String old = lc(f[0].trim()); + if (op != null && !old.isEmpty() && !byName.containsKey(old)) { + byName.put(old, op); + aliases.put(old, op); + } + } named("props.tsv", props, propsByName, true); named("globals.tsv", globals, globalsByName, false); } @@ -128,7 +139,12 @@ public final class OpTable { return ops[code]; } - /** Opcode by mnemonic (case-insensitive) or "op_XX", or null. */ + /** The opcode a former mnemonic now names, or null if name is not an old alias. */ + public Op alias(String name) { + return aliases.get(lc(name)); + } + + /** Opcode by mnemonic (case-insensitive, current or former name) or "op_XX", or null. */ public Op byName(String name) { Op o = byName.get(lc(name)); if (o == null && lc(name).startsWith("op_")) { diff --git a/src/main/java/com/eliasmueller/llamamod/format/strat/StratAssembler.java b/src/main/java/com/eliasmueller/llamamod/format/strat/StratAssembler.java index 0a74d9e..dbabd6a 100644 --- a/src/main/java/com/eliasmueller/llamamod/format/strat/StratAssembler.java +++ b/src/main/java/com/eliasmueller/llamamod/format/strat/StratAssembler.java @@ -16,9 +16,19 @@ public final class StratAssembler { * unit's first word; models/anims/units = STPC offsets of model headers, animation sets, unit * starts. */ - public record Layout(int base, List models, List anims, List units) { + public record Layout( + int base, List models, List anims, List units, Map unitNames) { + public Layout(int base, List models, List anims, List units) { + this(base, models, anims, units, Map.of()); + } + public Layout withBase(int b) { - return new Layout(b, models, anims, units); + return new Layout(b, models, anims, units, unitNames); + } + + /** The same layout where unit:Name resolves to the unit with that index (type names). */ + public Layout withUnitNames(Map names) { + return new Layout(base, models, anims, units, Map.copyOf(names)); } } @@ -662,7 +672,17 @@ public final class StratAssembler { add = d == null ? 0 : d; r = r.substring(0, plus); } - Integer idx = number(ln, r); + String key = r.trim(); + Integer idx = kind.equals("unit") && key.matches("[A-Za-z_]\\w*") + ? l.unitNames().get(key) + : null; + if (idx == null && kind.equals("unit") && key.matches("[A-Za-z_]\\w*")) { + err(ln, "unknown unit name '" + key + "' (custom object types are named, others use unit:N)"); + return null; + } + if (idx == null) { + idx = number(ln, r); + } if (idx == null) { return null; } diff --git a/src/main/java/com/eliasmueller/llamamod/format/strat/StratCompiler.java b/src/main/java/com/eliasmueller/llamamod/format/strat/StratCompiler.java index 73bc975..9aeb4a8 100644 --- a/src/main/java/com/eliasmueller/llamamod/format/strat/StratCompiler.java +++ b/src/main/java/com/eliasmueller/llamamod/format/strat/StratCompiler.java @@ -10,8 +10,9 @@ import java.util.Map; /** * Compiler for strat scripts, a small structured language for NEW behaviour (notes/strat-language.md, * "Script language"): statements and expressions in the style of the script view, compiled to the - * assembly of {@link StratAssembler}. Literals mean the same as in the assembly (10.0 = ten, 10 = - * ten raw 1/4096 units, 90deg). + * assembly of {@link StratAssembler}. Numbers: a plain integer is in game units ({@code 10} = 10.0), + * {@code 10r} and hex are raw words, {@code 1.5} and {@code 90deg} as in the assembly. Scripts + * compiled before this rule ({@code use rawNumbers}) read plain integers as raw words. */ public final class StratCompiler { /** A compile error at a 1-based source line. */ @@ -27,8 +28,24 @@ public final class StratCompiler { /** Prefix of the comment lines that carry the script source inside the generated assembly. */ public static final String SOURCE_PREFIX = ";| "; + /** Marker line behind the embedded source of scripts with unit numbers (language version 2). */ + static final String VERSION_MARK = "; script language 2"; + + /** Statement that keeps the old number rule (plain integers are raw words). */ + public static final String RAW_NUMBERS = "use rawNumbers"; + private record Tok(String kind, String text, int line) {} + /** + * Expression tree. num: value (raw word) and text (assembly literal); ins: one instruction that + * pushes a value; bin/neg/not: operator over kids; call: instruction text after the kids. + */ + private record Node(String kind, String text, int value, List kids, int line) { + boolean isNum() { + return kind.equals("num"); + } + } + private static final Map PREC = Map.ofEntries( Map.entry("||", 1), Map.entry("&&", 2), @@ -78,43 +95,78 @@ public final class StratCompiler { private static final List REFS = List.of("model", "anim", "unit", "sound", "tex", "text"); + /** Named event types for {@code on name { … }}. */ + private static final Map EVENTS = Map.of("touched", 4); + private final OpTable ops = OpTable.get(); private final List toks; private int p; - private final StringBuilder out = new StringBuilder(); + private StringBuilder out = new StringBuilder(); + /** Event handler code of the current strat/sub, placed behind its code. */ + private StringBuilder deferred = new StringBuilder(); + /** Event entries and switch tables, placed at the start of the unit. */ + private final StringBuilder tables = new StringBuilder(); + private final Map aliases = new HashMap<>(); private int labels; - /** Enclosing loops: {break label, continue label}. */ - private final Deque loops = new ArrayDeque<>(); + private int eventSlot; + private boolean rawNumbers; + /** Enclosing loops/switches: {break label, continue label (null = none)}. */ + private Deque loops = new ArrayDeque<>(); - private StratCompiler(String src) { + private StratCompiler(String src, Map names) { toks = lex(src); + names.forEach((n, v) -> { + if (v.matches("v\\d+") && n.matches("[A-Za-z_]\\w*")) { + aliases.put(n, v); + } + }); } /** Compiles a script to assembly text; the script is kept as {@link #SOURCE_PREFIX} comments. */ public static String compile(String src) { - StratCompiler c = new StratCompiler(src); - for (String l : src.split("\n", -1)) { - c.out.append(SOURCE_PREFIX).append(l.stripTrailing()).append('\n'); - } - c.program(); - return c.out.toString(); + return compile(src, Map.of()); } - /** The script embedded in compiled assembly, or null if the text is not compiler output. */ + /** + * Compiles a script; names = predefined variable names (parameter names of the object schema → + * "vN"), overridden by the script's own aliases. + */ + public static String compile(String src, Map names) { + StratCompiler c = new StratCompiler(src, names); + StringBuilder b = new StringBuilder(); + for (String l : src.split("\n", -1)) { + b.append(SOURCE_PREFIX).append(l.stripTrailing()).append('\n'); + } + b.append(VERSION_MARK).append('\n'); + c.program(); + // tables first: data behind a terminating instruction would be tried as dead code + return b.append(c.tables).append(c.out).toString(); + } + + /** + * The script embedded in compiled assembly, or null if the text is not compiler output. Scripts + * compiled with the old number rule get a {@value #RAW_NUMBERS} line, so they mean the same. + */ public static String embeddedSource(String asm) { if (!asm.startsWith(SOURCE_PREFIX)) { return null; } StringBuilder b = new StringBuilder(); + boolean v2 = false; for (String l : asm.split("\n", -1)) { if (!l.startsWith(SOURCE_PREFIX.trim())) { + v2 = l.equals(VERSION_MARK); break; } b.append(l.length() >= SOURCE_PREFIX.length() ? l.substring(SOURCE_PREFIX.length()) : "") .append('\n'); } - return b.toString().stripTrailing() + "\n"; + String src = b.toString().stripTrailing() + "\n"; + if (!v2 && !src.contains(RAW_NUMBERS)) { + src = RAW_NUMBERS + " // written when a plain 10 meant 10 raw units (1/4096)\n" + src; + } + return src; } /** Entry label of the first strat of a script (null if none). */ @@ -165,6 +217,10 @@ public final class StratCompiler { } if (s.startsWith("deg", j)) { j += 3; + } else if (j < s.length() + && s.charAt(j) == 'r' + && (j + 1 >= s.length() || !Character.isLetterOrDigit(s.charAt(j + 1)))) { + j++; } } out.add(new Tok("num", s.substring(i, j), line)); @@ -215,10 +271,6 @@ public final class StratCompiler { return peek().text.equals(text) && !peek().kind.equals("str"); } - private boolean at1(String text) { - return peek(1).text.equals(text) && !peek(1).kind.equals("str"); - } - private boolean accept(String text) { if (at(text)) { p++; @@ -270,10 +322,12 @@ public final class StratCompiler { out.append(" .string \"").append(name).append("\"\n"); place(name); emit("debugName \"" + name + "\""); + eventSlot = 0; boolean ends = block(); if (!ends) { emit("end"); } + flushDeferred(); } else if (accept("sub")) { String name = ident(); place(name); @@ -283,14 +337,20 @@ public final class StratCompiler { if (!ends) { emit("return"); } - } else if (at("alias")) { + flushDeferred(); + } else if (at("alias") || at("use")) { statement(); } else { - throw err("expected 'strat', 'sub' or 'alias' but found " + describe(peek())); + throw err("expected 'strat', 'sub', 'alias' or 'use' but found " + describe(peek())); } } } + private void flushDeferred() { + out.append(deferred); + deferred = new StringBuilder(); + } + /** Parses { statements }; returns whether control never falls out of its end. */ private boolean block() { expect("{"); @@ -319,7 +379,7 @@ public final class StratCompiler { String top = label(), done = label(); place(top); expect("("); - cond(done); + jumpIfFalse(expr(), done); expect(")"); loops.push(new String[] {done, top}); loopBody(top); @@ -347,18 +407,35 @@ public final class StratCompiler { expect("while"); expect("("); place(check); - expr(); + jumpIfTrue(expr(), top); expect(")"); - emit("jnz " + top); place(done); return false; } + case "switch" -> { + next(); + switchStatement(); + return false; + } + case "on" -> { + next(); + onEvent(t); + return false; + } case "break", "continue" -> { next(); - if (loops.isEmpty()) { - throw new CompileException(t.line, t.text + " outside a loop"); + boolean brk = t.text.equals("break"); + String target = null; + for (String[] l : loops) { + target = brk ? l[0] : l[1]; + if (target != null) { + break; + } } - emit("jmp " + loops.peek()[t.text.equals("break") ? 0 : 1]); + if (target == null) { + throw new CompileException(t.line, t.text + " outside a " + (brk ? "loop or switch" : "loop")); + } + emit("jmp " + target); return true; } case "yield" -> { @@ -399,6 +476,15 @@ public final class StratCompiler { out.append(" .alias ").append(n).append(" = ").append(v).append('\n'); return false; } + case "use" -> { + next(); + String what = ident(); + if (!what.equals("rawNumbers")) { + throw new CompileException(t.line, "unknown option " + what + " (use rawNumbers)"); + } + rawNumbers = true; + return false; + } default -> { // fall through to assignments and calls } @@ -407,12 +493,13 @@ public final class StratCompiler { throw err("expected a statement but found " + describe(t)); } if (isOp(t.text) && !isLvalueStart()) { - String mn = callExpr(); - OpTable.Op op = ops.byName(mn); + Node call = callExpr(); + value(call); + OpTable.Op op = ops.byName(call.text.split(" ")[0]); if (op.pushes() == 1) { emit("pop"); } - return mn.equalsIgnoreCase("end") || mn.equalsIgnoreCase("remove"); + return op.name().equalsIgnoreCase("end") || op.name().equalsIgnoreCase("remove"); } assignment(); return false; @@ -421,7 +508,7 @@ public final class StratCompiler { private void ifRest() { String other = label(); expect("("); - cond(other); + jumpIfFalse(expr(), other); expect(")"); block(); if (accept("else")) { @@ -439,29 +526,157 @@ public final class StratCompiler { } } - /** Condition: jumps to falseTarget when it is 0. */ - private void cond(String falseTarget) { - expr(); - emit("jz " + falseTarget); - } - /** Loop body; a trailing yield becomes the yielding back edge. */ private void loopBody(String top) { expect("{"); - int mark = -1; + boolean yieldEdge = false; while (!at("}")) { if (peek().kind.equals("eof")) { throw err("missing '}'"); } - mark = at("yield") && peek(1).text.equals("}") ? out.length() : -1; - if (mark >= 0) { + if (at("yield") && peek(1).text.equals("}")) { next(); + yieldEdge = true; break; } statement(); } expect("}"); - emit((mark >= 0 ? "jmpYield " : "jmp ") + top); + emit((yieldEdge ? "jmpYield " : "jmp ") + top); + } + + /** + * switch (e) { case c: … default: … }: C rules (cases fall through, break leaves the switch). + * Compiles to the VM's switch table (placed behind the strat) and a jump to default or the end. + */ + private void switchStatement() { + Tok t = peek(); + expect("("); + Node v = expr(); + expect(")"); + expect("{"); + String table = "sw_" + (++labels), done = label(); + value(v); + emit("switch " + table); + int jmpAt = out.length(); + emit("jmp " + done); + List cases = new ArrayList<>(); + String dflt = null; + String cont = loops.isEmpty() ? null : loops.peek()[1]; + loops.push(new String[] {done, cont}); + while (!at("}")) { + if (peek().kind.equals("eof")) { + throw err("missing '}'"); + } + if (accept("case")) { + Tok ct = peek(); + Node c = expr(); + if (!c.isNum()) { + throw new CompileException(ct.line, "a case value must be a constant"); + } + expect(":"); + String l = label(); + for (String[] x : cases) { + if (Integer.parseInt(x[0]) == c.value) { + throw new CompileException(ct.line, "duplicate case " + c.text); + } + } + cases.add(new String[] {Integer.toString(c.value), l}); + place(l); + } else if (accept("default")) { + expect(":"); + if (dflt != null) { + throw new CompileException(t.line, "two default labels"); + } + dflt = label(); + place(dflt); + } else { + statement(); + } + } + expect("}"); + loops.pop(); + place(done); + if (dflt != null) { + out.replace(jmpAt, jmpAt + (" jmp " + done + "\n").length(), " jmp " + dflt + "\n"); + } + if (cases.isEmpty()) { + throw new CompileException(t.line, "a switch needs at least one case"); + } + tables.append(table).append(":\n"); + tables.append(" .switch ").append(cases.size()).append('\n'); + for (String[] c : cases) { + int x = Integer.parseInt(c[0]); + boolean small = x >= Short.MIN_VALUE && x <= Short.MAX_VALUE; + tables.append(" .case ") + .append(small ? "" : "imm ") + .append(Num.literal(x)) + .append(", ") + .append(c[1]) + .append('\n'); + } + } + + /** + * on touched { … } / on event(type[, param]) [slot n] { … }: installs an event handler here + * (onEvent); the handler body is placed behind the strat and ends with return. + */ + private void onEvent(Tok t) { + String type, param = "0"; + if (accept("event")) { + expect("("); + type = rawWord(); + if (accept(",")) { + param = rawWord(); + } + expect(")"); + } else { + String n = ident(); + Integer k = EVENTS.get(n); + if (k == null) { + throw new CompileException(t.line, "unknown event " + n + " (touched, or event(type, param))"); + } + type = Integer.toString(k); + } + int slot = eventSlot; + if (accept("slot")) { + slot = Num.parse(rawWord()); + } + eventSlot = Math.max(eventSlot, slot + 1); + String entry = "ev_" + (++labels), handler = "on_" + labels; + emit("onEvent " + entry + ", " + slot); + // the handler: compiled into its own buffer with its own loop context + StringBuilder saved = out; + Deque savedLoops = loops; + out = new StringBuilder(); + loops = new ArrayDeque<>(); + place(handler); + if (!block()) { + emit("return"); + } + StringBuilder body = out; + out = saved; + loops = savedLoops; + tables.append(entry).append(":\n"); + tables.append(" .event ") + .append(type) + .append(", ") + .append(param) + .append(", ") + .append(handler) + .append('\n'); + deferred.append(body); + } + + /** A raw word operand (event type/param, slot): number as in the assembly. */ + private String rawWord() { + boolean neg = accept("-"); + Tok t = next(); + String s = (neg ? "-" : "") + (t.text.endsWith("r") ? t.text.substring(0, t.text.length() - 1) : t.text); + if (!t.kind.equals("num") || Num.parse(s) == null) { + throw new CompileException(t.line, "expected a number but found " + describe(t)); + } + return s; } private boolean isOp(String name) { @@ -505,7 +720,7 @@ public final class StratCompiler { } throw new CompileException( t.line, - "unknown name " + a + " (variables are vN or aliases, globals gN, " + "unknown name " + a + " (variables are vN, aliases or parameter names, globals gN, " + "properties self.name, player.name, …)"); } @@ -515,18 +730,17 @@ public final class StratCompiler { String op = next().text; switch (op) { case "=" -> { - expr(); + value(expr()); emit(pl.pop); } case "+=", "-=", "*=", "/=" -> { - boolean one = at("1.0") && (peek(1).line != peek().line || at1("}")); - if ((op.equals("+=") || op.equals("-=")) && pl.addr != null && one) { - next(); + Node e = expr(); + if ((op.equals("+=") || op.equals("-=")) && pl.addr != null && e.isNum() && e.value == Num.ONE) { emit(pl.addr); emit(op.equals("+=") ? "inc" : "dec"); } else { emit(pl.push); - expr(); + value(e); emit(BINOP.get(op.substring(0, 1))); emit(pl.pop); } @@ -535,45 +749,44 @@ public final class StratCompiler { } } - // ------------------------------------------------------------------ expressions + // ------------------------------------------------------------------ expressions (parse) - private void expr() { - binary(1); + private Node expr() { + return binary(1); } - private void binary(int min) { - unary(); + private Node binary(int min) { + Node l = unary(); while (peek().kind.equals("op") && PREC.containsKey(peek().text) && PREC.get(peek().text) >= min) { - String op = next().text; - binary(PREC.get(op) + 1); - emit(BINOP.get(op)); + Tok t = next(); + Node r = binary(PREC.get(t.text) + 1); + l = fold(new Node("bin", t.text, 0, List.of(l, r), t.line)); } + return l; } - private void unary() { + private Node unary() { + Tok t = peek(); if (accept("-")) { - if (peek().kind.equals("num")) { - number("-" + next().text); - return; - } - unary(); - emit("neg"); - } else if (accept("!")) { - unary(); - emit("not"); - } else { - primary(); + return fold(new Node("neg", "-", 0, List.of(unary()), t.line)); } + if (accept("!")) { + return fold(new Node("not", "!", 0, List.of(unary()), t.line)); + } + return primary(); } - private void primary() { + private Node primary() { Tok t = peek(); if (t.kind.equals("num")) { - number(next().text); - } else if (accept("(")) { - expr(); + return number(next()); + } + if (accept("(")) { + Node e = expr(); expect(")"); - } else if (t.kind.equals("id") && REFS.contains(t.text) && peek(1).text.equals(":")) { + return e; + } + if (t.kind.equals("id") && REFS.contains(t.text) && peek(1).text.equals(":")) { next(); next(); StringBuilder ref = new StringBuilder(t.text + ":" + next().text); @@ -581,34 +794,46 @@ public final class StratCompiler { next(); ref.append('+').append(next().text); } - switch (t.text) { - case "sound" -> emit("soundAddress " + ref); - case "tex" -> emit("push " + ref); + return switch (t.text) { + case "sound" -> new Node("ins", "soundAddress " + ref, 0, List.of(), t.line); + case "tex" -> new Node("ins", "push " + ref, 0, List.of(), t.line); case "text" -> throw new CompileException(t.line, "text:N is an inline operand: topSay()"); - default -> emit("address " + ref); - } - } else if (t.kind.equals("id") && isOp(t.text) && !isLvalueStart()) { - String mn = callExpr(); - if (ops.byName(mn).pushes() != 1) { - throw new CompileException(t.line, mn + " gives no value"); - } - } else if (t.kind.equals("id")) { - emit(place().push); - } else { - throw err("expected a value but found " + describe(t)); + default -> new Node("ins", "address " + ref, 0, List.of(), t.line); + }; } + if (t.kind.equals("id") && isOp(t.text) && !isLvalueStart()) { + Node c = callExpr(); + if (ops.byName(c.text.split(" ")[0]).pushes() != 1) { + throw new CompileException(t.line, c.text.split(" ")[0] + " gives no value"); + } + return c; + } + if (t.kind.equals("id")) { + return new Node("ins", place().push, 0, List.of(), t.line); + } + throw err("expected a value but found " + describe(t)); } - private void number(String text) { + /** A number token: plain integers are game units (×4096) unless rawNumbers; "r" = raw. */ + private Node number(Tok t) { + String s = t.text; + String text; + if (s.endsWith("r")) { + text = s.substring(0, s.length() - 1); + } else if (rawNumbers || s.startsWith("0x") || s.startsWith("0X") || s.contains(".") || s.endsWith("deg")) { + text = s; + } else { + text = s + ".0"; + } Integer v = Num.parse(text); if (v == null) { - throw err("bad number " + text); + throw new CompileException(t.line, "bad number " + s); } - emit((v >= Short.MIN_VALUE && v <= Short.MAX_VALUE ? "pushShort " : "push ") + text); + return new Node("num", text, v, List.of(), t.line); } - /** op(args): pushes the arguments and emits the opcode; returns its mnemonic. */ - private String callExpr() { + /** op(args): a call node; the argument count must match the opcode's pops. */ + private Node callExpr() { Tok t = peek(); String mn = ident(); OpTable.Op op = ops.byName(mn); @@ -625,28 +850,150 @@ public final class StratCompiler { inline.add(cur.toString()); cur.setLength(0); } else { - cur.append(x.text); + cur.append( + x.kind.equals("num") && x.text.endsWith("r") + ? x.text.substring(0, x.text.length() - 1) + : x.text); } } expect(">"); inline.add(cur.toString()); } - int args = 0; + List args = new ArrayList<>(); if (accept("(")) { while (!at(")")) { - expr(); - args++; + args.add(expr()); if (!accept(",")) { break; } } expect(")"); } - if (op.pops() >= 0 && args != op.pops()) { + if (op.pops() >= 0 && args.size() != op.pops()) { throw new CompileException( - t.line, mn + " takes " + op.pops() + " value" + (op.pops() == 1 ? "" : "s") + ", got " + args); + t.line, + mn + " takes " + op.pops() + " value" + (op.pops() == 1 ? "" : "s") + ", got " + args.size()); + } + return new Node("call", mn + (inline.isEmpty() ? "" : " " + String.join(", ", inline)), 0, args, t.line); + } + + // ------------------------------------------------------------------ constant folding + + /** Folds operators over constants with the VM's integer semantics (20.12 mul/div). */ + private static Node fold(Node n) { + if (!n.kids.stream().allMatch(Node::isNum)) { + return n; + } + int a = n.kids.get(0).value; + Integer v = + switch (n.kind) { + case "neg" -> -a; + case "not" -> a == 0 ? 1 : 0; + default -> { + int b = n.kids.get(1).value; + yield switch (n.text) { + case "+" -> a + b; + case "-" -> a - b; + case "*" -> (int) (((long) a * b) >> 12); + case "/" -> b == 0 ? null : ((a << 8) / b) << 4; + case "&" -> a & b; + case "|", "||" -> a | b; + case "&&" -> a != 0 && b != 0 ? 1 : 0; + case "==" -> a == b ? 1 : 0; + case "!=" -> a != b ? 1 : 0; + case "<" -> a < b ? 1 : 0; + case ">" -> a > b ? 1 : 0; + case "<=" -> a <= b ? 1 : 0; + case ">=" -> a >= b ? 1 : 0; + case "<<" -> a << (b >> 12); + case ">>" -> a >> (b >> 12); + default -> null; + }; + } + }; + if (v == null) { + return n; + } + String text = + n.kind.equals("neg") && !n.kids.get(0).text.startsWith("-") ? "-" + n.kids.get(0).text : Num.literal(v); + return new Node("num", text, v, List.of(), n.line); + } + + // ------------------------------------------------------------------ code generation + + /** Code that pushes the value of n (&& and || as the and/or opcodes: both sides evaluated). */ + private void value(Node n) { + switch (n.kind) { + case "num" -> emit( + (n.value >= Short.MIN_VALUE && n.value <= Short.MAX_VALUE ? "pushShort " : "push ") + n.text); + case "ins" -> emit(n.text); + case "neg" -> { + value(n.kids.get(0)); + emit("neg"); + } + case "not" -> { + value(n.kids.get(0)); + emit("not"); + } + case "bin" -> { + value(n.kids.get(0)); + value(n.kids.get(1)); + emit(BINOP.get(n.text)); + } + case "call" -> { + n.kids.forEach(this::value); + emit(n.text); + } + default -> throw new IllegalStateException(n.kind); + } + } + + /** Jumps to target when n is false (0), falls through otherwise; && and || short-circuit. */ + private void jumpIfFalse(Node n, String target) { + if (n.isNum()) { + if (n.value == 0) { + emit("jmp " + target); + } + } else if (n.kind.equals("not") && isLogic(n.kids.get(0))) { + jumpIfTrue(n.kids.get(0), target); + } else if (n.kind.equals("bin") && n.text.equals("&&")) { + jumpIfFalse(n.kids.get(0), target); + jumpIfFalse(n.kids.get(1), target); + } else if (n.kind.equals("bin") && n.text.equals("||")) { + String ok = label(); + jumpIfTrue(n.kids.get(0), ok); + jumpIfFalse(n.kids.get(1), target); + place(ok); + } else { + value(n); + emit("jz " + target); + } + } + + /** && / || / ! (whose negation is folded into the jumps); a plain !x stays "not" + jump. */ + private static boolean isLogic(Node n) { + return n.kind.equals("not") || n.kind.equals("bin") && (n.text.equals("&&") || n.text.equals("||")); + } + + /** Jumps to target when n is true (non-zero), falls through otherwise. */ + private void jumpIfTrue(Node n, String target) { + if (n.isNum()) { + if (n.value != 0) { + emit("jmp " + target); + } + } else if (n.kind.equals("not") && isLogic(n.kids.get(0))) { + jumpIfFalse(n.kids.get(0), target); + } else if (n.kind.equals("bin") && n.text.equals("||")) { + jumpIfTrue(n.kids.get(0), target); + jumpIfTrue(n.kids.get(1), target); + } else if (n.kind.equals("bin") && n.text.equals("&&")) { + String no = label(); + jumpIfFalse(n.kids.get(0), no); + jumpIfTrue(n.kids.get(1), target); + place(no); + } else { + value(n); + emit("jnz " + target); } - emit(mn + (inline.isEmpty() ? "" : " " + String.join(", ", inline))); - return mn; } } diff --git a/src/main/java/com/eliasmueller/llamamod/format/strat/StratListing.java b/src/main/java/com/eliasmueller/llamamod/format/strat/StratListing.java index 5a31055..0fa5f05 100644 --- a/src/main/java/com/eliasmueller/llamamod/format/strat/StratListing.java +++ b/src/main/java/com/eliasmueller/llamamod/format/strat/StratListing.java @@ -86,6 +86,11 @@ public final class StratListing { return null; } + /** Symbolic name of another unit for "unit:Name" operands (null = by index). */ + default String unitName(int unit) { + return null; + } + Names NONE = new Names() {}; } @@ -323,6 +328,10 @@ public final class StratListing { /** Reference text for an absolute STPC offset (operand of pushAddr). */ String addrRef(int v) { + return addrRef(v, Names.NONE); + } + + String addrRef(int v, Names names) { if (in(v) && labels.containsKey(v)) { return "@" + labels.get(v); } @@ -336,7 +345,9 @@ public final class StratListing { } int u = img.unitOf(v); if (u >= 0 && u != unit) { - return "unit:" + u + plus(v - img.units.get(u).start()); + String n = names.unitName(u); + return "unit:" + (n != null ? n : Integer.toString(u)) + + plus(v - img.units.get(u).start()); } return Num.integer(v); } @@ -673,7 +684,7 @@ public final class StratListing { } case StratOps.PUSH_ADDR -> { int v = w(o + 4); - args.add(addrRef(v)); + args.add(addrRef(v, names)); comment = addrComment(v, names); } case StratOps.PUSH_SOUND -> { diff --git a/src/main/java/com/eliasmueller/llamamod/format/strat/StratPseudo.java b/src/main/java/com/eliasmueller/llamamod/format/strat/StratPseudo.java index f3b9f8e..977cef7 100644 --- a/src/main/java/com/eliasmueller/llamamod/format/strat/StratPseudo.java +++ b/src/main/java/com/eliasmueller/llamamod/format/strat/StratPseudo.java @@ -183,6 +183,7 @@ public final class StratPseudo { } } Map> tables = switchTables(); + findChains(); // candidate blocks List cand = new ArrayList<>(); Map elseOf = new HashMap<>(); @@ -199,7 +200,7 @@ public final class StratPseudo { continue; } Integer t = labelIdx.get(operand(l)); - if (t == null) { + if (t == null || chainMember.contains(i)) { continue; } if (condJump(op) && t > i && clean(i, t)) { @@ -292,6 +293,9 @@ public final class StratPseudo { } opensAt.values().forEach(l -> l.sort((a, b) -> Integer.compare(b.close, a.close))); resolveJumps(accepted, consumed); + for (int m : chainMember) { + consumed.merge(ls.get(target(m)).label(), 1, Integer::sum); + } Map refs = new HashMap<>(); for (StratListing.Line l : ls) { if (l.kind() == StratListing.Kind.INSTR || l.kind() == StratListing.Kind.DATA) { @@ -342,7 +346,8 @@ public final class StratPseudo { out(l.offset(), l.label() + ":"); } for (Block b : opensAt.getOrDefault(i, List.of())) { - out(-1, b.kind.equals("do") ? "do {" : "loop {"); + String name = loopNames.get(b.open); + out(-1, (name == null ? "" : name + ": ") + (b.kind.equals("do") ? "do {" : "loop {")); depth++; } } @@ -356,6 +361,7 @@ public final class StratPseudo { flush(); whileLoops(); elseIfChains(); + andChains(); } private final Map caseOwner = new HashMap<>(); @@ -375,6 +381,8 @@ public final class StratPseudo { } if (ok && a.kind.equals("if") && elseAccepted.contains(a.open)) { ok = nests(b.open, end, a.open, a.close) && nests(b.open, end, a.close, ae); + // a jump from the then-part to the else label enters the else part: not a nested if + ok &= !(b.kind.equals("if") && b.close == a.close && b.open > a.open); } if (!ok) { return false; @@ -442,19 +450,22 @@ public final class StratPseudo { // the end: the default target when it lies behind every case, else the first label after // the last case's code that a "jmp" in a case body targets int endIdx = d; - if (d < e) { - endIdx = -1; - for (int i = s + 2; i < ls.size() && endIdx < 0; i++) { - if (ls.get(i).kind() == StratListing.Kind.INSTR && ls.get(i).op() == 0x16) { - Integer t = target(i); - if (t != null && t > e) { - endIdx = t; - } + // a default part behind the cases (compiled switches): a case body jumps over it + int last = d < e ? e : d; + int found = -1; + for (int i = s + 2; i < ls.size() && i < (d < e ? ls.size() : d) && found < 0; i++) { + if (ls.get(i).kind() == StratListing.Kind.INSTR && ls.get(i).op() == 0x16) { + Integer t = target(i); + if (t != null && t > last) { + found = t; } } - if (endIdx < 0) { - return; - } + } + if (d < e && found < 0) { + return; + } + if (found >= 0) { + endIdx = found; cs.add(new int[] {d, -1}); } if (!clean(s, endIdx)) { @@ -487,7 +498,8 @@ public final class StratPseudo { || ifAt.containsKey(i) || loopEnd.containsKey(i) || elseJumps.contains(i) - || silentJumps.contains(i)) { + || silentJumps.contains(i) + || chainMember.contains(i)) { continue; } Integer t = target(i); @@ -503,15 +515,20 @@ public final class StratPseudo { in = b; } } - if (in == null) { - continue; - } - int endAt = in.kind.equals("switch") ? in.close : in.close + 1; String as = null; - if (anchor(t) == anchor(endAt)) { - as = "break"; - } else if (in.isLoop() && anchor(t) == anchor(in.open)) { - as = "continue"; + if (in != null) { + int endAt = in.kind.equals("switch") ? in.close : in.close + 1; + if (anchor(t) == anchor(endAt)) { + as = "break"; + } else if (in.isLoop() && anchor(t) == anchor(in.open)) { + as = "continue"; + } + } + if (as == null) { + as = terminal(anchor(t)); + } + if (as == null) { + as = labeledJump(accepted, in, i, t); } if (as != null) { jumpAs.put(i, as); @@ -520,24 +537,306 @@ public final class StratPseudo { } } + // ---------------------------------------------------------- short-circuit condition chains + + /** Conditional jumps folded into the condition of a later one (chain members). */ + private final Set chainMember = new HashSet<>(); + + /** Last jump of a chain → its members in order and the body condition. */ + private record Chain(List members, Cond body) {} + + private final Map chains = new HashMap<>(); + + private final List pendingChain = new ArrayList<>(); + private int chainOff = -1; + + /** Boolean formula over the jumps of a chain: T, F, L (leaf k: jump k is taken; pos=false negated), AND, OR. */ + private record Cond(String kind, int k, boolean pos, Cond a, Cond b) { + static final Cond TRUE = new Cond("T", 0, true, null, null), FALSE = new Cond("F", 0, true, null, null); + + static Cond leaf(int k) { + return new Cond("L", k, true, null, null); + } + + Cond not() { + return new Cond("L", k, !pos, null, null); + } + + static Cond and(Cond x, Cond y) { + return y == TRUE ? x : x == TRUE ? y : new Cond("AND", 0, true, x, y); + } + + static Cond or(Cond x, Cond y) { + return y == FALSE ? x : x == FALSE ? y : new Cond("OR", 0, true, x, y); + } + + /** "if j then a else b" as and/or of j, a and b, or null if it does not simplify. */ + static Cond ite(Cond j, Cond a, Cond b) { + if (a == TRUE) { + return or(j, b); + } + if (a == FALSE) { + return and(j.not(), b); + } + if (b == TRUE) { + return or(j.not(), a); + } + if (b == FALSE) { + return and(j, a); + } + if (b.kind.equals("OR") && b.b.equals(a)) { + return or(and(j.not(), b.a), a); + } + if (b.kind.equals("AND") && b.b.equals(a)) { + return and(or(j, b.a), a); + } + return null; + } + } + + /** + * Finds chains of conditional jumps that compiled || / && conditions leave ("a; jnz T; b; jz F; + * T:"): separated only by expression code, each going to the false target F of the last one, + * to the code right behind it, or to the start of a later member's expression; at least one + * member (an else part would otherwise be hidden behind nested ifs that all jump to it). + */ + private void findChains() { + for (int n = ls.size() - 1; n >= 0; n--) { + if (ls.get(n).kind() != StratListing.Kind.INSTR + || !condJump(ls.get(n).op()) + || chainMember.contains(n)) { + continue; + } + Integer f = target(n); + if (f == null || f <= n) { + continue; + } + int body = anchor(n + 1); + // members backwards: segment starts (anchors) → formula from there + List members = new ArrayList<>(); + Map from = new HashMap<>(); + Cond last = Cond.leaf(n).not(); + int seg = segmentStart(n); + from.put(seg, last); + Cond best = null; + List bestMembers = null; + Cond cur = last; + while (seg > 0) { + int j = seg - 1; + while (j >= 0 && ls.get(j).kind() == StratListing.Kind.LABEL) { + j--; + } + if (j < 0 + || ls.get(j).kind() != StratListing.Kind.INSTR + || !condJump(ls.get(j).op()) + || chainMember.contains(j)) { + break; + } + Integer t = target(j); + if (t == null || t <= j || !labelsOnlyFrom(j, seg)) { + break; + } + int at = anchor(t); + Cond whenJumps = at == body ? Cond.TRUE : at == anchor(f) ? Cond.FALSE : from.get(at); + if (whenJumps == null) { + break; + } + cur = Cond.ite(Cond.leaf(j), whenJumps, cur); + if (cur == null) { + break; + } + members.add(0, j); + seg = segmentStart(j); + if (seg < 0) { + break; + } + from.put(seg, cur); + best = cur; + bestMembers = List.copyOf(members); + } + if (best == null) { + continue; + } + chainMember.addAll(bestMembers); + chains.put(n, new Chain(bestMembers, best)); + } + } + + /** Labels between line indexes j and seg are only targets of conditional jumps at or before j. */ + private boolean labelsOnlyFrom(int j, int seg) { + for (int k = j + 1; k < seg; k++) { + String lb = ls.get(k).label(); + for (int x = 0; x < ls.size(); x++) { + StratListing.Line l = ls.get(x); + boolean uses = l.kind() != StratListing.Kind.LABEL + && List.of(l.text().split("[ ,@+]+")).contains(lb); + if (uses && (x > j || l.kind() != StratListing.Kind.INSTR || !condJump(l.op()))) { + return false; + } + } + } + return true; + } + + /** + * Start (line index) of the expression code that the conditional jump at j pops: the lines + * before it must be pure expression code pushing exactly one value; −1 if not. + */ + private int segmentStart(int j) { + int need = 1; + for (int k = j - 1; k >= 0; k--) { + StratListing.Line l = ls.get(k); + if (l.kind() != StratListing.Kind.INSTR) { + return -1; + } + int d = stackEffect(l); + if (d == Integer.MIN_VALUE) { + return -1; + } + need -= d; + if (need == 0) { + return k; + } + if (need < 0) { + return -1; + } + } + return -1; + } + + /** Net pushes of a pure expression instruction (MIN_VALUE if it is not one). */ + private int stackEffect(StratListing.Line l) { + int op = l.op(); + if (PUSH.containsKey(op) + || ADDR.containsKey(op) + || op == StratOps.PUSH_SHORT + || op == StratOps.PUSH_IMM + || op == StratOps.PUSH_ADDR + || op == StratOps.PUSH_SOUND) { + return 1; + } + if (BINARY.containsKey(mn(l))) { + return -1; + } + if (op == 0x46 || op == 0xaf) { + return 0; + } + OpTable.Op info = ops.op(op); + if (info.pushes() == 1 && info.pops() >= 0 && op >= StratOps.PUSH_IMM && op != StratOps.SPAWN) { + return 1 - info.pops(); + } + return Integer.MIN_VALUE; + } + + /** Text of a chain's body condition; leaves: members' expressions (pendingChain), last = e. */ + private String chainCondition(int n, Chain c, String e) { + Map text = new HashMap<>(); + for (int k = 0; k < c.members.size(); k++) { + text.put(c.members.get(k), k < pendingChain.size() ? pendingChain.get(k) : "pop()"); + } + text.put(n, e); + pendingChain.clear(); + return render(c.body, text); + } + + private String render(Cond c, Map text) { + return switch (c.kind) { + case "L" -> { + int op = ls.get(c.k).op(); + boolean jnz = op == 0x13 || op == 0x15; + String e = text.get(c.k); + yield jnz == c.pos ? e : not(e); + } + case "AND" -> andOperand(render(c.a, text)) + " && " + andOperand(render(c.b, text)); + case "OR" -> orOperand(render(c.a, text)) + " || " + orOperand(render(c.b, text)); + default -> c.kind.equals("T") ? "1r" : "0"; + }; + } + + /** Parenthesizes an || operand with a top-level && (for reading). */ + private static String orOperand(String c) { + return topLevel(c).contains("&&") ? "(" + c + ")" : c; + } + + private static String not(String e) { + if (e.startsWith("!(") && e.endsWith(")") && balanced(e.substring(2, e.length() - 1))) { + return e.substring(2, e.length() - 1); + } + return e.matches("[\\w.]+") ? "!" + e : "!(" + e + ")"; + } + + /** Loops that a labeled break/continue names: open line index → name. */ + private final Map loopNames = new HashMap<>(); + + /** "break name"/"continue name" for a jump from line i to t out of an outer loop (null if none). */ + private String labeledJump(List accepted, Block inner, int i, int t) { + Block best = null; + String as = null; + for (Block b : accepted) { + if (b == inner || !(b.isLoop() || b.kind.equals("do")) || b.open >= i || i >= b.close) { + continue; + } + String k = anchor(t) == anchor(b.close + 1) + ? "break" + : b.isLoop() && anchor(t) == anchor(b.open) ? "continue" : null; + if (k != null && (best == null || b.open > best.open)) { + best = b; + as = k; + } + } + if (best == null || inner == null) { + return null; + } + String name = ls.get(best.open).label(); + loopNames.put(best.open, name); + return as + " " + name; + } + + /** + * "return"/"end"/"remove" when the instruction at line index i ends the strat or subroutine, + * so that a jump to it is the same as executing it (null otherwise). + */ + private String terminal(int i) { + if (i >= ls.size() || ls.get(i).kind() != StratListing.Kind.INSTR) { + return null; + } + int op = ls.get(i).op(); + return op == StratOps.JUMP_POP ? "return" : op == StratOps.END || op == 0x8e ? mn(ls.get(i)) : null; + } + /** "loop {" directly followed by "if (c) break" becomes "while (!c) {". */ private void whileLoops() { for (int i = 0; i + 1 < lines.size(); i++) { Line a = lines.get(i), b = lines.get(i + 1); - if (a.text.equals("loop {") + if (a.text.endsWith("loop {") + && (a.text.equals("loop {") || a.text.matches("\\w+: loop \\{")) && b.depth == a.depth + 1 && b.text.startsWith("if (") && b.text.endsWith(") break")) { - String c = b.text.substring(4, b.text.length() - 7); - String w = c.startsWith("!(") && c.endsWith(")") && balanced(c.substring(2, c.length() - 1)) - ? c.substring(2, c.length() - 1) - : c.startsWith("!") && !c.contains(" ") ? c.substring(1) : "!(" + c + ")"; - lines.set(i, new Line(b.offset, a.depth, "while (" + w + ") {")); + String w = breakCondition(b.text); lines.remove(i + 1); + // further "if (c) break" lines at the top: while (w && !c) + while (i + 1 < lines.size() + && lines.get(i + 1).depth == a.depth + 1 + && lines.get(i + 1).text.startsWith("if (") + && lines.get(i + 1).text.endsWith(") break")) { + w = andOperand(w) + " && " + andOperand(breakCondition(lines.get(i + 1).text)); + lines.remove(i + 1); + } + String name = a.text.equals("loop {") ? "" : a.text.substring(0, a.text.length() - 6); + lines.set(i, new Line(b.offset, a.depth, name + "while (" + w + ") {")); } } } + /** The loop condition that "if (c) break" leaves: !c. */ + private static String breakCondition(String line) { + String c = line.substring(4, line.length() - 7); + return c.startsWith("!(") && c.endsWith(")") && balanced(c.substring(2, c.length() - 1)) + ? c.substring(2, c.length() - 1) + : c.startsWith("!") && !c.contains(" ") ? c.substring(1) : "!(" + c + ")"; + } + /** "} else {" + a lone "if" up to the else's end becomes "} else if (…) {"; an empty then-block is negated. */ private void elseIfChains() { for (int i = 0; i + 1 < lines.size(); i++) { @@ -591,6 +890,59 @@ public final class StratPseudo { } } + /** "if (a) {" whose whole body is "if (b) {…}" becomes "if (a && b) {…}". */ + private void andChains() { + for (int i = 0; i + 1 < lines.size(); ) { + Line a = lines.get(i), b = lines.get(i + 1); + int close = -1; + if (isPlainIf(a.text) && isPlainIf(b.text) && b.depth == a.depth + 1) { + for (int k = i + 2; k < lines.size(); k++) { + Line x = lines.get(k); + if (x.depth <= b.depth) { + close = x.depth == b.depth && x.text.equals("}") ? k : -1; + break; + } + } + } + if (close < 0 + || close + 1 >= lines.size() + || !lines.get(close + 1).text.equals("}") + || lines.get(close + 1).depth != a.depth) { + i++; + continue; + } + String c = andOperand(a.text.substring(4, a.text.length() - 3)) + " && " + + andOperand(b.text.substring(4, b.text.length() - 3)); + lines.set(i, new Line(a.offset, a.depth, "if (" + c + ") {")); + lines.remove(close + 1); + lines.remove(i + 1); + for (int k = i + 1; k < close; k++) { + Line x = lines.get(k); + lines.set(k, new Line(x.offset, x.depth - 1, x.text)); + } + } + } + + /** c with everything inside brackets blanked out. */ + private static String topLevel(String c) { + StringBuilder top = new StringBuilder(); + int d = 0; + for (char ch : c.toCharArray()) { + d += ch == '(' ? 1 : ch == ')' ? -1 : 0; + top.append(d == 0 ? ch : ' '); + } + return top.toString(); + } + + private static boolean isPlainIf(String t) { + return t.startsWith("if (") && t.endsWith(") {") && balanced(t.substring(4, t.length() - 3)); + } + + private static String andOperand(String c) { + String t = topLevel(c); + return t.contains("||") || t.contains(" | ") || t.contains(" & ") ? "(" + c + ")" : c; + } + private static boolean nests(int a0, int a1, int b0, int b1) { return a1 <= b0 || b1 <= a0 || (a0 >= b0 && a1 <= b1) || (b0 >= a0 && b1 <= a1); } @@ -686,7 +1038,9 @@ public final class StratPseudo { || op == StratOps.PUSH_IMM || op == StratOps.PUSH_ADDR || op == StratOps.PUSH_SOUND) { - push(off, a + (l.comment() != null && l.comment().startsWith("strat") ? " /*" + l.comment() + "*/" : "")); + // the script language reads a plain integer as units: raw words get the "r" suffix + String v = a.matches("-?[1-9]\\d*") ? a + "r" : a; + push(off, v + (l.comment() != null && l.comment().startsWith("strat") ? " /*" + l.comment() + "*/" : "")); return; } if (op == 0x47 || op == 0x48) { @@ -709,11 +1063,23 @@ public final class StratPseudo { push(off, "!" + pop()); return; } + if (condJump(op) && chainMember.contains(i)) { + if (pendingChain.isEmpty()) { + chainOff = begin(off); + } + pendingChain.add(strip(pop())); + return; + } if (condJump(op)) { String e = strip(pop()); boolean neg = op == 0x13 || op == 0x15; - String yield = op <= 0x13 ? " /*yield*/" : ""; int b0 = begin(off); + if (chains.containsKey(i)) { + e = chainCondition(i, chains.get(i), e); + neg = false; + b0 = chainOff; + } + String yield = op <= 0x13 ? " /*yield*/" : ""; flush(); Block lp = loopEnd.get(i); String jumpIf = neg ? e : "!(" + e + ")"; @@ -723,8 +1089,9 @@ public final class StratPseudo { } else if (lp != null) { depth--; Line last = lines.isEmpty() ? null : lines.get(lines.size() - 1); - if (last != null && last.text.equals("do {") && last.depth == depth) { - lines.set(lines.size() - 1, new Line(b0, depth, "do {} while (" + jumpIf + ")" + yield)); + if (last != null && last.text.endsWith("do {") && last.depth == depth) { + String name = last.text.substring(0, last.text.length() - 4); + lines.set(lines.size() - 1, new Line(b0, depth, name + "do {} while (" + jumpIf + ")" + yield)); } else { out(b0, "} while (" + jumpIf + ")" + yield); } diff --git a/src/main/resources/com/eliasmueller/llamamod/format/strat/op-aliases.tsv b/src/main/resources/com/eliasmueller/llamamod/format/strat/op-aliases.tsv new file mode 100644 index 0000000..8ce71d1 --- /dev/null +++ b/src/main/resources/com/eliasmueller/llamamod/format/strat/op-aliases.tsv @@ -0,0 +1,5 @@ +# old mnemonic current mnemonic (old names still assemble; stored sources keep working) +flagEC10000 freezeOffCamera +flagEC2 touchable +flagEC100 noFloorPhysics +hudReset2 hudResetNoop diff --git a/src/main/resources/com/eliasmueller/llamamod/format/strat/ops.tsv b/src/main/resources/com/eliasmueller/llamamod/format/strat/ops.tsv index e7cf0cb..2fc898f 100644 --- a/src/main/resources/com/eliasmueller/llamamod/format/strat/ops.tsv +++ b/src/main/resources/com/eliasmueller/llamamod/format/strat/ops.tsv @@ -46,11 +46,11 @@ 0x2c nop_0x2c - 0 0 No-op (shared empty handler); unused. high - 0x2d nop_0x2d - 0 0 No-op (shared empty handler); unused. high - 0x2e nop_0x2e - 0 0 No-op (shared empty handler); unused. high - -0x2f flagEC10000 imm 0 0 arg!=0 sets, 0 clears +0xEC bit 0x10000 = "freeze when off-camera": the camera pass (FUN_00436190) sets +0xEC 0x8000 when the strat is outside the camera range; with both bits set the frame loop (0x54c603) and the strat-vs-strat collision loop (0x54cc1a) skip it. Used by ~1350 strats (pickups, triggers, enemies). medium - +0x2f freezeOffCamera imm 0 0 arg!=0 sets, 0 clears +0xEC bit 0x10000 = "freeze when off-camera": the camera pass (FUN_00436190) sets +0xEC 0x8000 when the strat is outside the camera range; with both bits set the frame loop (0x54c603) and the strat-vs-strat collision loop (0x54cc1a) skip it. Used by ~1350 strats (pickups, triggers, enemies). medium - 0x30 trackPlayer imm 0 0 If no player yet: re-executes itself next frame (pc-=4, yield); else arg sets/clears +0xEC bit 0x4000 = update distance to player each frame (+0x148). medium - -0x31 flagEC2 imm 0 0 arg sets/clears +0xEC bit 2 = "others can stand on / touch me": in the strat collision loop (0x54cc96) a strat touching a strat with this bit gets +0xE8 0x400000 (and 0x800000 when it moves) = properties 32/33; also readable as property 0x1f. Set by Llama, Coin, Jar, EnemyCoin, RubyIdol. medium - +0x31 touchable imm 0 0 arg sets/clears +0xEC bit 2 = "others can stand on / touch me": in the strat collision loop (0x54cc96) a strat touching a strat with this bit gets +0xE8 0x400000 (and 0x800000 when it moves) = properties 32/33; also readable as property 0x1f. Set by Llama, Coin, Jar, EnemyCoin, RubyIdol. medium - 0x32 flagE8_80000000 imm 0 0 arg sets/clears +0xE8 bit 31; no reader of the bit found in the exe (scan of all +0xE8 flag tests); unused in the levels. medium - -0x33 flagEC100 imm 0 0 arg sets/clears +0xEC bit 0x100; the collision response (0x4044f7) skips the floor/slope handling when it is set. Used by LlamaSpit, DropObject, RollerCoaster, KuscoTurtle (objects that move by script, not by floor physics). medium - +0x33 noFloorPhysics imm 0 0 arg sets/clears +0xEC bit 0x100; the collision response (0x4044f7) skips the floor/slope handling when it is set. Used by LlamaSpit, DropObject, RollerCoaster, KuscoTurtle (objects that move by script, not by floor physics). medium - 0x34 flagEC200000 imm 0 0 arg sets/clears +0xEC bit 0x200000; no direct test of the bit found in the exe (all +0xEC flag tests scanned). Used by Llama, RiverCroc, RiverLog, Rock, river NPCs (river/canoe level objects). low - 0x35 nop_0x35 - 0 0 No-op (shared empty handler); unused. high - 0x36 nop_0x36 - 0 0 No-op (shared empty handler); unused. high - @@ -329,7 +329,7 @@ 0x147 nop_0x147 - 0 0 Empty handler FUN_00426500 (shared no-op); does nothing. high - 0x148 gotoLevel4_1 - 0 0 Hardcoded level change: next level (0x584EB4/EB8/EBC/EC0) = 4/1/1/0, previous level (0x585008..14) = 4/1/4/0, game state 0x584638 = 7 (load level). medium - 0x149 nop_0x149 - 0 0 Empty handler FUN_00426500 (shared no-op); does nothing. high - -0x14a hudReset2 - 0 0 Calls FUN_004268c0(2), which returns at once for any argument other than 0 (verified in the assembly): a no-op. Unused. high - +0x14a hudResetNoop - 0 0 Calls FUN_004268c0(2), which returns at once for any argument other than 0 (verified in the assembly): a no-op. Unused. high - 0x14b setGlobal5fd086 imm 0 0 Stores the low 16 bits of the inline word in global 0x5FD086 (never read elsewhere; dead leftover). medium - 0x14c removeCollPoint - 1 0 pops id (fixed, >>12); removes the collision point with that id from the strat's collision point list (+0xC8 array of 4-byte entries, count +0xC6). Counterpart of 0xc6 (add/set collision point). medium stSetCollPoint (inverse) 0x14d setFlagEC_400000 flags 0 0 Inline word: nonzero sets, zero clears bit 0x400000 of strat flags2 (+0xEC); the bit selects which height constant own property 0xF2 returns. high - diff --git a/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratEditsTest.java b/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratEditsTest.java index d9e4c8c..01bd8ad 100644 --- a/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratEditsTest.java +++ b/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratEditsTest.java @@ -213,4 +213,142 @@ class StratEditsTest { } throw new AssertionError(); } + + /** Import in the same session behind custom types: they stay last, can be edited/deleted, creating is undoable. */ + @Test + void customTypesAfterImportInTheSameSession() throws Exception { + Bases cd = cd(); + StratEdits.init(); + CrossImport.init(); + Project p = ProjectIO.read(ProjectIO.write(Project.create(cd, "imp", "t1l1m001"), cd), cd); + History h = new History(p.scene()); + h.execute(TypeEdits.create(p, StratEdits.cloneOf(p.scene(), "Coin", "CoinA"))); + h.execute(Edits.placeStrat(p.scene(), "CoinA", 0, 30, 2, 30, 0.0)); + Strat a = p.scene().strats().get(p.scene().strats().size() - 1); + CrossImport.importInto(p, List.of(new CrossImport.TypeRef("t1l2m001", "Spider", spiderCode(cd))), cd); + h.clear(); + int units = StratEdits.analysis(p.scene()).img().units.size(); + assertEquals(units - 1, StratEdits.firstCustomUnit(p.scene()), "the custom unit is the last one again"); + assertEquals(null, StratEdits.rebuildBlocker(p.scene())); + assertEquals(entry(p, "CoinA"), a.code()); + assertEquals("CoinA", nameAt(WadBuilder.build(p.scene()), a.code())); + assertNotNull(p.scene().catalog().type("Spider")); + assertTrue(StratEdits.analysis(p.scene()).code().errors.isEmpty()); + assertArrayEquals( + StratEdits.chunk(p.reference()).data(), + StratEdits.chunk(p.scene()).data(), + "reference = scene"); + + // create (undoable), edit, delete + h.execute(TypeEdits.create(p, StratEdits.cloneOf(p.scene(), "Coin", "CoinB"))); + assertEquals(2, StratEdits.records(p).types().size()); + h.undo(); + assertEquals(1, StratEdits.records(p).types().size()); + assertTrue(p.scene().catalog().type("CoinB") == null); + h.redo(); + StratEdits.CustomType ta = StratEdits.records(p).types().get(0); + h.execute(TypeEdits.edit(p, 0, withSource(ta, ta.source().replace("push 5.625deg", "push 90deg")))); + assertEquals(0x400000, spin(p, "CoinA").value()); + assertEquals(entry(p, "CoinA"), a.code()); + byte[] wad = WadBuilder.build(p.scene()); + Project q = ProjectIO.read(ProjectIO.write(p, cd), cd); + assertTrue(q.warnings().isEmpty(), q.warnings().toString()); + assertArrayEquals(wad, WadBuilder.build(q.scene()), "reloaded project builds the same WAD"); + h.execute(TypeEdits.delete(p, 0)); + assertTrue(!p.scene().strats().contains(a)); + h.undo(); + assertEquals(entry(p, "CoinA"), a.code()); + } + + /** unit:N operands that point at custom types are stored by name and follow the type when indexes shift. */ + @Test + void referencesBetweenCustomTypesAreSymbolic() throws Exception { + Bases cd = cd(); + StratEdits.init(); + Project p = ProjectIO.read(ProjectIO.write(Project.create(cd, "refs", "t1l1m001"), cd), cd); + History h = new History(p.scene()); + h.execute(TypeEdits.create(p, StratEdits.cloneOf(p.scene(), "Coin", "First"))); + h.execute(TypeEdits.create(p, StratEdits.cloneOf(p.scene(), "Coin", "Target"))); + int target = StratEdits.firstCustomUnit(p.scene()) + 1; + int off = entry(p, "Target") + - StratEdits.analysis(p.scene()).img().units.get(target).start(); + String src = + """ + .unit RefB + .string "RefB" + RefB: + debugName "RefB" + address unit:%d+%d + pop + spin: + jmpYield spin + end + """ + .formatted(target, off); + StratCatalog.Variant v = p.scene().catalog().type("Coin").variant(0); + h.execute(TypeEdits.create(p, new StratEdits.CustomType("RefB", null, "RefB", src, v, "Coin"))); + assertTrue(StratEdits.records(p).types().get(2).source().contains("address unit:Target+" + off)); + int tu = StratEdits.analysis(p.scene()).img().unitOf(entry(p, "Target")); + assertEquals(StratEdits.analysis(p.scene()).img().units.get(tu).start() + off, addressIn(p, "RefB")); + // delete the first type: Target moves one unit down, RefB still points at it + h.execute(TypeEdits.delete(p, 0)); + tu = StratEdits.analysis(p.scene()).img().unitOf(entry(p, "Target")); + assertEquals(StratEdits.analysis(p.scene()).img().units.get(tu).start() + off, addressIn(p, "RefB")); + int ru = StratEdits.analysis(p.scene()).img().unitOf(entry(p, "RefB")); + assertTrue(StratEdits.listing(p.scene(), ru).text().contains("unit:Target+0x" + Integer.toHexString(off))); + // renaming the target renames the reference; deleting it is refused + StratEdits.CustomType t = StratEdits.records(p).types().get(0); + h.execute(TypeEdits.edit( + p, 0, new StratEdits.CustomType("Goal", t.basedOn(), t.entryLabel(), t.source(), t.proto()))); + assertTrue(StratEdits.records(p).types().get(1).source().contains("unit:Goal+" + off)); + List rest = List.of(StratEdits.records(p).types().get(1)); + List problems = StratEdits.checkTypes(p.scene(), rest, -1, null); + assertNotNull(problems); + assertTrue(problems.get(0).contains("unknown unit name"), problems.toString()); + Project q = ProjectIO.read(ProjectIO.write(p, cd), cd); + assertTrue(q.warnings().isEmpty(), q.warnings().toString()); + assertArrayEquals(WadBuilder.build(p.scene()), WadBuilder.build(q.scene())); + } + + /** Value of the first address operand in a type's unit. */ + static int addressIn(Project p, String type) { + StratEdits.Analysis a = StratEdits.analysis(p.scene()); + int u = a.img().unitOf(entry(p, type)); + for (StratCode.Site s : a.code().addrSites) { + if (a.img().unitOf(s.offset()) == u) { + return s.value(); + } + } + throw new AssertionError("no address operand in " + type); + } + + /** Edit can switch the type the fields come from; it is saved. */ + @Test + void editChangesTheFieldsType() throws Exception { + Bases cd = cd(); + StratEdits.init(); + Project p = ProjectIO.read(ProjectIO.write(Project.create(cd, "fields", "t1l1m001"), cd), cd); + History h = new History(p.scene()); + StratEdits.CustomType t = StratEdits.cloneOf(p.scene(), "Coin", "CoinF"); + h.execute(TypeEdits.create(p, t)); + String other = p.scene().catalog().types().stream() + .map(StratCatalog.Type::name) + .filter(n -> !n.equals("Coin") + && !n.equals("CoinF") + && p.scene().catalog().type(n).variant(0).nVars() + != p.scene().catalog().type("Coin").variant(0).nVars()) + .findFirst() + .orElseThrow(); + StratCatalog.Variant ov = p.scene().catalog().type(other).variant(0); + h.execute(TypeEdits.edit( + p, 0, new StratEdits.CustomType("CoinF", "Coin", t.entryLabel(), t.source(), ov, other))); + assertEquals(ov.nVars(), p.scene().catalog().type("CoinF").variant(0).nVars()); + Project q = ProjectIO.read(ProjectIO.write(p, cd), cd); + assertEquals(other, StratEdits.records(q).types().get(0).fieldsFrom()); + assertEquals("Coin", StratEdits.records(q).types().get(0).basedOn()); + h.undo(); + assertEquals( + p.scene().catalog().type("Coin").variant(0).nVars(), + p.scene().catalog().type("CoinF").variant(0).nVars()); + } } diff --git a/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsGameLevel.java b/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsGameLevel.java index 7fd2a5d..4cedbb4 100644 --- a/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsGameLevel.java +++ b/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsGameLevel.java @@ -69,9 +69,64 @@ public final class StratsGameLevel { } """; + /** Script language 2: switch over a state that an event handler advances, unit numbers, && / ||. */ + static final String TOUCHER = + """ + // grows each time the player touches it: 1x, 2x, 3x, then spins fast + strat Toucher { + alias hits = v5 + alias cooldown = v6 + setModel(model:5) + collisionOn<0x20000>() + collRadius(0.6) + self.y = self.y + 1 + hits = 0 + cooldown = 0 + on touched { + if (cooldown == 0 && hits < 3) { + hits += 1 + cooldown = 20 + soundPlay(sound:6) + } + } + loop { + if (cooldown > 0 || hits > 9) { + cooldown -= 1 + } + switch (hits) { + case 0: + scale(1) + turnLeft(2deg) + break + case 1: + scale(2) + turnLeft(4deg) + break + case 2: + scale(3) + turnLeft(8deg) + break + default: + scale(3) + turnLeft(45deg) + } + yield + } + } + """; + + /** The same with a timer event (type 0x40) instead of touched: grows without the player. */ + static final String TICKER = TOUCHER.replace("strat Toucher", "strat Ticker") + .replace("on touched", "on event(0x40, 30)") + .replace(" collisionOn<0x20000>()\n collRadius(0.6)\n", ""); + public static void main(String[] a) throws Exception { Bases cd = Bases.fromCd(Path.of(System.getProperty("user.home") + "/.wine-lama/iso-dk/Setup/Eng/Cd")); StratEdits.init(); + if (a.length > 1 && a[1].equals("v2")) { + v2(cd, Path.of(a[0])); + return; + } if (a.length > 1 && a[1].equals("rain")) { Project p = ProjectIO.read(ProjectIO.write(Project.create(cd, "edit", "t1l2m001"), cd), cd); History h = new History(p.scene()); @@ -119,4 +174,42 @@ public final class StratsGameLevel { System.out.println("saved " + a[0] + " (" + p.scene().strats().size() + " objects, start " + sx + "," + sy + "," + sz + ")"); } + + /** + * Village 1: a custom type, then an import (Spider) in the same session, then the custom type + * edited (3x scale) and a compiled script type created (Toucher, 2.5 cells ahead of the start). + */ + static void v2(Bases cd, Path out) throws Exception { + com.eliasmueller.llamamod.editor.tools.catalog.CrossImport.init(); + Project p = ProjectIO.read(ProjectIO.write(Project.create(cd, "strats2", "t1l1m001"), cd), cd); + History h = new History(p.scene()); + StratEdits.CustomType big = StratEdits.cloneOf(p.scene(), "Coin", "BigCoin"); + h.execute(TypeEdits.create(p, big)); + com.eliasmueller.llamamod.editor.tools.catalog.CrossImport.importInto( + p, + List.of(new com.eliasmueller.llamamod.editor.tools.catalog.CrossImport.TypeRef( + "t1l2m001", "Spider", StratEditsTest.spiderCode(cd))), + cd); + h.clear(); + String src = + big.source().replace(" setModel\n", " setModel\n pushShort 3.0\n scale\n"); + h.execute(TypeEdits.edit(p, 0, big.withSource(src))); + String asm = StratCompiler.compile(TOUCHER, StratEdits.paramNames("Coin")); + h.execute(TypeEdits.create(p, new StratEdits.CustomType("Toucher", null, "Toucher", asm, big.proto(), "Coin"))); + Strat start = p.scene().playerStart(); + double sx = start.x() / 4096.0, sy = start.y() / 4096.0, sz = start.z() / 4096.0; + String tick = StratCompiler.compile(TICKER, StratEdits.paramNames("Coin")); + h.execute(TypeEdits.create(p, new StratEdits.CustomType("Ticker", null, "Ticker", tick, big.proto(), "Coin"))); + // the start view looks along +z (the row of the first in-game test is in front of it) + h.execute(Edits.placeStrat(p.scene(), "Toucher", 0, sx, sy, sz + 2.5, 0.0)); + h.execute(Edits.placeStrat(p.scene(), "Ticker", 0, 30.0, 8.0, 64.6, 0.0)); + String[] types = {"Coin", "BigCoin", "Spider"}; + for (int i = 0; i < types.length; i++) { + h.execute(Edits.placeStrat(p.scene(), types[i], 0, 31.5 + 1.5 * i, 8.0, 64.6, 0.0)); + } + System.out.println( + "types: " + StratEdits.customNames(p) + ", start " + sx + "," + sy + "," + sz + " yaw " + start.ry()); + ProjectIO.save(p, out, cd); + System.out.println("saved " + out); + } } diff --git a/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsTour.java b/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsTour.java index 86c7bb0..53c3b0e 100644 --- a/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsTour.java +++ b/src/test/java/com/eliasmueller/llamamod/editor/tools/strats/StratsTour.java @@ -44,12 +44,13 @@ public final class StratsTour { var p = w.document().project(); StratEdits.CustomType big = StratEdits.cloneOf(w.scene(), "Coin", "BigCoin"); w.execute(TypeEdits.create(p, big)); - String asm = StratCompiler.compile(StratsGameLevel.PULSER); - w.execute(TypeEdits.create(p, new StratEdits.CustomType("Pulser", null, "Pulser", asm, big.proto()))); + String asm = StratCompiler.compile(StratsGameLevel.TOUCHER, StratEdits.paramNames("Coin")); + w.execute(TypeEdits.create( + p, new StratEdits.CustomType("Toucher", null, "Toucher", asm, big.proto(), "Coin"))); Strat st = w.scene().playerStart(); double x = st.x() / 4096.0, y = st.y() / 4096.0, z = st.z() / 4096.0; - w.execute(Edits.placeStrat(w.scene(), "Pulser", 0, x + 1, y, z + 2, 0.0)); - w.execute(Edits.placeStrat(w.scene(), "Pulser", 0, x - 1, y, z + 2, 0.0)); + w.execute(Edits.placeStrat(w.scene(), "Toucher", 0, x + 1, y, z + 2, 0.0)); + w.execute(Edits.placeStrat(w.scene(), "Toucher", 0, x - 1, y, z + 2, 0.0)); w.execute(Edits.placeStrat(w.scene(), "BigCoin", 0, x, y, z + 3, 0.0)); Strat last = w.scene().strats().get(w.scene().strats().size() - 2); w.selection().set(last, null); diff --git a/src/test/java/com/eliasmueller/llamamod/format/strat/StratCompilerTest.java b/src/test/java/com/eliasmueller/llamamod/format/strat/StratCompilerTest.java index 425099b..c64313b 100644 --- a/src/test/java/com/eliasmueller/llamamod/format/strat/StratCompilerTest.java +++ b/src/test/java/com/eliasmueller/llamamod/format/strat/StratCompilerTest.java @@ -50,7 +50,7 @@ class StratCompilerTest { assertFalse(view.contains("goto"), view); assertTrue(view.contains("strat Spinner:"), view); assertTrue(view.contains("while (v0 < 10.0) {\n turnLeft(4deg)\n v0 += 1.0\n yield\n}"), view); - assertTrue(view.contains("if ((self.y > 2.0) && !self.animPlaying) {"), view); + assertTrue(view.contains("if (self.y > 2.0 && !self.animPlaying) {"), view); assertTrue( view.contains( "} else if (self.distToPlayerSqXZ < 4.0) {\n break\n } else {\n call L_00b4()"), @@ -60,13 +60,176 @@ class StratCompilerTest { } @Test - void numbersMatchTheAssembly() { - String asm = StratCompiler.compile("strat N { v0 = 1.5\n v1 = 100.0\n v2 = 90deg\n v3 = -3 }"); + void plainIntegersAreUnits() { + String asm = StratCompiler.compile( + "strat N { v0 = 1.5\n v1 = 100\n v2 = 90deg\n v3 = -3\n v4 = 215r\n v5 = 0x10\n v6 = -7r }"); assertTrue(asm.contains("pushShort 1.5\n"), asm); assertTrue(asm.contains("push 100.0\n"), asm); assertTrue(asm.contains("push 90deg\n"), asm); - assertTrue(asm.contains("pushShort -3\n"), asm); + assertTrue(asm.contains("pushShort -3.0\n"), asm); + assertTrue(asm.contains("pushShort 215\n"), asm); + assertTrue(asm.contains("pushShort 0x10\n"), asm); + assertTrue(asm.contains("pushShort -7\n"), asm); assertTrue(asm.trim().endsWith("end"), asm); + // the old rule: plain integers are raw words + String old = StratCompiler.compile("use rawNumbers\nstrat N { v3 = -3\n v4 = 10 }"); + assertTrue(old.contains("pushShort -3\n") && old.contains("pushShort 10\n"), old); + } + + @Test + void scriptsCompiledWithTheOldRuleKeepTheirMeaning() { + // generated before language version 2: no marker line behind the embedded source + String asm = ";| strat N {\n;| v0 = 10\n;| }\n .string \"N\"\nN:\n end\n"; + String src = StratCompiler.embeddedSource(asm); + assertTrue(src.startsWith(StratCompiler.RAW_NUMBERS), src); + assertTrue(StratCompiler.compile(src).contains("pushShort 10\n")); + // new output: the source comes back unchanged + String v2 = StratCompiler.compile("strat N {\n v0 = 10\n}"); + assertEquals("strat N {\n v0 = 10\n}\n", StratCompiler.embeddedSource(v2)); + } + + static String view(String script, String entry) { + return StratPseudo.of(StratPseudoTest.listing(StratCompiler.compile(script), entry)) + .text(); + } + + @Test + void foldsConstants() { + String asm = StratCompiler.compile("strat N { v0 = 2 * 3 + 0.5\n v1 = -(1 << 4)\n v2 = 90deg / 2 }"); + assertTrue(asm.contains("pushShort 6.5\n"), asm); + assertTrue(asm.contains("push -16.0\n"), asm); + assertTrue(asm.contains("push 512.0\n"), asm); // 45deg + assertFalse(asm.contains("mul") || asm.contains("add\n") || asm.contains("shl"), asm); + } + + @Test + void shortCircuitConditions() { + String script = + """ + strat C { + if (v0 > 2 && v1 || !v2) { + turnLeft(4deg) + } + while (v3 < 3 && v4) { + v3 += 1 + } + } + """; + String asm = StratCompiler.compile(script); + assertFalse(asm.contains(" and\n") || asm.contains(" or\n"), asm); + String v = view(script, "C"); + assertFalse(v.contains("goto"), v); + assertTrue(v.contains("if ((v0 > 2.0 && v1) || !v2) {\n turnLeft(4deg)\n}"), v); + assertTrue(v.contains("while (v3 < 3.0 && v4) {\n v3 += 1.0\n}"), v); + // value context: both sides evaluated (the and/or opcodes) + assertTrue(StratCompiler.compile("strat D { v0 = v1 && v2 }").contains(" and\n")); + } + + @Test + void switchWithFallThroughAndDefault() { + String script = + """ + strat S { + loop { + switch (v0) { + case 1: + v1 = 2 + break + case 2: + case 3: + v1 = 100000 + default: + v1 = 0 + } + yield + } + } + """; + String asm = StratCompiler.compile(script); + assertTrue(asm.contains(".switch 3\n .case 1.0, "), asm); + String v = view(script, "S"); + assertFalse(v.contains("goto"), v); + assertTrue( + v.contains("case 1.0:\n v1 = 2.0\n break\n case 2.0:\n case 3.0:\n" + + " v1 = 100000.0\n default:\n v1 = 0\n }"), + v); + CompileExceptionCheck.fails("strat S { switch (v0) { case v1: end } }", "constant"); + CompileExceptionCheck.fails("strat S { switch (v0) { case 1: case 1: end } }", "duplicate"); + } + + @Test + void eventHandlers() { + String script = + """ + strat E { + on touched { + soundPlay(sound:6) + remove + } + on event(0x40, 30) slot 3 { + v0 += 1 + } + loop { yield } + } + """; + String asm = StratCompiler.compile(script); + assertTrue(asm.contains("onEvent ev_1, 0\n"), asm); + assertTrue(asm.contains("onEvent ev_2, 3\n"), asm); + assertTrue(asm.indexOf(".event 4, 0, on_1") < asm.indexOf("\nE:\n"), "entries before the code: " + asm); + String v = view(script, "E"); + assertTrue(v.contains("onEvent ev_0000, 0 // event type 4 → "), v); + assertTrue(v.contains("soundPlay(sound:6)\nremove\n"), v); + assertTrue(v.contains("v0 += 1.0\nreturn\n"), v); + assertFalse(v.contains("goto"), v); + } + + @Test + void parameterNamesFromTheSchema() { + String asm = StratCompiler.compile( + "strat P { if (snapToFloor) { self.y = self.floorHeight } }", java.util.Map.of("snapToFloor", "v0")); + assertTrue(asm.contains("pushVar v0\n"), asm); + // the script's own alias wins + asm = StratCompiler.compile( + "strat P { alias snapToFloor = v4\n v0 = snapToFloor }", java.util.Map.of("snapToFloor", "v0")); + assertTrue(asm.contains("pushVar v4\n"), asm); + } + + /** Old and new opcode names assemble to the same words (op-aliases.tsv). */ + @Test + void renamedOpcodesKeepTheirOldNames() { + StratAssembler.Layout l = + new StratAssembler.Layout(16, java.util.List.of(), java.util.List.of(), java.util.List.of()); + int[] a = StratAssembler.assemble("x:\n flagEC10000 1\n flagEC2 1\n flagEC100 0\n hudReset2\n end", l) + .words(); + int[] b = StratAssembler.assemble( + "x:\n freezeOffCamera 1\n touchable 1\n noFloorPhysics 0\n hudResetNoop\n end", l) + .words(); + org.junit.jupiter.api.Assertions.assertArrayEquals(a, b); + assertEquals("freezeOffCamera", OpTable.get().byName("flagEC10000").name()); + assertEquals("freezeOffCamera", OpTable.get().alias("FLAGEC10000").name()); + assertTrue(StratCompiler.compile("strat A { flagEC10000<1>() }").contains("freezeOffCamera 1")); + } + + /** unit:Name resolves through the layout's unit names. */ + @Test + void unitNames() { + StratAssembler.Layout l = new StratAssembler.Layout( + 100, java.util.List.of(), java.util.List.of(), java.util.List.of(16, 40)) + .withUnitNames(java.util.Map.of("Other", 1)); + int[] w = + StratAssembler.assemble("x:\n address unit:Other+0x8\n end", l).words(); + assertEquals(48, w[1]); + StratAssembler.AsmException e = assertThrows( + StratAssembler.AsmException.class, () -> StratAssembler.assemble("x:\n address unit:Nope\n end", l)); + assertTrue(e.getMessage().contains("unknown unit name"), e.getMessage()); + } + + static final class CompileExceptionCheck { + static void fails(String src, String part) { + StratCompiler.CompileException e = + assertThrows(StratCompiler.CompileException.class, () -> StratCompiler.compile(src)); + assertTrue(e.getMessage().contains(part), e.getMessage()); + } } @Test diff --git a/src/test/java/com/eliasmueller/llamamod/format/strat/StratPseudoTest.java b/src/test/java/com/eliasmueller/llamamod/format/strat/StratPseudoTest.java index eedebdd..85a9cd0 100644 --- a/src/test/java/com/eliasmueller/llamamod/format/strat/StratPseudoTest.java +++ b/src/test/java/com/eliasmueller/llamamod/format/strat/StratPseudoTest.java @@ -125,6 +125,50 @@ class StratPseudoTest { assertEquals(List.of(toList(li.words())), List.of(toList(back.words()))); } + /** Jumps out of nested loops and to a return: labeled break/continue and return instead of goto. */ + @Test + void multiLevelBreaksAndJumpsToReturn() { + String src = + """ + Main: + outer: + pushVar v0 + jz skip + inner: + pushVar v1 + jz next + jmp out ; break out of both loops + next: + pushVar v5 + jz c2 + jmp ret ; leaves both loops to the return + c2: + pushVar v2 + jz cont + jmp outer ; continue the outer loop + cont: + jmpYield inner + skip: + jmpYield outer + out: + pushVar v3 + jz fin + jmp ret + fin: + push 1.0 + popVar v4 + ret: + return + """; + String t = StratPseudo.of(listing(src, "Main")).text(); + assertFalse(t.contains("goto"), t); + assertTrue(t.contains("entry_0000: loop {"), t); + assertTrue(t.contains("break entry_0000"), t); + assertTrue(t.contains("continue entry_0000"), t); + assertTrue(t.contains("if (v5) {\n return\n }"), t); + assertTrue(t.contains("if (!(v3)) {\n v4 = 1.0\n}\nreturn"), t); + } + static List toList(int[] a) { return java.util.Arrays.stream(a).boxed().toList(); } @@ -132,7 +176,7 @@ class StratPseudoTest { /** Over all units of the CD: balanced blocks, every remaining goto has its label, few gotos left. */ @Test void everyUnitIsWellFormed() throws IOException { - int gotos = 0, units = 0; + int gotos = 0, units = 0, labeled = 0; Pattern g = Pattern.compile("goto (\\w+)"); for (Path p : StratRoundTripTest.levels()) { StratRoundTripTest.Loaded l = StratRoundTripTest.load(p); @@ -144,7 +188,7 @@ class StratPseudoTest { StratPseudo ps = StratPseudo.of(li); units++; int open = 0; - Set labels = new HashSet<>(); + Set labels = new HashSet<>(), loopNames = new HashSet<>(); for (StratPseudo.Line x : ps.lines) { String s = x.text().replaceAll("\\s*//.*$", ""); if (s.startsWith("}")) { @@ -157,6 +201,10 @@ class StratPseudoTest { if (s.matches("\\w+:")) { labels.add(s.substring(0, s.length() - 1)); } + Matcher ln = Pattern.compile("^(\\w+): (loop|do|while)").matcher(s.trim()); + if (ln.find()) { + loopNames.add(ln.group(1)); + } } assertEquals(0, open, p + " unit " + u + ": unclosed block"); for (StratPseudo.Line x : ps.lines) { @@ -165,11 +213,16 @@ class StratPseudoTest { gotos++; assertTrue(labels.contains(m.group(1)), p + " unit " + u + ": goto without label " + x.text()); } + Matcher b = Pattern.compile("(break|continue) (\\w+)").matcher(x.text()); + if (b.find()) { + labeled++; + assertTrue(loopNames.contains(b.group(2)), p + " unit " + u + ": no loop named in " + x.text()); + } } } } - System.out.printf("script view: %d units, %d gotos%n", units, gotos); + System.out.printf("script view: %d units, %d gotos, %d labeled break/continue%n", units, gotos, labeled); assertTrue(units >= 1400); - assertTrue(gotos < 500, "gotos: " + gotos); + assertTrue(gotos <= 40, "gotos: " + gotos); } }