1986 · Mastertronic

Storm

This minisite was contributed by air. It’s agent-generated and needs a human editor. Clone https://github.com/gamesexplained/gamesexplained and follow kit/START.md to curate games/c64/storm with me to Gold.

What the code does that the manual never mentions. A spell that should clear a room can leave a monster standing, and brooches kept from an earlier game can lock Corrine's door until the game is loaded again.

01 · The spell

Bug: after a kill, a spell leaves a monster standing

A scroll or an amulet clears the monsters by counting slots up to the number of monsters out. Kill one in a low slot first and the count stops short of the last one.

Room 0 with Agravain standing where a new game puts him, run on the page's 6502 over the listing's bytes: the main loop's monster work (move_monster, spawn), the monster branch of shot_hit ($7D0C) for each shot, and the scroll's magic ($69C0). Checked against the kit's 6502 simulator: every byte of memory matches after each step up to the second scroll, which neither runs to its end. The last picture is the emulator's.

The magic ($69C0) takes the slots from 0 and stops when the slot number reaches mon_count, then sets the count to 0. That is right only while the monsters fill the lowest slots. A shot that kills the monster in slot 0 leaves five out in slots 1 to 5, so the spell stops after slot 4 and slot 5's monster walks on, uncounted.

Shoot it and shot_hit takes one from a count that is already 0, which leaves 255. spawn makes no monster while ten or more are out, so the room's generators stand idle until the players leave and come back, when enter_room sets the count to 0 again. In the emulator no monster appeared in 1,500 frames with the generator standing.

A second scroll in that room loops over 255 slots, reading positions from the bytes after the monster tables and erasing at the addresses they make. In the emulator it wrote over the panel and the play area, and the game froze: the main loop never ran again, and the raster interrupt fired about a hundred times a frame.

Room 0 after a scroll, one monster still in the room

In the emulator: slot 0 shot, then a scroll. Slot 5's monster is still there.

The screen written over after the second scroll

The survivor shot, then a second scroll: the game stops here.

02 · The laboratory

Bug: brooches from an earlier game can lock the laboratory for good

The door to Corrine opens only for exactly three snake brooches, and brooches carry over from one game to the next. Go past three and the game cannot be won again until it is loaded afresh.

Brooches carried inBrooches picked up before reaching the door: 0, 1, 2, 3
0shutshutshutopens
1shutshutopensshut
2shutopensshutshut
3opensshutshutshut
Agravain stopped beside the laboratory door in room 3, the message line reading THREE SNAKE BROACHES ARE NEEDED

In the emulator, with four brooches: the door refuses, and Agravain stays where he is.

The door's test is CMP #$03 and BEQ at $6B41. In the emulator, with brooches set to 4 in room 3, walking into the door brought the message and stopped the player; set to 3, the door opened and he walked through.

Three brooches can be taken in the whole game, in rooms 11, 44 and 63. obj_effect adds one for each, and touch_object opens the laboratory door in room 3 when the count is 3, not when it is 3 or more. A new game resets the rooms, so the brooches are back in place, but it leaves the count as the last game left it (carry-over). Players who found all three last time hold 3 already: one more takes the count to 4, the door refuses, and no brooch can bring it back down. Neither a game over nor a reset clears it, since the restart goes through the same game_init. Only loading the game again does.

03 · Touches

Bug: some monsters' touches cost far more on alternate steps

A touch costs four times the monster's kind, but the byte the game multiplies also holds the monster's animation frame, so the cost changes as it walks.

Each cost computed by the game's touch_damage ($62A4) on the kit's 6502 simulator in the page, for every value mon_kind takes, and checked against the same code called on the simulator directly. The same costs came out of the emulator.

mon_damage adds the kind byte to itself twice in decimal mode, and touch_damage adds the result to the player's drain. The low three bits are the kind; kinds 2 and 4 flip bit 7 as they walk, and kind 5 counts through bits 4 and 5. Decimal addition of bytes that are not decimal numbers gives the odd results: $82 becomes 30, and $25 overflows past 99 to leave 1. So a kind-5 monster costs 20, 60, 1, or 41 depending on the frame it touches on, and armour, which stops any drain smaller than itself (Energy), stops the cheap frames and not the dear ones.

04 · Carry-over

Secret: the first game starts with three keys and two scrolls

A new game resets the rooms, energy, armour, and scores, but not the items the players share. The file on the disk was saved in the middle of a game, so its items come with it.

Room 0 as the file holds it: its inner walls marked removed, its key and its cabbala symbol taken.

The same room after reset_walls and reset_objects, as every game sees it.

Both rooms drawn by the game's own routines on the kit's 6502 simulator in the page, and checked against the same code called on the simulator directly. The counters are the file's bytes. In the emulator, the first game after loading held 3 keys and 2 scrolls, and counters set to 7 keys, 2 brooches, and 5 scrolls before a game over were the same in the next game.

game_init runs reset_walls and reset_objects before the title draws room 0, so nobody sees the half-played room. It does not touch the counters of keys, special keys, snake brooches, amulets, masks, and scrolls. So the first game can open three locked doors and cast two scrolls before its players have picked anything up, and whatever a game ends holding passes to the next one. Players who end a game holding the three snake brooches can open the laboratory in the next without finding them again, and are shut out of it if they pick one up (the laboratory).

05 · Armour

Secret: one piece of armour ends Storm's hunger

Hunger takes 1 from Storm and 2 from Agravain every 25 passes of the main loop, and armour that is greater than a drain cancels it without wearing down (Energy). A piece of armour gives Storm 3 and Agravain 2, so Storm's first piece and Agravain's second stop hunger for good; only monsters' touches can then wear the armour down. In the emulator, Agravain with armour 4 still had 1968 energy after 500 frames, and with armour 2 the armour was gone within them.

06 · Room 69

Bug: room 69's description runs into room 70's

Each room's description should end with a zero byte. Room 69's has none, so the message line carries on into the next room's until it reaches its limit of 80 characters.

The message line in room 69 reading CLOYINGDRIED BLOOD CLINGS T

The message line in room 69, in the emulator.

The 80 characters the message line scrolls in room 69, read from room_msgs as panel_band reads them; the part in red is room 70's.

07 · Reset

Secret: a reset restarts the game and RESTORE does nothing

Hidden inside the energy routine are the nine bytes of a cartridge's signature, which the C64 checks for at every reset.

The bytes at $7FFC-$8008, from the listing: the end of lose_energy's test for 500, its branch over the signature, then the signature itself at $8000.

When the KERNAL resets, it looks at $8000 for two addresses followed by the letters CBM and the digits 80 (with bit 7 set on the letters), and jumps to the first address if it finds them. A reset button that leaves memory alone therefore restarts Storm at restart ($80A1), which sets the chips back up and goes to the title, instead of dropping to BASIC. The signature sits in the middle of lose_energy, which branches over it at $7FFE. The RESTORE key, which would otherwise break out of most programs, is handled by nmi, which acknowledges it and returns.

08 · Borders

Bug: rooms 37 and 81 draw their outer wall in their last wall's style

No list says what the outer wall looks like. draw_border uses whatever the last inner wall left behind.

Room 37, drawn by the game's routines on the page's 6502.

Room 81.

Room 37 in the emulator, its outer wall in a different style from most of its inner walls

Room 37 in the emulator.

draw_walls leaves its character and colour in char_code and colour_ofs, and draw_border draws the outer wall with them. In 98 rooms every wall has the same style, so this goes unseen. Rooms 37 and 81 mix two, and their outer walls take the style of the last record in the list, removed or not.

09 · A new monster

Bug: a new monster's direction is cleared in the wrong slot

spawn means to clear the new monster's direction, but the store at $5E97 is indexed by the generator's number, not the monster's slot. The new monster keeps the direction its slot last held, and some other slot's is set to up. move_monster hands that direction to step_monster as its starting value, and kinds 1, 3 and 6 are drawn facing it. Whether a player can ever see a monster face the wrong way because of it was not checked.