Variables

Without a symbol table from the original source code, this list is presented as speculation (but with some pretty solid investigation into the nature of some!)

AddressTypeVariableX-refNotesConfidence
400wGameBoardCellColumn (X position)28c74
28c74
292c8
2934e
29ce8
2d6fa
2d74e
2d774
2d7a2
2db8e
2deb8
2e018
2e3ae
3871c
38724
38784
5ad90
5b4f0
This is the entity’s grid X/column (tile or logical column), also persisted to the portal column table per slot. (Position % 40)
Persisted into TBLPortalColumn_26DF2

Read/modified as a column index during pixel/plot logic and per-step updates: e.g. LAB_PlotPixelAndStep_2D74E reads it (move.w …,D0), other paths add D7 into it (add.w D7,(EntityCOLUMN) at 2D774/2D7A2), and subtract it from D5 (2D6FA).
Stored into a per-portal table indexed by an entity/portal slot: move.w (EntityCOLUMN),(0,A3,D4*1) => TBLPortalColumn_26DF2 (2E018).
Captured/restored around stack saves (292C8/2934E) and loaded from an entity table via (0,A5,D4*1) (29CE8).
High
402wGameBoardCellRow (Y position)292ce
29348
29cf0
2d71a
2d754
2d780
2d796
2dec6
2e026
2e3a6
Entity’s grid Y/row (Position  / 40)
persisted into TBLPortalRow_26F1E

Used as the paired index to $400: read into D1/D4 (2D754/2DEC6), subtracted from D6 (2D71A), stepped with add.w D7,(EntityROW) (2D780/2D796).
Stored into TBLPortalRow_26F1E at (0,A3,D4*1) (2E026).
Saved/restored on the stack (292CE/29348) and initialised from (0x2,A5,D4*1) (29CF0).
High
404wGameBoardCellTypeFlags292bc
2935a
29ba2
29bae
2af54
2db8e
2dc46
2dd74
2dd86
2dd9e
2de26
2de5e
2de72
2dea4
2ded8
2e02e
2e246
2e26e
2e342
2e34e
2e364
2e376
2e386
A type/flags word for the active entity/portal:
Bits 7–4 function as a growth type identifier (e.g. circular, diamond, cross), bits 3–0 represent growth size; the increment pattern (7→8→9→A) in the 2×2 stamp sequence strongly suggests the size of the growth.
Upper bit15 selects flagged/portal flag (bit15 set at 2DE72), a control flag for execution paths.
Bit 15 clear (0): Takes the LSL #5 path, likely a simpler operation (e.g., scaling position).
Bit 15 set (1): Takes the table-driven path, possibly involving complex growth or portal logic

Sometimes used as a small counter/phase via addq.
Written with small constants in “life” render paths: #0x40 (29BA2) and #0x41 (29BAE).
Used as a typed/flagged field in control logic: pushed/popped (2DD74/2DE26), copied, ORed and incremented (or.w D5,(EntityTYPE) at 2E34E; addq.w three times at 2E364/376/386).
High bit explicitly set: ori.w #-0x8000,(EntityTYPE) (2DE72).
Also receives “PortalType_D6” (2E02E) and other small constants (#0x7 at 2E342).

Bit-15 is asserted either by building D0=$8000|byte then MOVE.W D0,$404 (0002DE56–0002DE5E) or by ORI.W #$8000,$404 (0002DE72); the very next consumer is MOVE.W $404,-(A7) at 0002DD74 inside SUB_ProcessPortalGrowthUpdate_2DD46.
In SUB_UpdateGameBoards_2DE80, $404 is copied to D2 and branched on sign (BPL at 0002DEDE): with bit-15 clear it follows a simple LSL #5 index path (0002DF0C); with bit-15 set it takes a table-driven path (0002DEE8–0002DF0A).
During 2×2 bitmap placement (0002E300+), it’s set to #$007 then ORed with (D5 & $0F0) (0002E342–0002E34E), and subsequently incremented alongside the position (0002E364/0002E376/0002E386), showing low-nibble as size and upper nibble as type.
Also written with small constants #$40 / #$41 in life-render code (00029BA2/00029BAE), confirming its general “type/flags” role.
High
40Aw 
GameBoardCellIndex
292c2
29354
29bbe
2af5a
2dd5c
2dd6e
2ddc4
2ddd0
2dddc
2dde6
2ddf0
2ddfc
2de06
2de12
2de1c
2de2c
2de3a
2de8c
2e008
2e240
2e27c
2e33c
2e35e
2e36e
2e380
2e39c
A linear position index into the playfield/map (row-major), used for adjacency and as the canonical “position” of the entity/portal.
Used as a single index for 3×3 square neighbourhood scan.

ProcessAdjacentSquares_2DDD0 applies a fixed pattern: -0x29, +1, +1, +0x26, +2, +0x26, +1, +1, later +0x27 elsewhere (2E36E). That’s the classic 3×3 sweep with a fixed row stride (≈0x27/0x26).
Frequently copied to/from D-regs (2DD5C, 2DD6E, 2DDC4, 2DE8C) and saved/restored (2DE2C).
Used as the base for “growth” calc (2DE3A) and portal position writes (2E008/2E240/2E27C/2E33C).
High
40CwCurrentWorking
GameBoardCellIndex
2d89e
2dff6
2e0ce
2e390
A working/cursor index used during iterative operations on the current entity/portal (scratch/cursor board index during growth scan)

Loaded/stored as the “current” location in workflows: move.w D0,(…40C) (2D89E), move.w PortalLocationData_D5w,(…40C) (2DFF6), later read into D1 (2E0CE) and written back again (2E390 “StoreCursorAndRepeat”).
High
40EwRenderModeShadow2da54
2da74
2dcda
A latched copy of the current render config for inner routines (avoids re-reading the global or passes as a cheap “parameter”).

Mirrored from FaceAnimStep_410 (2DA54), sometimes overwritten from D0 (2DA74), and then read by SUB_2DCDA.

Role inferred from a single mirroring operation at 2DA54 into $40E; exact downstream consumers not fully closed.
Med-High
410wFaceAnimStep2d9a8
2d9b0
2da2c
2da54
2da6e
2db76
2dbb4
Face squash animation step index — indexes into TBL_GrowthPathTail_33A78 to drive the current step of the face scale/squash render. Written from the animation table at 2D9A8, compared/dispatched in render paths (2D9B0, 2DA2C, 2DA6E, 2DB76, 2DBB4). Mirrored from/to $40E (RenderModeShadow).High
412wRenderPhaseTimer28ebc
28ee4
28f36
28f5e
29004
2902c
2daa2
2db4e
2dbf2
2dc06
2dc5a
2dcd0
 A general-purpose phase/countdown timer used across title/game render phases.

Loaded with various durations (e.g., #0xAF, #0x64, #0x40, #0x1) then repeatedly decremented (subq.w #1 at many sites: 28EE4/28F5E/2902C/2DB4E/2DCD0).
Re-initialised when switching render types (2DAA2, 2DC5A, 2DBF2, 2DC06).
High
414lSubphaseTicks2dab2
2db1c
2dc62
2dcbc
A tiny subphase tick counter
Set to #4 (2DAB2, 2DC62) and decremented each tick/frame (2DB1C, 2DCBC).
High
418lDelayCounter2dbe4
2dc2e
Another short delay counter
Set to #0x20 then decremented (2DBE4/2DC2E)
High
41AwVBLTickCounter29292
2929e
VBL tick counter incremented every non-title-screen frame (29292). ANDed with LevelActiveGate_4D6 (2929E); non-zero result gates the copper-list update path. Together with $4D6 this forms a simple “is gameplay active” copper gate.High
420wCurrentGrowthValue 2dc46
2e050
2e088
A per-row growth value / presence flag fetched from a growth table (A3 base, D6 row)

Cleared during a structure init (move.l #0,(A0)+ at 2DC46).
Later loaded from a row-indexed table (0,A3,D6*1) (2E050) and immediately tested (2E088 “GrowthRow1_2E088”: tst.w (Growth_420))
High
422wA0EndPtr2db66
2db6c
2dbc6
2dbcc
2dc3c
An end pointer for a copy/fill loop (sentinel = start + size).
Set from A0, then a constant added (+$400 or +$420) and later compared against A0 as a loop bound (cmpa.l (0422),A0, 2DC3C), with A0 presumably walking the block.
High
42EwGrowthWriteOffset_ScreenA2ce44
2ce62
2ce8e
2df0e
2df56
A word address/offset cursor into a growth-related table with long-sized (4-byte) entries (since it advances by 4)

Per-buffer growth write cursor for SCREEN A. When the active screen is ScreenA it uses $42E first, then uses $430 for the second pass (0002CE78).

Used as an address/offset source: movea.w (…42E),A4 (2CE44/2CE62).
Cleared (2CE8E), read (2DF0E), and stepped by 4 (2DF56).
High
430wGrowthWriteOffset_ScreenB2ce2e
2ce5a
2ce78
2df22
2df4e
Per-buffer growth write cursor (word offset) for the other screen buffer (SCREEN B), advanced by 4 bytes per cell write and cleared after use

In SUB_UpdateOrganicGrowth_2CE20, when the active screen is not ScreenA it loads A4 from $430 (0002CE2E), renders a growth pass, then clears $430 (0002CE5A).
In the writeout path, SUB_UpdateGameBoards_2DE80 tail), if the active screen is not ScreenA it reads $430 into D4 (0002DF22), performs stores, then advances it by 4 (0002DF4E). The $42E path mirrors this for ScreenA.
High
432wFaceFlipTableOffset29e0c
2b3c6
2b3e2
2d992
2d9d4
2da18
2da9a
Table offset into the face flip/squash animation data (+2 per tick during animation). Cleared at state injection points (29E0C, 2B3C6, 2B3E2, 2D9D4) and at DayNightTimer==37 (Tarot injection). Read by the face render dispatcher (2D992/2DA18) to index the current animation frame. Drives the face squash sequence for day/night flip and Tarot reveal.High
434wFaceOpenAnimOffset28d12
29e12
29e8a
2b1da
2b2da
2b312
2b39a
2b3cc
2b3e8
2cff4
2d00e
2d034
2d072
2d922
2da08
Face-open animation offset (+2 per tick during face animation). One of two timer gating conditions for DayNightTimer: timer only ticks when this is 0 AND GraphicAnimFrameState_446==0. Advanced by 2 (2D00E), reset (2D034), compared to threshold $292 (2B2DA). Saved/restored via $438. Stretched day length = 150 DayNight ticks + combined durations of any face animation runs.High
438wFaceAnimationCounter_Save2d072
2da0e
Save slot for the above.High
43AaddrActiveCentralFaceGfxPtr28e00
2905c
2908e
2b37c
2cffe
2d03a
2d99a
Active/selected central face graphic pointer (resource currently being loaded/displayed)

Set to several face asset addresses (#0x5D546, #0x5E546, #0x60546) and used by LAB_LoadDefaultFace_2CFFE as A0.
Also gets assigned from $43E in a couple of paths (2D03A/2D99A).
High
43EaddrFrontGfxBufferPtr25e20
2607c
26e58
28162
285cc
2865e
28df6
29052
29084
29e18
29e2e
2b376
2d03a
2d7cc
2d7d2
2d99a
2da4e
Double-buffer pointer pair – front/current graphics buffer (or render base) – “current” graphics buffer base; swapped with $442

Both 43E and 442 get initialised to various addresses; one is often _graphicsY (28162 → 043E) or from D2 (28168/2B382 → 0442).
Swapped as a pair in SUB_SwapScreenBuffers_2D7CC:
A3 ← (043E); then (043E) ← (0442); then (0442) ← A3 (2D7CC/2D7D2/2D7DC).
Many render paths read (043E) into A3 for further graphics work (2D7CC, 2DA4E).
High
442addrBackGfxBufferPtr28168
285d6
28668
2b382
2d7d2
2d7dc
Back/next graphics buffer
(see above) – “other” graphics buffer base; swapped with $43E
High
446wGraphicAnimFrameState28ccc
28ce2
29e6e
29e7a
29ede
2b30c
2b394
2b3d2
2b3ee
2d02a
2d8d6
2d906
2d92a
2d9b8
2d9da
2da5e
Face animation state for the central face/screen graphic. NOT the main game mode (that is GameControlMode at $5B2). Controls which face render routine runs in Step 4.

0: Idle — automated sequence (TBL_FaceTransitionSequence_33E3C) advances to next state.
1: Day/night squash (SUB_RenderFaceSquashFromCentre_2DB5A) — triggered at DayNightTimer==150.
2: Automated background spin variant A (LAB_RenderGraphicsType3_2DC56).
3: Level-complete / automated spin (LAB_RenderGraphicsType2_2DBB4).
4: Tarot reveal (LAB_RenderTarotFaceComposite_2DAA2) — injected manually at DayNightTimer==37 (2B3EE), NOT in automated sequence.
5: Automated background spin variant B.

Automated sequence (loops): [1→3→2→5→1→3…]. State 4 deliberately omitted from sequence. Dispatch table: TBL_FaceTransitionDispatch_33E28.
High
44Aw StateFrameIndex2d8e0
2d8e6
2d8fc
A per-state frame counter/index – counts ticks since entering the current GameState. Increments then cleared on state change.

Incremented each tick within the state manager (2D8E0), read (2D8E6), and cleared (2D8FC)

Limited to 3 xrefs; increment/read/clear pattern is clear but the exact state-machine context it tracks was not fully closed.
Med-High
44CaddrCurrentScreenDescPtr26e84
26f64
283f2
284f2
28524
2856a
285ae
2864c
28782
287ca
287d8
295d4
29e5a
29f3a
2c9e0
2cb42
Pointer to the current screen/scene descriptor (fed into A5 as the working base for the code that follows)

Initialised to many constants (#0x343EA, #0x3560A, #0x35AA6, …), then used as an address source for A5 in WhichScreen_2C9E0/2CB42.
High
450wLarge Eyeball Bitmap X28462
2c69c
2c6fa
2c788
2c79c
2c7b8
2c7d4
Base X for a 4-sprite eye layer (“group 1”); low byte feeds four sprite X bytes.

Init: move.w #-0x8000,(Eye_450) (28462).
Step pairs: subi.w #$66 (2C69C) / addi.w #$66 (2C6FA).
Low byte copied to four sprite param bytes at $356A7, $356CD, $356F3, $35719 (2C788/79C/7B8/7D4).
High
452wLarge Eyeball Bitmap Y2846a
2c63e
2c758
2c792
2c7ae
2c7ca
2c7e6
Base Y for the same 4-sprite layer as $450.

Init: move.w #$5500,(EyeXY_452) (2846A).
Step pairs: subi.w #51 (2C63E) / addi.w #$33 (=51) (2C758).
Low byte copied to $356A9, $356CF, $356F5, $3571B (2C792/7AE/7CA/7E6).
High
454wMed Eyeball Bitmap X28472
2c6a4
2c702
2c7f0
2c804
2c820
Base X for a 3-sprite eye layer (“group 2”).

Init: move.w #-0x7800 (28472).
Step pairs: subi.w #$8E (2C6A4) / addi.w #$8E (2C702).
Low byte → $3573F, $35765, $3578B (2C7F0/804/820).
High
456wMed Eyeball Bitmap Y2847a
2c646
2c760
2c7fa
2c816
2c832
 Base Y for group 2.

Init: move.w #$5700 (2847A).
Step pairs: subi.w #71 (2C646) / addi.w #$47 (=71) (2C760).
Low byte → $35741, $35767, $3578D (2C7FA/816/832).
High
458wSmall Eyeball Bitmap X28482
2c6ac
2c70a
2c83c
2c850
2c86c
 Base X for a 3-sprite eye layer (“group 3”).

Init: move.w #-0x7400 (28482).
Step pairs: subi.w #$AC (2C6AC) / addi.w #$AC (2C70A).
Low byte → $357B1, $357D7, $357FD (2C83C/850/86C).
High
45AwSmall Eyeball Bitmap Y2848a
2c64e
2c768
2c846
2c862
2c87e
 Base Y for group 3.

Init: move.w #$5900 (2848A).
Step pairs: subi.w #86 (2C64E) / addi.w #$56 (=86) (2C768).
Low byte → $357B3, $357D9, $357FF (2C846/862/87E).
High
45CwEye? Unused? 28492Set to $9000 at 28492. No reads or other uses.

Written to constant #$9000 at init ($28492); no reads found anywhere in the traced range. Likely vestigial Eye init code for a sprite layer that was stripped from the final game.
Med
45EwEye?  Unused?2849aSet to $5B00 at 2849a. No reads or other uses.

Written to constant #$5B00 at init ($2849A); no reads found anywhere in the traced range. Likely vestigial Eye init code for a sprite layer that was stripped from the final game.
Med
460wMed Iris Bitmap X284aa
2c6bc
2c71a
2c8b8
2c8cc
Base X for a 2-sprite eye layer (“group 5”).

Init: move.w #-0x6D00 (284AA).
Step pairs: subi.w #$1A6 (2C6BC) / addi.w #$1A6 (2C71A).
Low byte → $3586F, $35895 (2C8B8/8CC).
High
462wMed Iris Bitmap Y284ca
2c65e
2c778
2c8c2
2c8de
Base Y for group 5.

Init: move.w #$5600 (284CA).
Step pairs: subi.w #211 (2C65E) / addi.w #$D3 (=211) (2C778).
Low byte → $35871, $35897 (2C8C2/8DE).
High
464wLarge Iris Bitmap X284a2
2c6b4
2c712
2c888
2c89c
Base X for a 2-sprite eye layer (“group 4”).

Init: move.w #-0x7000 (284A2).
Step pairs: subi.w #$14C (2C6B4) / addi.w #$14C (2C712).
Low byte → $35823, $35849 (2C888/89C).
High
466wLarge Iris Bitmap Y284c2
2c656
2c770
2c892
2c8ae
Base Y for group 4 (Large Iris, 2-sprite layer).

Init: move.w #-0x6B00 (284C2).
Step pairs: subi.w #$1E2 (2C656) / addi.w #$1E2 (2C770).
Low byte → sprite Y fields at 2C892/2C8AE.
High
468wSmall Iris Bitmap X284b2
2c6c4
2c722
2c8e8
2c8fc
Base X for a 2-sprite eye layer (“group 6”).

Init: move.w #-0x6B00 (284B2).
Step pairs: subi.w #$1E2 (2C6C4) / addi.w #$1E2 (2C722).
Low byte → $358BB, $358E1 (2C8E8/8FC).
High
46AwSmall Iris Bitmap Y284d2
2c666
2c780
2c8f2
2c90e
Base Y for group 6.

Init: move.w #$5900 (284D2).
Step pairs: subi.w #241 (2C666) / addi.w #$F1 (=241) (2C780).
Low byte → $358BD, $358E3 (2C8F2/90E).
High
46CwGlobal Eye Position X284ba
2c678
2c696
2c6d6
2c6f4
2c918
Global eye base X (accumulator), also mirrored to a UI/debug byte at $35907

Init: move.w #-0x6800 (284BA).
Read/modify/write cycles at 2C678→2C696 and 2C6D6→2C6F4; low byte copied to $35907 (2C918).
High
46EwGlobal Eye Position Y284da
2c616
2c620
2c638
2c734
2c752
2c922
Global eye base Y (accumulator), also mirrored to a UI/debug byte at $35909.

Init: move.w #$5B00 (284DA); read/compare (cmpi.w #22528) (2C620).
Read/modify/write cycles at 2C616→2C638 and 2C734→2C752; low byte copied to $35909 (2C922).
High
470wEyeBlinkPhase2c92c
2c944
2c94e
2c968
Blink state/phase in steps of $10; reset at end of blink

Read, then addi.w #$10,(Eye_470) (2C92C/944/94E), then cleared (2C968).
Values 00→10→20→30→40→50→00.
High
472wJoystickX296d4
2b700
2b748
2bfbc
2bfc8
2c058
2c070
2c0b6
2c0ca
2c0de
2c1b8
2c1ce
2c3cc
2c3e2
Discrete horizontal joystick direction (−1/0/+1), source for follower/filtered X and star-chart input.

Read as the primary X input in LAB_ReadJoystick_2B700 and SUB_ProcessJoystickInput_2BFBC (move.w (…472),D2). Mirrored to multiple consumers (JoyX1 at 2B748/2C3CC/2C3E2; _JoystickX at 2C0CA). Explicitly written as 0, -1, +1 (2BFC8, 2C058, 2C070). Polled for change/compare (tst.w at 2C0B6, cmp.w at 2C0DE). Also read for clamping/flow at 2C1B8/2C1CE.
High
474wJoystickY2b706
2b74e
2bfc2
2bfce
2c08e
2c0a6
2c0c0
2c0d4
2c0f2
2c1be
2c1f6
2c3d2
2c40e
2c4ca
Discrete vertical joystick direction (−1/0/+1), fanned out to multiple systems (UI/star-chart/gameplay).

Read as Y input into several game and UI sinks (directionjoystick 2B706, _joysticky 2B74E, _JoystickY 2C0D4). Explicit writes to 0, −1, +1 (2BFCE, 2C08E, 2C0A6). Tested/compared (tst.w 2C0C0; cmp.w 2C0F2). Mixed into D0 with OR at 2C1BE and reused by star-chart paths (2C3D2/2C40E/2C4CA).
High
476wJoystickXFollower2812a
2ab0e
2c0ca
Sticky horizontal aim latch used by the bullet-fire path. Updated from raw X only when the current frame has non-zero X or Y joystick input — so it holds the last direction the player aimed and is used to determine bullet direction even if the player is not pressing the stick that frame.

Initialised to #4 at 2812A (non-zero = right). Updated from JoystickX_472 at 2C0CA. Tested by the fire routine at 2AB0E. C# field: JoystickXFollower_476.
High
478wJoystickYFollower2ab24
2c0d4
Sticky vertical aim latch paired with JoystickXFollower_476. Updated from raw Y only when the current frame has non-zero joystick input; holds the last aimed Y direction for bullet fire.
Updated from JoystickY_474 at 2C0D4; tested by the fire routine at 2AB24. C# field: JoystickYFollower_478.
High
47AwLastKeycode288e2
288ee
288fa
28916
2892c
2c152
Last keycode latch used by menu/flow logic (compared against specific rawkey values).
Cleared in several places (288E2/288FA/2892C). Compared against #$74 and #$7E (288EE/28916). Written from D1 in LAB_StoreKeycode_2C152 (2C152)
High
47Cw InputArmedFlag28a54
2c042
2c49c
Polled (tst.w at 28A54). Set to #1 at 2C042 and 2C49C.

Pattern is clear (polled at $28A54, set at $2C042/$2C49C) but the owning flow is small and its broader trigger context was not fully traced.
Med
47EwJoystickFIRE2884c
288ce
288d4
28c94
28cd8
28cf2
28d08
28d22
28d58
28d6a
28d74
28e3a
28e66
28eaa
28ed0
28eda
28ef4
28f26
28f4a
28f54
28f6e
28fa2
28fc0
28ff0
29018
29022
2903c
2906e
290a0
290be
29134
29152
29170
2918e
291ac
291f2
29204
29568
2aa56
2b73e
2bfd4
2c002
2c26e
2c292
2c436
009fe2c2
009fe2e2
 Joystick fire button latch

Extensively tested across demo, instructions, and gameplay (many tst.w sites). Asserted with #1 (2C002). Cleared frequently (2884C/288CE/291F2/29568/2BFD4/2C292). Also present in a short absolute‐word mirror (9FE2C2/9FE2E2).
High
482w ActionCooldown2aa44
2aa4c
2aac0
2aad4
2aaf6
 Small countdown used in the 2AAxx input/action cluster (debounce/cooldown/sequence step)

Polled/decremented (2AA44/2AA4C), preset to #6 or #3 (2AAC0/2AAD4), cleared (2AAF6).
High
484wPortalListIndex297ea
2982c
2b47e
2d874
2df86
2dfee
2e182
Loaded into a loop index before scanning the portal-location list: MOVE.W (PortalCounter_484).l,D3 at 2E182, then iterated backwards in steps of 2 with SUBQ.W #2,D3 while comparing the current candidate slot against a position: CMP.W 0(A6,D3.W),D1 (loop at 2E190–2E19C). When a match is found, the slot is cleared: CLR.W 0(A6,D3.W) at 2E19E (i.e., remove portal). Elsewhere it’s read to size list-driven logic (D6 at 297EA/2D874, D5 at 2982C, D4 at 2DF86). It is incremented by 2 on updates: ADDQ.W #2,(PortalCounter_484).l at 2DFEE – matching the word (2-byte) granularity of each portal entry in the A6 table.High
486wGrowthColumnCounter2e04a
2e058
2e05e
2e06a
 Column loop index (1..40) for growth row processing

Cleared at row loop start (2E04A), incremented per column (2E058), compared against #1 and #$28 (2E05E/2E06A).
High
488wStarChartUnfurlCounter2a102
2a1a6
2a1ac
2a1b8
2c440
Star-chart parchment unfurl counter. Runs 0→150 across the unfurl animation of the star-chart screen; the star-chart body polls this to know when the scroll bars have finished animating.

Incremented at 2A102, compared against thresholds at 2A1A6/2A1AC/2A1B8, also tested in star-chart path 2C440. Raising StarChartRefreshPendingFlag_524 at completion. C# field: StarChartUnfurlCounter_488.
High
48AaddrPointsToAdd26994
292da
2996a
29d30
2adae
2adf6
2d4c8
Pending score
Zeroed at scene start: MOVE.L #0,(pointstoadd) (292DA). Accumulates diverse score deltas across gameplay: ADDI.L #$BB8 (+3000) at 2996A, ADDI.L #175 at 29D30, ADDQ.L #3 at 2ADAE, and ADD.L D2,(pointstoadd) at 2ADF6. Polled via MOVE.L (pointstoadd).l,D0 at 2D4C8 (used by the score update/commit routine in that region).
High
48Eaddr PaletteStreamPtr293e2
293f0
Word-step stream pointer (cursor) into a colour/palette data sequence.

Added into A0 (adda.l (…48E),A0 at 293E2), then advanced by 2 (addq.l #2,(…48E) at 293F0). In the same code region, a word is fetched from (A0) into $496 and written to COLOR00 (293F6/293A6).

Render-owned; used only in the copper/palette IRQ path. The simulation does not implement palette streaming.
Low
496w Color00Latch293a6
293f6
Current COLOR00 value latch (staging between table read and hardware write).

Latched from (A0) (293F6), then written to CustomChips.COLOR[0] (293A6)

Render-owned staging latch between palette table read and COLOR00 hardware register write. No simulation role.
Low
498b PaletteControlByte293bcOnly observed as a byte read into D0 (293BC).
Byte control/state value used in the same palette/IRQ block (exact role unclear with a single read).


Single read site in the palette/IRQ block; render-owned. Exact role beyond byte feed into D0 not confirmed.
Low
49Cb FrameToggleByte293c8
293d0
Frame/parity toggle byte to perturb an index/value (e.g., flicker/alternator).

Toggled with eori.b #$1,(…49C) (293C8), then added into D0b (293D0).

Render-owned EOR-toggle byte used to perturb a colour index each frame (simple alternator). The simulation does not implement this.
Low
49EwSunsetCompleteFlag2948e
295b4
295c2
Explicitly set to 0 / 1 (2948E/295B4). Tested in flow (295C2).

Boolean flag pattern is clear (set 0/1 at $2948E/$295B4, tested at $295C2). Render-owned sunset completion flag; the simulation does not implement sunset rendering.
Med
4A0w SunsetFadeCounter29500
29506
29512
 Increments, compared to #2, then cleared (29500/29506/29512).
2-step cycle counter (0→1→(>=2?)→0)

Clear 0→1→(>=2)→0 modulo cycle at $29500-$29512. Render-owned sunset pacing; the simulation does not implement sunset rendering.
Med
4A2wSunsetBlitterCounter2946c
29472
294f2
295bc
Sunset effect blitter tick (even-step counter)
Read/incremented by 2 in two paths, cleared at 295BC (2946C/29472/294F2/295BC).

Even-step blitter tick counter for the sunset effect. Pattern (read, +2, clear) is clear; full blitter sequence not traced. Render-owned.
Med
4A4addr StarChartPtr_Pending2d0be
2d0c8
Pending/new star-chart data pointer (staged before activation).
Written from A0 (2D0C8). Later copied into $4A8 (2D0BE).

Render-owned pending star-chart data pointer. Written then staged into the active slot ($4A8). Pattern clear.
Med
4A8addr StarChartPtr_Active2d0b4
2d0be
Active star-chart data pointer
Compared against A0 to detect change (2D0B4). Updated from $4A4 (2D0BE).

Render-owned active star-chart data pointer. Compared against A0 to detect change; updated from $4A4. Pattern clear.
Med
4B2wGuardianType2821c
28e50
29d6a
2a622
2a65c
2a868
2b17a
2bc66
2bd30
Guardian type selector (0..6)

0 = Devil, 0001 = Blades, 0002 = Hand, 0003 = Hydra, 0004 = Spider, 0005 = Firefly, 0006 = Giant Maggot
High
4B4wEnergy2a37e
2a3a2
2b324
2be8c
2be92
Energy. Values 0 < 47 > 95 (0, 2f00, 5f00 bit shifted 8 bits to the right, so divided by 256) in 0x20 steps, byte-significant for UI

Written from energylevel (2A3A2), read/subtracted/updated in gameplay (2A37E/2BE8C/2BE92), and byte-read at 2B324 (UI).
High
4B8wDayNightTimer2b3a4
2b3aa
2b3b8
150-tick day/night cycle counter. Incremented each VBL at 2B3A4; when it reaches 150 it triggers the face-squash animation (GraphicAnimFrameState_446 = 1); at 37 it injects the Tarot reveal (GraphicAnimFrameState_446 = 4). Cleared at 2B3B8 when the threshold fires. C# field: DayNightTimer_4B8.High
4BAwDay/Night Flag28158
2ad6a
2ada4
2b36a
2b424
2b454
2d9ea
0 = Night, 1 = DayHigh
4C4w MovementEnabled2835a
2b67e
2b698
2bf86
2c0e8
Movement-allowed flag set by input layer
Set/cleared in joystick handling (2835A/2B698/2BF86/2C0E8) and polled (2B67E).
High
4C6w CarryingGoodSporeFlag298cc
298e0
2aa60
2aab0
2aaba
2b7e4
2bdf6
2be18
Tested by pickup/use sites (2AA60/2BDF6), read for logic (298CC/2AAB0/2B7E4), cleared at state changes (298E0/2AABA), assigned from A2w on pickup (2BE18)High
4C8wEvilSporeLaunchTimer2b4fa
2b504
2b5cc
Polled/decremented in flight logic (2B4FA/2B504), loaded from D3 at 2B5CC
dec by 1 from BD to 00
High
4CAwSporeLaunchDelayTimer2b514
2b51e
2b528
2b5d2
 Launch delay countdown for evil spore

Preset #8, then tested/decremented, then cleared (2B514/2B51E/2B528/2B5D2).
High
4CCw EvilSporeInFlight Flag2b532
2b53a
2b572
2b5d8
 In-flight state flag for evil spore

Set to #1 on launch (2B532), tested (2B53A), cleared at completion/abort (2B572/2B5D8).
High
4D0w UIBlitStartOffset28384
285e0
28656
2d0d4
52a00
Initialised to different constants (28384/285E0/28656). Read at 2D0D4

Render-owned blitter start offset; set to different constants at mode transitions ($28384/$285E0/$28656). No simulation readback.
Low
4D2addrForbiddenCellBitmapPTR2837a
285e8
2878c
2e0f6
Stores the address of the forbidden cells bitmap that cannot be written into during growth.
Runtime pointer to a 1-bit bitmap used as a write-forbid mask for both growth and portal writes.
It is set to 33EEE at $2837A for in-game
It is set to 33FE8 at $285E8 for demo/instructions
High
4D6wLevelActiveGate2816e
285fc
28686
28d8e
29298
292e8
29ac6
29e82
29ece
Copper-update gate. ANDed with VBLTickCounter_41A at 2929E to gate the copper-list update path. Set to 1 during active gameplay; cleared at mode transitions. Also tested directly (29298/292E8) as a “gameplay active” flag.High
4D8wDayNightChangeTrigger2b3be
2d9e0
2da02
One-shot trigger to flip/render day-night transition.
Set to #1 (2B3BE), polled then cleared in the render/state path (2D9E0/2DA02).
High
4DAw EnergyUpdateTimer2b32e
2b33c
2b346
2b34c
Energy update timer/phase used to pace energy gain/loss

Compared to D1, dec/inc around energy update (2B32E/2B33C/2B346/2B34C)
High
4DCw EnergyStepCounter2b2f6
2b302
2b31c
 0..7 step counter for energy animation or staged updates
Compared to #7, incremented each step, cleared on wrap/reset (2B2F6/2B302/2B31C).
High
4DEw TwoFrameDelay2c53a
2c544
2c592
Tiny 2-frame delay used in the 2C53x cluster (UI/input)
tst.w, subq.w #1, preset to #2 (2C53A/2C544/2C592).
High
4E0wSunsetPhase27098
2a072
2a07e
Sunset effect phase accumulator.
Incremented and read as phase (2A072/2A07E). Also appears in a data table ref at 27098.

Render-owned sunset phase accumulator. The simulation does not implement the sunset rendering path.
Low
4E2wSunsetOffset2a092
2a0ca
Sunset effect position/offset accumulator (coarse step)
Read and increased by #$A0 (2A092/2A0CA)

Render-owned sunset position accumulator (coarse step). The simulation does not implement sunset rendering.
Low
4E4wSunsetActiveFlag2a064
2a0d8
Polled (2A064) and set to #1 (2A0D8).

Render-owned sunset active flag. The simulation does not implement the sunset rendering effect.
Low
4E6wSunsetEnableFlag2940c
29488
2a042
2a05a
Sunset effect enable/armed flag (used by animation manager).
Polled (2940C/2A05A), set and cleared (2A042/29488).


Render-owned sunset armed/enable flag. Set and cleared by animation manager ($2940C/$29488/$2A042/$2A05A). Pattern is clear.
Med
4E8wSunsetSunYOffset28af4
29416
2a016
2a02e
2a036
Sunset object position (with range checks)
Initialised to #$60; read; incremented by #$A0; compared to two bounds #$293F and #$1A40 (28AF4/2A016/2A02E/29416/2A036).
High
4EAwSunsetCopperEffectTimer28afc
29f76
29f80
2a04a
Title-screen timer for the duration of the sunset copper effect.
Preset #$3F; polled/loaded; decremented each tick (28AFC/29F76/29F80/2A04A)
High
4ECwSunset Frame Counter 28afc
29f76
29f80
2a04a
Modulo-3 tick for the sunset sun descending (sub-frame cadence used to pace the sun descnding animation/blits independently of the main phase/position counters)
Tight 0..2 frame cycle: ADDQ.W #1,(…4EC) (29FFE), compare CMPI.W #3,(…4EC) (2A004), then reset CLR.W (…4EC) (2A010). This sits alongside the sunset system where other state includes SunsetPhase_04E0, SunsetOffset_04E2, SunsetActiveFlag_04E4, SunsetEnable_04E6, and position SunsetY_04E8; the modulo-3 cadence gates per-frame sub-stepping of the effect.
High
4F0wActiveTarotMode28e0a
29ad8
2aac8
2ab4e
2ab5a
2ab84
2b6bc
2b6e4
2b80e
2b840
2b8d0
2bbae
2be48
2be54
2bed0
2beda
2bee4
2bf28
2bf6e
2d4a6
2d81c
2d8b2
The current firepower mode derived from the tarot system; also gates other mechanics (growth suppression at 7).
Written from the active tarot card and then incremented by 1 on pickup; later used as an index into a timer table to seed PowerUpTimer_528.
MOVE.W Tarot,CurrentTarotCard_4F0 / ADDQ.W #1,CurrentTarotCard_4F0 / table lookup into PowerUpTimer_528 at 2BED0–2BEF2.
Drives bullet patterns (double/triple shot) in the fire routine, via compares against 8 and 9 (and 6 for a special behaviour).
Consulted during growth to suppress evil growth when firepower is 7.

Read in the bullet-fire routine to alter shot patterns: 2×shot if value==6, 3×shot if value==9, by offsetting D5/D6 (bullet X/Y) and spawning extra bullets.
Also copied from Tarot ($526) during card changes: move.w (tarot_526).l,(CurrentTarotCard_4F0).l. C# field: ActiveTarotMode_4F0.
High
4F2wPlayerX296de
2b862
2b87c
Player’s X position.

Joystick read maps to movement tables, but PlayerX itself is sourced from a level/init table at PlayerXPosition_347CA and copied into PlayerXFollower.
Title/init paths set PlayerXPosition_347CA then various sprite updates consume it.
High
4F4wPlayerY2b86c
2b882
Player’s Y position
Same pattern as X: copied into PlayerYFollower; written from PlayerYPosition_347CC during setup.
High
4F6wPlayerXFollower2b824
2b862
Smoothed/lagged copies of player position used by several subsystems
Read by input/render glue (used where immediate player X isn’t desired), and kept in lockstep with PlayerX.
High
4F8wPlayerYFollower2b834
2b86c
Paired latch for Y; updated with PlayerY. (Same update pattern as X follower.)
lags $4F4 by 1 vbl?
High
4FCw EnergyUpdateInhibitFlag2a5c8
2ad60
2bf3e
Checked before converting spore value to energy in the spore processing loop; if non-zero, the energy update path is skipped.
Tested as a boolean guard in multiple energy/update paths (tst.w (…4FC)). No writes in those blocks – only gate checks.
High
4FEwCurrentEntityTableBasePtr28370
284e8
285f2
29e64
29f44
2b888
Base pointer to the active entity pool table. Written as TBL_PlayerMovementData_347C6 at $28370 during level init; read into A0 as the base for the entity loop in LAB_EnterCollisionLoop_2B888. Also written at demo/instructions init paths ($284E8/$285F2) with different table bases for those screens.High
502wGameOver28898
28942
29920
2cfca
Boolean Global “game over” flag.
Polled in the main loop to branch into the Game Over flow; set to 1 when the game ends. (tst.w GameOver → branch to grave/ending; later move.w #1,GameOver.)
High
504wBulletFiringCounter2ab90
2ab96
2aba2
2bf8e
Per-frame range counter for bullet.
Incremented each frame while firing; when it reaches 9, resets to 0 and allocates/updates bullet slots using A0/A1/A2 patterns tables. The counter is explicitly compared with #9 and gated.
High
506wEvilPortalsRemaining28ffa
2dfd0
2e1aa
Incremented when portals are created; decremented when portals are destroyed/overrun. Gate for level completion logic.High
508wGoodPortalsRemaining2dfba
2e1d6
Incremented/decremented alongside evil portal counterpart, checked during portal overrun to decide loss.High
50AwLevelWonFlag292f6
29e52
2b102
2b4f0
A separate “win flag” polled in a few logic spots and set on success. It’s distinct from $516 (LevelComplete tri-state) but used similarly in some paths (likely mode-local). (usage pattern matches a boolean gate.)High
50CwVictory_50C29ed6Level-win transition flag written to #1 by SUB_WinLevel_29E02 at 29ED6 immediately after the victory branch is taken (the same block also flips audio/state for the win sequence). C# field: Victory_50C.High
50EwCellByteTEMP292d4
29342
2dd62
2dd90
2ddba
 Scratch “current cell type/size” byte for growth logic
Byte copy of the GameBoardB cell at the active portal position used to decide growth/portal behaviour; saved/restored across routines. It’s read, masked, and compared in growth update.
High
510w LevelPaletteProfileIndex28222
29fd4
2af30
Loaded from level table data and reused as a shared 0-3 profile selector for both palette setup and the evil-growth shot threshold lookup.

The older sunset-specific label was too narrow. The word is written from level data at $28156, consumed immediately by the level-palette helper, and later read again at $2AF30 in gameplay.
Med
512w FollowerOrbitIndex2bbd2
2bbd8
2bbe0
Incremented by 2, masked with #0xF, then used as an index in follower logic.High
514wPowerCrystalFlightTimer2b230
2b236
2b240
Power Crystal-in-flight lifespan timer
Loaded from D1 when crystal starts moving; then polled and decremented until zero to gate motion/effect.
High
516wLevelComplete2890c
28932
297da
29e22
29eac
29f00
29f64
2b03a
2d088
2d7e4
2df60
2e1bc
2e1de
Canonical tri-state: set +1 on all evil portals cleared; set −1 on all good portals cleared; used by game logic to trigger win/lose events ($11/$12).
-1 = Level lost, 0 = Level running, +1 = Level won
High
518wGrowthType2822e
2825e
282ce
28630
2b0ce
Written from level data; read and added/masked to select a growth behaviour/pathfinding pattern.
0 = Circular, 0001 = Diamond, 0002 = Cross, 0003 = Octagonal
High
51AwGrowthStepPendingFlag297d0
297e4
2b0d6
2e03e
2e188
Sticky “portal growth occurred” flag used during growth pass.
Set to 1 in several paths that mark a “portal growth” event (e.g., when a portal is overrun). Cleared on entry to growth pathfinding.
High
51Caddr TarotEffectPtr2b410
2d94a
Long pointer written from 333BA[Tarot*4] and later loaded into A5 during tarot effect handling.
Long computed from a table via (0,A0,D1.w) then later movea.l (…51C),A5 to execute/apply a tarot effect.
High
520wGrowthAllowedFlag28d3c
28d7e
29300
295de
29622
2cf9c
2cfc4
2dd46
2de6a
2de80
2deaa
Master growth enable/disable flag
Hot gate for almost every growth write/update path (tst.w GrowthAllowed early-out). When clear, routines that would alter gameboard exit.
High
522wTitleFlameAccumulator28d34
295ee
2cfac
2cfe2
Initialised with 0x90, added to itself (add.w D0,(…522)) during the title sun/flame effect to drive a palette/position ramp.High
524wStarChartRefreshPendingFlag2a1be
2a1c8
2a1d0
One-shot flag raised when the star-chart unfurl animation completes, signalling the front-end to refresh the constellation star metadata. Set to 1 at 2A1C8 when StarChartUnfurlCounter_488 reaches its final threshold; polled at 2A1BE, then cleared at 2A1D0. C# field: StarChartRefreshPendingFlag_524.High
526wTarot2b400
2be3c
2be60
2be7c
2bea4
2bed0
Used to branch to Death/Wheel/Hanged Man/Star handlers; also copied into CurrentTarotCard_4F0 when a crystal is picked up.

0 = The Lion, 0001 = Death, 0002 = The Moon, 0003 = Hanged Man, 0004 = Wheel of Fortune, 0005 = The Sun, 0006 = Tower, 0007 = The Star
High
528w PowerUpDurationTimer2b1c2
2b1cc
2bef2
2d4ae
 Loaded from a small table (DAT_333EC), indexed by CurrentTarotCard_4F0, decremented each tick to time power-up duration, with a hard set to $4B in another path.High
52AwFlameAnimStepSize_52A28d2c
295e6
2cfdc
Dual-use field. During title/flame-effect sequences, serves as a branch selector written to 1 or 2 to choose the animation path (28D2C/295E6). During game-over beast sequences, serves as the per-VBL step added to TitleFlameAccumulator_522: SUB_GameOverSequence_295CC writes #2 here so each flame-table longword is shown for two consecutive VBL frames. C# field: FlameAnimStepSize_52A.High
52CaddrLevelMemoryAddress28216
2a790
2a94c
Base pointer to level data, read into A3/A1 by level loadersHigh
530wGrowthRateThreshold28268
28636
28f0c
2b0de
2e096
Probability/threshold governing growth attempts
Compared against random samples to to decide whether a row grows this tick (growth gating) (cmp.b (growthrate),D1b inside growth selection). Also forced to $FFFF in some modes to “force allow”
High
532wGuardianRespawnTimer29d20
2a5b4
2b19a
2b1a4
2b1ae
2bcae
Standard countdown with compares to 0x41 etc to schedule (servant?); reset to 0x1E in another path (shorter retry).
 
(SendGuardianToPandaemonium sets to 325, then decreases by 1 at address 2b1a4)
High
536wGrowthRateTimer2b38e
2d854
2d85c
Evil growth accumulator. Incremented +2 every VBL; fires a growth tick when it exceeds the constellation growth rate (loaded from level data). The rate is subtracted after firing, so it self-regulates to the correct average growth frequency. Unrelated to joystick input.High
538wGrowthTickAccumulator2b388
2d7f2
2d7fe
Good growth tick accumulator. Fires a good-portal growth tick when it reaches or exceeds GrowthTickThreshold_5E0 (7/9/11 for Arcade/Normal/Tactical). Unrelated to input delay.High
53AwActivePortalTypeFlag28eb4
28f30
291f8
2d804
2d862
2d892
Controls which portal type grows this tick: 0 = evil portals grow, 1 = good portals grow. Set by the growth tick controller to alternate or select portal type per growth event. Also written to #1 by the ending screen at 291F8 to force good-portal growth during the win outro. C# field: ActivePortalTypeFlag_53A.High
53EwGuardianPhaseCountdown281ba
29d28
2a5dc
2a5e6
2a5ec
2a634
2a69a
2a6b4
2a6d0
2a6ec
2a708
2a724
Guardian phase/hold countdown. Written with various constants (0x19, 0x7D, 0xAF, …) at each guardian state transition, then decremented/polled across the full guardian lifecycle (approach, attack, retreat, pandaemonium).
dec by 1 from 7D to 00 (SendGuardianToPandaemonium sets to 25)
High
542wScreenFlags2b0f2
2b10c
2b118
2cc04
2d488
Bitfield where individual bits are set/cleared with bset.b / bclr.b and tested with btst.b to gate screen/UI behaviour (e.g., spore-related rendering and level-lost signalling clears/set bits 1/2).High
544wPlayerDeadFlag298c0
2a5be
2b68e
2bd62
2bf34
2d490
Set to 1 at player death by SUB_LifeLost_298B6; gates player movement, spore-to-energy conversion, and guardian management while non-zero. Cleared at respawn step 2. Not a “tarot gate” — it is the canonical player-dead flag.High
546wSunsetStepCounter29422
29428
29434
A 0–2 modulo step index that paces the inner phases of the sunset effect (e.g., which mini-step to do this frame).
In SUB_ManageSunsetAnimation_2940C it’s incremented and then compared to #3; when it reaches 3, it’s cleared – a small repeating sub-phase counter:
addq.w #1,(WORD_00000546).lcmpi.w #3,(WORD_00000546).lclr.w (WORD_00000546).l

Render-owned 0-2 modulo sub-phase counter for the sunset effect ($29422-$29434). The simulation does not implement sunset rendering.
Low
548w SunsetTransitionCounter2943a
29450
The broader “progress” counter for the sunset animation (number of transition ticks so far). Often used with the step counter to decide when to advance colours/positions.
Same routine increments it every update (addq.w #1,(WORD_00000548).l) and also reads it into D0 for transition logic, i.e., move.w (WORD_00000548).l,D0w. It’s the longer-period counter the stepper above consults while evolving the effect.

Render-owned progress counter for the sunset transition ($2943A/$29450). The simulation does not implement sunset rendering.
Low
54AwPlayerAnimPhaseIndex2b656
2b66a
2b678
Ring index into TBL_MovementPhasePointerTable_326EA for the player animation phase. Incremented by 4 per step (word stride), reset to 4 on wrap. Drives which animation frame pointer is active for the current movement phase.High
54CwPlayerSeekOffsetX2b8ac
2b8f6
2b902
2b940
2b94a
2baec
2baf6
Per-frame X seek force applied by entities toward the player. Zeroed at VBL start; each active entity adds its per-frame seek delta here. The accumulated value steers entities toward the player position. Not a collision rebound — entities use it proactively, not reactively.High
54EwPlayerSeekOffsetY2b8b2
2b91a
2b926
2b99e
2b9a8
2bb26
2bb30
Per-frame Y seek force applied by entities toward the player. Same pattern as PlayerSeekOffsetX_54C: zeroed at VBL start, accumulated per entity per frame.High
550wGuardianActivationDelay2aa14
2b130
2b13a
Guardian activation delay countdown. Decremented each tick; LAB_CheckTimerEXT550_2B130 gates guardian activation logic behind this countdown. Set from D2 on guardian state transitions. Common pattern: tst.w then subq.w #1 until zero.High
552wLevelTimerMAIN2b06a
2b076
2b0a4
2beb0
2bec0
Course timing
counts frames and is compared against thresholds 75 and 95 to flip timer state or trigger effects. Also read and re-written in tarot (Hanged Man) time-adjustment logic.
inc by 1
High
554wLevelTimerTICK2b04e
2b054
2b064
Fine timing – Tick accumulator that rolls up into the main timer.
inc by 1 to 2F then reset to 00
High
556wGrowthDisabledFlag29ae4
2ae1c
2b044
2b0c6
2d80c
2d828
2d8be
2df6a
Global “freeze growth” switch (disables spores/growth updates and also pauses the level timer pipeline that depends on growth ticks).

Checked before the level timer advances and before growth logic runs: tst.w (GrowthDisabled_556) at 2B044 short-circuits the in-game timer progression; the same flag is tested again in the growth/portal eligibility flow to skip growth entirely when set.
High
558w GuardianAnimIndexTEMP2a9e2
2bcb6
Temporary stash for the guardian animation/frame index (kept in D7 across helper calls) during guardian update.
Stored with move.w D7,(WORD_00000558).l (e.g., 2A9E2), then later restored move.w (WORD_00000558).l,D7w inside the guardian/amoeba logic block (2BCB6). This sits in the middle of guardian sprite and position updates.
High
55Aw LevelTickThreshold2824a
2b05a
GameBias-scaled tick threshold that paces how often LevelTimerMAIN increments (i.e., game speed/tempo derived from level data and bias mode).
During level init, a timer value from level data (word at 6(A1)) is scaled by GameBias (tactical/normal/arcade) and stored here: MOVE.W D0,ModifiedByGameBias_55A (2824A). At runtime the per-frame “tick” counter $554 is compared against this threshold to decide when to advance the main level timer: CMP.W (ModifiedByGameBias_55A),D0 (2B05A).
High
55CwHiScoreRowCharOffset2c260
2c28c
2c388
2d5e2
Active screen-memory character offset for the row currently being edited on the hi-score parchment. The qualification path seeds this to one of the five traced row offsets, then each confirmed letter advances it by #8. Not a score value — it is a display/write position cursor. C# field: HighScoreValue_55C.Med
55EwHighScoreIndex28c8a
2c1ac
2c278
2c2c0
2d5f6
Current character-entry count for the active hi-score name slot. The VBL Ouija handler increments this after each fire-confirm; compared to #5 to check whether the 5-character name is complete. The non-qualifying score path writes #5 immediately to skip name entry. C# field: HighScoreIndex_55E.High
560addrHighScoreTablePTR2c27e
2d5e8
 holds a pointer to the active high-score tableHigh
564w HighScoreCharStepIndex28bb8
2c302
2c326
2c34c
Per-step UI state index for the Ouija/Grave screen logic
Used as a small step/index in the Ouija/“grave” UI flow: compared to 5, read into D0, then incremented each tick inside the same control block (CMP.W #5, EXT_564; MOVE.W EXT_564,D0; ADDQ.W #1,EXT_564). This lives alongside the other two state words $566/$568 in the same handler.
High
566w GraveScreenActiveFlag28bb0
2c2f8
One-shot “armed/active” flag enabling the Ouija/Grave UI stepper
Set to 1 at the start of the same sequence (MOVE.W #1,EXT_566) and polled as a gate (TST.W EXT_566) before the $564/$568 tickers run.
High
568w GraveAnimStep2c30e
2c314
2c320
 0..2 subphase counter for the Ouija/Grave UI
Ticked every frame (ADDQ.W #1,EXT_568), compared to 3, then cleared back to 0 on hitting the threshold – classic tiny sub-phase timer used next to $564.
High
56Aw GraveScreenAnimActive28c28
28c38
2c2ee
2c374
 “Sprite anim in-progress”/guard flag for this screen flow.
Enabled early (MOVE.W #1,EXT_56A), tested both in the “wait for sprite anim” and the “grave” handler, then explicitly cleared when the sequence finishes.
High
56Cw ColourTimer22a3d4
2a406
2c2c6
2c2d0
Enable/hold-off timer for a colour-cycle effect #2
Polled as a gate before a colour effect, explicitly cleared, set to 1 to re-arm; coupled with $56E as the corresponding index for the same effect path.
High
56Ew ColourIndex22a3de
2a3f6
2c2d8
Phase/index accumulator for colour effect #2
Read into D0, incremented by 2 per update, and reset – paired with $56C’s gating
High
570w ColourTimer328a5e
2a40c
2a43e
2c016
2c034
2c57c
Enable/hold-off timer for a colour-cycle effect #3
Tested as a gate in several places and set/cleared to control updates to $572
High
572w ColourIndex32a416
2a434
2c03c
Phase/index accumulator for colour effect #3
Read into D0, incremented by 1 per update, cleared on re-arm – paired with $570
High
574w EyeTearTimer2845c
2af9e
2afa8
2b016
Inter-tear delay for Eye of Infinity.
Seeded from <D1>, then repeatedly tested and decremented; later reloaded with #$AF as a delay – drives the Eye-of-Infinity tear cadence
Set to $7F, once it hits zero, the eye cries a tear, then reset to $AF
High
576w GuardianRespawnFlag2a8b6
2bc82
2bc8c
“Respawn occurred/allowed” flag for Guardian logic
Cleared on entry, tested during guardian logic, then set to 1 when a respawn condition is met.
High
578w EyeMovePhase2c5be
2c5ce
2c5e2
Eye movement phase/tick (horizontal/overall) used to pace the eye logic
Used as a small counter for the eye movement routine: read into D0 as input, cleared, then bumped by +2 each tick.
High
57Aw EyeDesiredXDirection2c600
2c66e
2c6cc
Desired X-direction for the eye: −1 left / +1 right
Loaded from D2 (the computed X direction), then compared against −1 and +1 in “CheckLeft/RightMovement”.
High
57CwEyeDesiredYDirection2c606
2c60c
2c72a
Desired Y-direction for the eye: −1 up / +1 down
Written from D3 (the computed Y direction), then checked against −1 and +1 in “CheckUp/Down”.
High
57Ew EyeXFlipToggle2c5e8
2c68a
2c6e8
Horizontal-move parity/flip flag for eye logic
A toggle bit flipped with EORI #1 on left/right branches and polled at decision points. Acts as a parity/flip tracker during horizontal moves.
High
580w EyeYFlipToggle2c5f4
2c62c
2c746
Vertical-move parity/flip flag for eye logic
Tested at “CheckYDirection” and toggled with EORI #1 in the up/down paths – mirrors $57E but for vertical motion.
High
582w EyeStateToggle2c5a6
2c5ae
Eye state toggle (e.g., gating a sub-effect/branch)
Simple EORI #1 toggle and TST.W gate in the eye state check – used as an on/off eye-state flag.
High
584w ControlAckFlag28a86
29266
2939a
Generic “armed/ack” flag for that mid-game control path (purpose local to that routine)
et to 1, polled in the 0x29266 path, then cleared at 0x2939A; used as a simple gate/ack in that control flow
High
586w PendingPaletteBankTrigger2813a
28dee
2a3b8
2a3c2
2a3ce
One-shot full-palette preset selector.
Seeded from D0 or forced to 2; when non-zero, the pre-Step-1 palette helper loads D0=value-1, calls SUB_SetColourPalette_2DCF0, and immediately clears the word.

Despite the older timer-style name, this behaves as a queued palette-bank trigger rather than a countdown. It remains render/front-end owned and is not a simulation-state field.
Med
588wSelectedConstellation2c4ac
2c4b6
2c50a
 Currently selected constellation indexHigh
58Ew FiringFinishedFlag2abfa
2ac06
2ac98
One-frame “fire completed” latch for the bullet system
Set to 1 when a shot finishes, then explicitly cleared at the next update pass before returning
High
594w LocalControlFlag29254
2925e
292b4
Local control flag (exact role is confined to that small flow)
Written 0→1, polled, then cleared as a simple flag in a short control region (~0x2925x).

Only 3 xrefs; flag pattern (0->1, polled, cleared) confirmed but purpose is local to one small control region (~$29254) and was not fully traced.
Med
598w PowerCrystalDataIndex2b294
2b29a
2b9e8
2e43c
Index for current Power-Crystal / special-object data in table.
Read to D1/D2 by crystal/“special object” logic, cleared after use, and written from D1 in Special_2E43C – a working index into that object’s data table.
High
59Aw GlobalTickStep2b082
2b092
2b09e
2b5e0
2b5f6
2b600
Shared cadence value (even-step tick) used as a divider/limit in timing checks.
Initialised to 38, compared against 6, decremented by 2 per tick, and used to compare/subtract against D0 inside timing/level-end checks.
High
59Cw TimingCounter2b5ea
2b5f0
2b606
Free-running small counter used in those timing calculations.
Incremented each pass, copied to D0, then written back – simple running counter used alongside $59A in the same timing block.
High
59EwScoreDigitCache2d504
2d504
2d50a
6-byte score digit dirty-check display cache used in Step 13 of the VBL pipeline (SUB_CheckPointsToAdd_2D4C8). Each byte holds the last-rendered digit value; the renderer compares the current score digit against the cached value and only redraws changed digits. Unrelated to Hi-Score UI text.High
5A6wFaceAnimActiveFlag2cfd2
2cfec
2d058
Set to 1 and tested in the face animation paths; re-set again on another branch – behaves as a simple “face anim enabled/armed” flag.High
5AAw JoystickRepeatDelay2bf96
2bfa0
2c298
Joystick repeat/cooldown timer
Set to 14 as a delay, then ticked down and polled in the joystick routine – input repeat/holdoff.
High
5ACwEyeAnimFrameCounter2af84
2af8a
Incremented every frame and compared to 0x12 in the Eye logic.High
5AEwEyeScreenActive2af96
2bfb4
Set to 1 during eye setup, then polled from the general joystick routine – used to gate input while eye screen is activeHigh
5B0wPauseOrFireOnTitleFlagPolled during title/pause flow; gates fire-button or pause behaviour on the title screen.

Outer-loop fire gate at $288BC confirmed; C# field PauseOrFireOnTitleFlag_5B0 exists. Confidence Med because the full rendering context of which pause behaviour it gates was not traced in detail.
Med
5B2wGameControlMode280dc
280dc
28132
28180
2840a
28518
2855e
285a2
28640
28776
287be
2885c
288a6
288b2
28900
28922
28a1e
28a3c
28a48
28a68
28a6e
28a7a
28aaa
28b3e
28c62
290c8
290d4
291e6
2920c
29220
29286
292a8
295cc
299d0
29e02
29ff4
2a0f6
2a300
2a30c
2a546
2a8c4
2aa3a
2af78
2b01e
2b030
2b170
2b418
2b640
2bb74
2bd58
2bfa8
2bff6
2c00a
2c194
2c1a0
2c518
2c524
2c530
2cf80
2d04e
2d4ea
2d86a
2d90c
2d916
2da7c
2e542
2e6d4
2e72c
009fe346
Master game mode enum

0 = In game
1 = Eye of Infinity screen
2 = Star chart screen
3 = Title screen (sunset and shadow)
4 = Demo/Instructions
5 = Hi-Score (Ouija)
6 = Grave screen
7 = Select game bias screen
8 = Ending screen – Well done

Global mode enum – set/tst/cmp all over to dispatch Title/Eye/Star-Chart/Hi-Score/Grave/etc. (0..8).
High
5B6addrAddress to screen29586
29648
296f4
299bc
2a01e
2a0a8
2a28e
2a2e8
2a2f2
2a318
2a33a
2a35c
2a456
2c9f6
2ca30
2cc70
2ce20
2cf48
2d0ce
2df14
2df40
Which screen are we working on? $10000/$18000

Holds the active screen base ($10000 or $18000); many branches compare it to choose Copper lists and to swap bitplane pointers.
High
5BAaddrBPL1PT Address to screen269f0
29590
29652
299c6
2a026
2a2e2
2a2e8
Shadow for bitplane-1 pointer during buffer switching
Holds the current bitplane 1 pointer shadow; written during buffer swaps and read when issuing BPL1PT into custom chips.
10000/18000

Render-owned BPL1PT hardware shadow; written during buffer swaps for Amiga custom-chip DMA registers ($29590/$29652/$299C6/$2A026). The simulation tracks AddressToScreen_5B6 instead.
Med
5C0wCurrent Constellation2814c
28806
28956
28a12
28a2a
28a30
299d8
29c98
29ccc
2a214
2b5aa
2c026
2c54e
2c586
2d832
 Current constellation index: incremented, polled for limits, mirrored to D-regs across star-chart and bias screens.
High
5C2addrStarPositions Pointer28200
299e8
29e40
2a226
2c44a
Active star-position table pointer.
Pointer to the star-position table; loaded to A0/A1 and replaced when switching datasets.
2EC6A, 2E874
High
5C6wCurrent Star281f8
299e0
29e38
2c496
Initialised to 0 when entering the title/selection flow: MOVE.W #$000,CurrentStar at 299E0. This happens alongside setting the constellation index and the star-position table pointer, i.e., part of constellation-selection setup.
During constellation selection, the code iterates the star-position table at Addr_5C2, checks each entry’s status and proximity to the player sprite (reads sprite X/Y from the sprite flag block), and when the cursor overlaps a selectable star it writes that loop index D3 into CurrentStar at 2C 496:
Table walk & status test (TST.W (A0) then CMPI.W #$001,(A0));
Distance checks against sprite position (abs |ΔX|, |ΔY| < 12);
On hit, MOVE.W D3,CurrentStar (select star).
On level completion, the selected star is marked “captured” by using CurrentStar as an index: MOVE.W CurrentStar,D0LSL.W #3,D0 (8-byte stride per entry) → MOVEA.L Addr_5C2,A0MOVE.W #$002,0(A0,D0.W) (set status=2) and decrement “stars remaining”.
High
5C8wLives281c4
281e0
287fc
29916
2993c
2994c
29958
29962
Remaining lives, initially set to 2, dec/inc, read for UI and bounds checksHigh
5CAwStars Remaining In Constellation2894c
29e4c
2a1d6
2a24e
 Stars left to complete the current constellation.High
5CClScore259b0
2882a
2898a
2d4d4
2d4da
2d52c
2e1b2
32-bit score – written/added to in multiple spots; also fed into Hi-Score code.High
5D0addrPlayerAnimFramePtr28176
2b672
2cb84
Player animation frame data pointer. Stepped by $18 (24 bytes) per animation frame through the player sprite frame sequence. Written at level init with the first frame address; incremented each step to advance the animation.High
5D4w GuardianCounter in Demo28e50
28e70
28e76
28e82
Demo-mode guardian type rotator.
Demo guardian selector: ++ each pass, wrapped at 6, mirrored into guardianType.

Only 4 xrefs; used exclusively in demo-mode guardian type cycling (incremented, wrapped at 6, mirrored into GuardianType_4B2). Pattern clear but scope is narrow — demo/instructions front-end only.
Med
5D6wGuardianPhase2a668
2a66e
0..3 looping phase (used in guardian animation timing). Small 2-bit phase counter: ADDQ.W #1 then ANDI.W #3.High
5D8wPlayerBobDirection28276
2bb98
2bb9e
±1 direction for player idle bob animation. Initialised to +1 at level start; NEG.W flips it to −1 and back on each bob cycle. Added into the player Y position to produce the idle oscillation. Unrelated to collision response.High
5DAwPlayerBobToggle2bb7e
2bb84
Alternates 0/1 each frame via ADDQ + ANDI #1 to gate the player idle bob step. Paired with PlayerBobDirection_5D8: the toggle decides when to flip, the direction decides which way.High
5DCwHighestSelectableConstellation28822
28960
2896a
29a12
2c572
Upper bound for selectable constellation index.
Initialised to 2; compared against selector inputs and updated; checked wherever constellation selection is clamped.
High
5DEwGameBias28822
28960
2896a
29a12
2c572
Selected game bias enum.
0 = Tactical Bias
Slower, more manoeuvrable player, More intelligent growth, Less aggressive Guardians.
1 = Normal Bias (Balanced)
2 = Arcade Bias
Faster, more intertia (less control) for player, Less intelligent growth, more agressive Guardians.
High
5E0wGrowthTickThreshold291ba
291d2
291de
2d7ec
Good growth fire interval. Written during level setup at $291BA–$291DE as 7 (Arcade), 9 (Normal), or 11 (Tactical) based on GameBias. GrowthTickAccumulator_538 fires a good-portal tick when it reaches this threshold. Unrelated to joystick direction.High
5E2wJoystickDirection2bfda
2c060
2c078
2c096
2c0ae
2c554
Primary joystick direction code (1..4) for game/Eye/Ouija.
Cleared, then written 1..4 by low-level joystick paths; read back when composing higher-level decisions (e.g., eye/ouija input).
0 = no movement
1 = up
2 = down
3 = left
4 = right
High
5E4w ClearScreen Flag280bc
28852
288c6
288dc
289a6
28a0c
28a8e
28b4a
28b7c
28d86
28e20
29270
29640
297b6
29ee6
29f4e
 “Clear screen on next frame” flag.
Set/cleared at every mode transition; polled before issuing full screen clears. Also asserted during exception setup (stack at $800, set ClearScreenBOOL).
High
349de???Hand Eye sprite X coordoffset +6 from Hand sprite

Render-owned Eye/Hand sprite coordinate. Offset +6 from the Hand sprite table; no simulation role.
Low
349e0???Hand Eye sprite Y coordoffset +30 from Hand sprite

Render-owned Eye/Hand sprite coordinate. Offset +30 from the Hand sprite table; no simulation role.
Low

Leave a Reply

Create a website or blog at WordPress.com

Up ↑