Guardians

Each star is protected by one of seven guardians, and learning how to defend yourself from these is the key to survival. Each guardian has ‘servants’ and the patterns and habits of these must also be learned.

Guardians can only be “sent to Pandaemonium” (killed) during the day cycle – shooting them has no effect during the night cycle.

The guardian type for the level is stored in $4B2, and is read in from the level data from offset +0x0

0000 – The Devil

Animation has 7 frames

The Devil’s servants are the hardest to deal with. You can avoid them by running away, but this is time (and energy) consuming. To shoot them, retreat to a safe distance, wait for them to come into your line of fire and shoot them.

Servant animation has 7 frames

The colour palette is modified for this guardian.
The guardian function at 2A858 references a memory table at 36514-365AB (length 0x98 or 152 bytes) for this guardian.

0001 – Rotating blades

Animation has 3 frames

Only appears within the Sagittarius constellation, and presumably was meant to be a secret, but since it’s value is 0x1, it appears in the second viewing of the demo, if you just leave the title screen running!
It’s pattern is predictable, but it is so fast, it is almost impossible to avoid. The eight mini-blades it constantly fires add to the difficulty.

Servant animation has 10 frames

The guardian function at 2A858 references a memory table at 365AC-36643 (length 0x98 or 152 bytes) for this guardian.

0002 – The Hand

Animation has 5 frames

The Hand produces spinning silver stars which require swift action to avoid. If you leave them alone, they split into two – and they can do this twice. During the game, the hand is just shown as the sprite with the outstretched fingers, with the eye sprite overlayed on top of it. During the game over screen, all five frames of the hand sprite are used as it rises from the grave to wave you goodbye.

Servant animation has 4 frames

The guardian function at 2A858 references a memory table at 36644-366DB (length 0x98 or 152 bytes) for this guardian.

0003 – The Hydra

Animation has 5 frames

The Hydra moves in a simple circular pattern, firing six servants at a time – two from each of its heads. The servants need to be shot twice to be destroyed. If they are not too close, it’s best to leave them alone, as they soon disappear.

Servant animation has 9 frames

The guardian function at 2A858 references a memory table at 366DE-36773 (length 0x98 or 152 bytes) for this guardian.

0004 – The Spider

Animation has 4 frames

The Spider’s servants move in a circular motion towards you and also have to be hit twice to be killed. They don’t pose too much of a problem, so it’s often best to leave them alone, but on later levels they start to home in on you.

Servant animation has 5 frames

The guardian function at 2A858 references a memory table at 36774-3680B (length 0x98 or 152 bytes) for this guardian.

0005 – The Firefly

Animation has 8 frames

This guardian flies in a predictable spiral pattern, but it’s servants aren’t quite as simple. They fly out three times in diagonals, but horizontally and vertically on the fourth. Once you master that pattern, it’s easy to work out where the next wave of servants will be going and be ready to avoid them.

Servant animation has 5 frames

The guardian function at 2A858 references a memory table at 3680C-368A3 (length 0x98 or 152 bytes) for this guardian.

0006 – The Maggot

Animation has 5 frames

May seem to be the hardest guardian to deal with, as it always appears on the left hand side of the screen in line with you. During the day cycle, move into the centre of the screen and shoot as it will be directly in the line of fire.

Servant animation has 6 frames
Animation has 6 frames

The guardian function at 2A858 references a memory table at 368A4-3693B (length 0x98 or 152 bytes) for this guardian.

Guardian Memory Address Tables

GuardianStart AddrEnd AddrLength
0000 Devil0x365140x365AB0x98 (152)
0001 Blades0x365AC0x366430x98 (152)
0002 Hand0x366440x366DB0x98 (152)
0003 Hydra0x366DC0x367730x98 (152)
0004 Spider0x367740x3680B0x98 (152)
0005 Firefly0x3680C0x368A30x98 (152)
0006 Maggot0x368A40x3693B0x98 (152)

Whether the game is reading from the ServantSpawnerData (152-byte arrays) or the ServantProjectileData (304-byte arrays), the 4 x 38-byte footprint works identically.

The 38-Byte Entity Object Structure

Hex OffsetLengthDescription / Purpose
+0x002 bytes (Word)Active Status Flag<00 01> means the entity is active and processing. <00 00> means the slot is inactive/empty. The game checks TST.W (A0) constantly.
+0x022 bytes (Word)Entity Type / Sprite ID. This dictates the visual lookup. For example, 2D is the Devil, 2E is Blades, 30 is the Hand. If destroyed, the game forces this to $000C (which flags the generic explosion animation).
+0x042 bytes (Word)Raw X-Coordinate. The absolute baseline X-position of the object on screen.
+0x062 bytes (Word)Raw Y-Coordinate. The absolute baseline Y-position of the object on screen.
+0x084 bytes (Long)Command / State Vector. Often stores a longword pointer or command tag like FFFF xxxx. When an entity is shot and killed by the player, SUB_Guardian_FlagDestroyed_2A7FE injects $FFFF1B00 directly into this offset to trigger the death routine!
...(Intermediate Animation states and coordinate offsets)
+0x122 bytes (Word)Timer / Phase Counter A. Used to track servant lifespans or sub-phases. Wiped (CLR.W $12(A0)) whenever the entity assumes the destroyed flag.
+0x141 byte (Byte)Timer / Phase Counter B. Another precise counter or state byte wiped cleanly (CLR.B $14(A0)) when the entity is destroyed.
+0x2A2 bytes (Word)Hardware Sprite X-Offset. (Offset + 42 0x2A) Spliced specifically for feeding the actual active hardware sprite engine.
+0x2C2 bytes (Word)Hardware Sprite Y-Offset. (Offset + 44 0x2C)

The game engine runs entirely on top of these 38-byte chunks, using them as generic GameObject structs.

Devil_ServantSpawner (TBL_Devil_ServantTable_36514)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001002D00F00050FFFF1818000201000000000108000000000020000000200001010000
10001002D00000000FFFF190400FF01000000000000000000000010100000200000000000
20001002D00000000FFFF19F000FF01000000000000000000000000200000200000000000
3000000000000000000000000000000000000000000000000000000000000000000000000

Blades_ServantSpawner (TBL_Blades_ServantTable_365AC)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001002E00F00050FFFF0A24000201000000000100020002000020000000100000000100
10001002E00C00065FFFF0A3400FF01000000000100000000000010100000100000000000
20001002E00D00065FFFF0A4400FF01000000000100000000000000200000100000000000
3000000000000000000000000000000000000000000000000000000000000000000000000

Hand_ServantSpawner (TBL_Hand_ServantTable_36644)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001003001000050FFFF0E8C000101000000000106BE0000000010000000100001010000
10001003000C00065FFFF0EDC00FF01000000000000000000000000000000100000000000
20001000800B60082FFFF137C00FF00000000000000000000000000000000100000000000
3000000000000000000000000000000000000000000000000000000000000000000000000

Hydra_ServantSpawner (TBL_Hydra_ServantTable_366DC)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001003900F00050FFFF0D34000201000000000103D80000000025000000100001010000
10001003900C00065FFFF0D8800FF01000000000100000000000015100000100000000000
20001003900D00065FFFF0E1000FF01000000000100000000000005200000100000000000
3000000000000000000000000000000000000000000000000000000000000000000000000

Spider_ServantSpawner (TBL_Spider_ServantTable_36774)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001001C00E00050FFFF0A54000301000000000104880000000030000000100001010000
10001001C00C00065FFFF0A8800FF01000000000100000000000020100000100000000000
20001001C00D00065FFFF0ABC00FF01000000000100000000000010200000100000000000
30001001C00E00065FFFF0AF000FF01000000000100000000000000300000100000000000

Firefly_ServantSpawner (TBL_Firefly_ServantTable_3680C)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001001E00E00050FFFF0C240003010000000001053C0000000030000000100001010000
10001001E00C00065FFFF0C6800FF01000000000100000000000020100000100000000000
20001001E00D00065FFFF0CAC00FF01000000000100000000000010200000100000000000
30001001E00E00065FFFF0CF000FF01000000000100000000000000300000100000000000

Maggot_ServantSpawner (TBL_GiantMaggot_ServantTable_368A4)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001001E0050FFFF0B240003010000000001066C00000000300000001000010100000001
1001E00000000FFFF0B6400FF010000000001000000000000201000001000000000000001
2001E00000000FFFF0BA400FF010000000001000000000000102000001000000000000001
3001E00000000FFFF0BE400FF01000000000100000000000000300000100000000000000E

Devil_ServantProjectile (TBL_GuardianDevilMovementTable_36A6C)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000F00100004FFFF1B2C000000000000FF01032A0000000000000001000001010000
10001000F00100004FFFF1B2C000000000000FF0103320000000000000001000001010000
20001000F00100004FFFF1B2C000000000000FF01033A0000000000000001000001010000
30001000F00100004FFFF1B2C000000000000FF0103420000000000000001000001010000
40001000F00100004FFFF1B2C000000000000FF01034A0000000000000001000001010000
50001000F00100004FFFF1B2C000000000000FF0103520000000000000001000001010000
60001000F00100004FFFF1B2C000000000000FF01035A0000000000000001000001010000
70001000F00100004FFFF1B2C000000000000FF0103620000000000000001000001010000

Spider_ServantProjectile (TBL_GuardianSpiderMovementTable_36BE8)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000E00100004FFFF1D80000000000000FF01005A0000000000000002000001010000
10001000E00100004FFFF1D80000000000000FF0100620000000000000002000001010000
20001000E00100004FFFF1D80000000000000FF01006A0000000000000002000001010000
30001000E00100004FFFF1D80000000000000FF0100720000000000000002000001010000
40001000E00100004FFFF1D80000000000000FF01007A0000000000000002000001010000
50001000E00100004FFFF1D80000000000000FF0100820000000000000002000001010000
60001000E00100004FFFF1D80000000000000FF01008A0000000000000002000001010000
70001000E00100004FFFF1D80000000000000FF0100920000000000000002000001010000

Firefly_ServantProjectile (TBL_GuardianFireflyMovementTable_36DB0)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000F001C0006FFFF1D34000000000000FF00014A0000000000000000000001010000
10001000F00240006FFFF1D34000000000000FF00015E0000000000000000000001010000
20001000F001C000EFFFF1D34000000000000FF0001720000000000000000000001010000
30001000F0024000EFFFF1D34000000000000FF0001860000000000000000000001010000
40001000F001C0006FFFF1D34000000000000FF00019A0000000000000000000001010000
50001000F00240006FFFF1D34000000000000FF0001AE0000000000000000000001010000
60001000F001C000EFFFF1D34000000000000FF0001C20000000000000000000001010000
70001000F0024000EFFFF1D34000000000000FF0001D60000000000000000000001010000

Hand_ServantProjectile (TBL_GuardianHandMovementTable_36F78)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
10001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
20001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
30001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
40001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
50001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
60001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000
70001000F00080008FFFF1BEC000000000000FF0103950000000000000000000001010000

Blades_ServantProjectile (TBL_GuardianBladesMovementTable_37140)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000F00040004FFFF1C1C0000000000000100FFFDFFFD000000000000000000000000
10001000F00110000FFFF1C1C00000000000001000000FFFC000000000000000000000000
20001000F001C0004FFFF1C1C00000000000001000003FFFD000000000000000000000000
30001000F00000011FFFF1C1C0000000000000100FFFC0000000000000000000000000000
40001000F00220011FFFF1C1C000000000000010000040000000000000000000000000000
50001000F0004001CFFFF1C1C0000000000000100FFFD0003000000000000000000000000
60001000F001C001CFFFF1C1C000000000000010000030003000000000000000000000000
70001000F00110020FFFF1C1C000000000000010000000004000000000000000000000000

Maggot_ServantProjectile (TBL_GuardianMaggotMovementTable_37270)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000D00180008FFFF1CEC0000000000000100FFF8FFF8000000000000000000000000
10001000D00180008FFFF1CEC00000000000001000000FFF6000000000000000000000000
20001000D00180008FFFF1CEC00000000000001000008FFF8000000000000000000000000
30001000D00180008FFFF1CEC0000000000000100FFF60000000000000000000000000000
40001000D00180008FFFF1CEC0000000000000100000A0000000000000000000000000000
50001000D00180008FFFF1CEC0000000000000100FFF80008000000000000000000000000
60001000D00180008FFFF1CEC000000000000010000080008000000000000000000000000
70001000D00180008FFFF1CEC00000000000001000000000A000000000000000000000000

Hydra_ServantProjectile (TBL_GuardianHydraMovementTable_373A0)

SlotActive (+0)ID (+2)X (+4)Y (+6)Cmd (+8)P1 (+C)P2 (+E)TimerA (+12)TimerB (+14)Remaining
00001000F00000005FFFF1C7C0000000000000101FFFEFFFE000000000000000000000000
10000000F00000005FFFF1C7C0000000000000101FFFD0000000000000000000000000000
20001000F00000005FFFF1C7C0000000000000101FFFE0002000000000000000000000000
30001000F00110007FFFF1C7C00000000000001010000FFFD000000000000000000000000
40001000F00110007FFFF1C7C000000000000010100000003000000000000000000000000
50001000F00240005FFFF1C7C00000000000001010002FFFE000000000000000000000000
60000000F00240005FFFF1C7C000000000000010100030000000000000000000000000000
70001000F00240005FFFF1C7C000000000000010100020002000000000000000000000000

Leave a comment

Create a website or blog at WordPress.com

Up ↑