1983 · Legend
Every byte of the Spectrum's 48 KB of RAM, one pixel each, 384 to a row. Lit pixels are what this game is: its code, graphics, level data, sound, text, tables and variables, exactly where they sit in memory. Dim areas are screen and working memory; dark is unused.
| Tier | silver |
|---|---|
| Coverage | 100 % of the bytes the game uses have a description |
| Comments checked | Audited & low error rate. Every comment was audited once, then the last sample of 60 comments had 2 wrong, so between 1 and 11 % of the listing’s comments are likely wrong. How listings are checked |
| Build analysed | original Legend release (TOSEC: Valhalla (1983)(Legend).tzx), a tape of four ROM-speed files: a BASIC loader, the loading screen, 12,185 bytes of machine code at $D066 and the game's BASIC program saved with its variables, autostarting at line 9800 |
| Copy | agent-draft |
| Tools | emulator: release ZEsarUX-13.0, ZEsarUX_linux-13.0-ubuntu24_x86_64.tar.gz; check-emulator 41 of 45 on 10 October 2026 (count-while-running, input-type-ascii, load-keeps-frame-phase and warp, each with a workaround in kit/skills/spectrum/tool-zesarux); for the Characters tab (11 October 2026), the kit's own Spectrum, kit/spectrum/machine.js, with SkoolKit 10.1's 48K ROM, running a snapshot SkoolKit's tap2sna made from the same tape, disassembler: SkoolKit 10.1 (control file, sna2ctl and sna2skool), host: Linux x86_64 (Ubuntu 24.04, no display), a hosted cloud session, python: 3.13.16, node: 22.22.0, browser: Chromium 1194 from Playwright, headless, for the page check |
| Model | claude-opus-5-5[1m] |
| Kit version | 0.0.136 |
Every step that measured the Source tab’s comments or made them more accurate, in the order it happened, with the models that did it. Accuracy of the Source explains each step and what the row above makes of them.
| Step | By | What it found | Of the listing |
|---|---|---|---|
| Research | claude-opus-5-5[1m] | Looked the game up online (its manual, reviews or wiki pages) before reading its code. | |
| Annotation | claude-opus-5-5[1m] | Wrote the listing’s comments. 100 % of the program is described, in 644 comments. | |
| Sample 1 | claude-opus-5-5[1m] | 7 of 60 comments wrong, so between 6 and 22 % of the listing is likely wrong. All 7 were then corrected. 18 BASIC, 3 variable and 39 machine-code comments; all 7 wrong in a detail | |
| Audit 1 | claude-opus-5-5[1m] | Checked all 644 comments and corrected 124. three agents; 122 marked wrong in a detail, and two more their notes pointed to, all corrected | |
| Sample 2 | claude-opus-5-5[1m] | 2 of 60 comments wrong, so between 1 and 11 % of the listing is likely wrong. Both were then corrected. 18 BASIC, 3 variable and 39 machine-code comments; both wrong in a detail |
likely wrong the sample’s range corrected right, or likely right not yet measured
Read this before annotating code. What the game is documented to do, with verification status against the binary. Statuses: open (documented, not found yet), traced (in the code, could not be exercised; say what was tried), confirmed (in the code, consistent with the emulator), live (observed directly), differs (the code does something else). "Absent" is not a status.
Sources:
reference/.| Feature | Status | Where |
|---|---|---|
| Three windows: the picture at the top, a white information window, a black command window with a flashing cursor | live | print_text_window ($D6EB) prints five lines of the 20-line text area; print_input_line ($D4B6); the interrupt ($FE69) flips the cursor every 16 frames |
| Commands are typed and ENTERed; capitals and punctuation optional | live | enter_pressed ($D784) lower-cases letters and splits words at any other character; key_pressed ($D52B) takes letters, digits, space and ! " , - . ; ? |
| A delay after ENTER while the other characters take their turns | live | the BASIC main loop, line 8100: the flag (8110), the comings and goings (5500) and one character's turn (4010) on each pass, the command when ENTER has set enter_flag |
| Editing: CAPS SHIFT 5–8 move the cursor, CAPS SHIFT 0 deletes left | live | key_pressed ($D52B): 5 and 8 move a character, 6 and 7 a whole screen line, 0 is delete_left ($D63E); each tried in play |
| CAPS SHIFT 1 deletes the whole input line | live | clear_line ($D616) |
| CAPS SHIFT 2 pulls the last entry back into the input window | live | recall_line ($D6D1) gives back the line clear_line last emptied, and ENTER ends with clear_line, so after ENTER it is the command just typed (seen in play) |
| SYMBOL SHIFT Q, A, Z scroll the white text window over a 20-line text area | live | scroll_text_back ($D726), scroll_text_on ($D740), print_text_window ($D6EB); the area is n$, 640 characters at $AD5A |
Minor spelling mistakes are put right (ge sord reads as get sword) | live | find_word ($D937): one wrong, missing or extra letter, or the entry with most letters matched if that is within two of the word's length |
| An entry the parser cannot understand is highlighted in red and left for editing | live | show_bad_word ($D8C8) puts PAPER 2 round the first word the dictionary lacks; the line never reaches BASIC |
| "This doesn't make sense" and "what?" for entries it cannot use | live | line 2900 (ver): "This doesn't make sense:-" and the command read back ("You drop."); line 115: "what?" for every parser error but 4 |
| Thirty-six characters, each with a sort and six qualities (badness or goodness, charisma, strength, bravery, brains) that govern how they behave | differs | c$ (characters_table, $BC23) holds them as nibbles from 1 to 15; the inlay's 1 to 5 for charisma, strength, bravery and brains are those divided by three and rounded up, for every character but Gripe (charisma 2 in the game, 4 on the inlay) and Tyr (bravery 13 in the game, 4 on the inlay). Goodness 1 to 7 is the inlay's badness 5 to 1, and 8 to 15 its goodness 1 to 5. No line reads bravery (FN b, line 50), so it changes nothing. A sixth nibble the inlay leaves out, FN p, decides who moves on. Snake and Raven make 39 rows with you |
| Characters act on their own: they move, eat, drink, fight, pick things up and drop them | live | lines 4010–4610: up to ten turns a pass, each a random character here picking one of six actions at random. Watched for two runs of 400,000 frames (133 minutes) with nobody typing, in kit/spectrum/machine.js |
| Six quests, each for a special object, found only in order: Ofnir (key), Drapnir (ring), Skornir (shield), Skalir (sword), Felstrong (axe), Grimnir (helmet) | differs | nothing counts quests: the order comes from the special places that let you through only with a quest object (s$, $C644). Felstrong (location 6) needs no other quest object and can be the first; the rest come in the manual's order; Grimnir needs Felstrong, Skalir and Skornir; Valhalla needs Grimnir. A search over the map's tables |
| Quest objects weigh more than ordinary ones | confirmed | p$ ($BAEF): Felstrong 12 to the axe's 5, Skalir 14 to the sword's 8, Skornir 20 to the shield's 12, Grimnir 20 to the helmet's 10, Drapnir 7 to the ring's 5, Ofnir 2 to the key's 1 |
| Ofnir opens no chest and Drapnir works no ringway | traced | line 1955 needs the key (80), line 1505 the ring (85); neither accepts the quest object |
| Dying of hunger or in a fight sends you to hell, keeping only helmet, sword or axe, money and the quest objects other than Ofnir and Drapnir | differs | lines 5615–5625: you keep slots 1–3, the weapon, the shield and the helmet, and your crowns, so an ordinary shield stays too; everything else goes, Ofnir and Drapnir with it. You arrive at location 30, 39 or 21, at random |
| You come back from hell very strong | traced | line 5625: the dead come back at full strength (csa with 1024, capped), 175 for you |
| Other characters who die lose everything but their weapons, Ofnir and Drapnir included, and reappear elsewhere | differs | the same lines as for you: they keep weapon, shield, helmet and crowns, lose the rest, and go to any location |
| Objects lost at death are scattered at random through the world | traced | line 5615: each goes to a random location other than this one with a free place, so a lost Ofnir or Drapnir lies somewhere on the map |
| One helmet, one shield, and one sword or one axe at a time | traced | bput (line 3110): slot 1 the weapon, 2 the shield, 3 the helmet; a second is error 7 |
| Strength drains with everything you do, more with more carried; eating and drinking restore it; food does more than wine | differs | dov (line 5450): every command costs 5 strength, whatever is carried; the load only limits what can be picked up (weight plus load at most the strength now, line 3110). Food gives 64 back and wine 32 (lines 7150, 7200) |
| A fixed amount of food and drink in the world | differs | line 5110: while the food tally fo (230 at the start, 2 off for each meal and 1 for each drink) is under 100, each empty place at a location you enter is filled one time in three with new food or wine |
| Fights are won, lost or drawn, two characters at a time, by strength and weapons, with a small luck factor; a sword beats an axe except when thrown | differs | lines 1360–1376: each side scores its strength plus 40 for a weapon and 40 more for a sword; within 20 it is a draw, by 64 or more a kill. No random number enters it. Thrown, an axe does 20 and a sword 10 (line 1471) |
| Throwing any object but money starts a fight; fireballs and lightning can kill | traced | line 1452: the target attacks the thrower; line 1471: lightning takes 30 strength and a fireball 40, and a character with none left dies at its next action (line 5450) |
| Who likes you depends on whom you attack: attack baddies and the goodies co-operate | live | line 1356: one attack you order in two moves the attacker's goodness a step, up for a victim under 8, down for one of 8 or more; at your starting 15 a step up is refused. Lines 210, 4410 and 4510 decide refusals, attacks and gifts by the gap in goodness. Seen in play: Loki's byte 17 went from 31 to 15 when he fought back at a throw by Skadi that you ordered |
| Get or take, drop, give, and asking characters to give | live | lines 1201, 1402, 1752 |
| Buying and selling with crowns; 200 crowns at the start; characters accept or refuse | differs | you start with 200 crowns (c$); a seller 10 or more from you in goodness may refuse to sell at all, (gap − 9) / gap of the time, and asks the value × (1 + gap / 32) (line 1129); a buyer pays the value × (1 − gap / 32) (line 1830). Crowns received are counted wrong: moba (line 3410) adds the receiver's own number, so you get 1 crown however many you pick up ("You get 50 crowns." then "You have 151 crowns.", seen in play) |
| Chests and cupboards: locked when closed, one key opens all, opening takes strength, closed again when you leave | live | line 1955: the opener needs (35 − n) × 6 strength at special place n, which at locations 4, 6, 37, 44 and 81 is more than your 175 ("You are not strong enough to open the cupboard.", seen at location 6); line 5105 closes them |
| Klepto steals | live | line 5300: only when an object is put down where all six places are taken; Klepto comes and carries off an ordinary object: the one put down, or, when that is a quest object, an ordinary one it takes the place of (line 5305); only when every place holds a quest object or a container does he take whatever is in the last. He carries it to a neighbouring location. Seen in play: "Klepto steals the rock.", the rock then at location 61 with Klepto |
| Summoning a character, who may refuse ("Sorry...") | live | line 2002: "Sorry.." when nobody else is here or more than six are |
| Asking characters to do things, which they may refuse; they will not buy or sell for you | live | line 210: one time in three; 11 in 12 when you ask the character last asked by anyone, or last traded with; always when the gap in goodness less half the asker's charisma is above 2; line 1102 |
what, where, who, how, list | live | lines 6450, 6500, 6200, 6600, 6100 |
help: directions that need or forbid an object or character, what a random character carries, where a ringway leads; sometimes "Sorry..." | differs | line 6555: the directions that need something are shown, but the text for one that forbids something never is (seen in play, with the conditions set by hand); "Sorry.." one time in two, and nineteen in twenty once help has been given here |
Ringways: jump with a ring to another location | live | line 1505; m$ byte 3 is where each leads |
l and r step left and right; go to an object or character | live | lines 600–630 and 1080; seen in play, your column from 27 to 26 to 25 and back, and "You go to Thor." |
go with a direction or its abbreviation; you always face north; huts cannot be entered | live | lines 1055–1065, cango (3860), mnex (3810) |
| The faster you move, the harder it is for others to keep up | traced | a character at the location you just left may follow you: each character turn picks one of the 38 others at random, and one still there comes after you when its restlessness (FN p) beats RND × 8 and it likes or loathes you, 0 to 4 or 12 and more apart in goodness (line 4010). Turns run only while no command is waiting (line 8100), so the sooner you move on, the fewer chances it gets |
pause freezes the game until the next command | live | line 6020 |
save and load a game position on tape; open containers close | traced | lines 6050 and 6255: the code in the REM of line 1 saves and loads the variables. Pressing BREAK while the tape runs resets the Spectrum (seen in play) |
print, noprint and copy on the ZX printer | traced | lines 6300–6400, through the ROM's printer channel; no printer was attached |
| A location holds at most six objects; dropping a container with more inside crashes the game (Spectrum Computing's known error) | differs | m$ has six places for each location, and what lies inside a chest takes one of them. A chest or cupboard weighs nothing and cannot be carried ("You can't carry the chest.", seen in play). The crash is real but comes another way: putting an ordinary object into a container where all six places are taken stops the game with "3 Subscript wrong, 5310:5" (seen in play) |
Found in the code, not in the manual.
| Feature | Status | Where |
|---|---|---|
| Every location's picture is drawn by code, not stored: the random-number generator is seeded from the location's number before each picture, so a place looks the same on every visit | live | seed_random ($DE35), the terrain drawers from terrain_table ($E352), the scene features (feature_table, $FAF1). Seen in play: Valheim left and entered again, its picture (character rows 0–11, pixels and colours) the same to the byte |
| The castle's flag flaps one pass of the main loop in two | live | line 8110, gfx_flag ($FBCB); seen in play, the flag's cell redrawn with no key pressed |
Food, wine, a key or anything numbered above 66 counts as the better weapon in a fight, and attack Thor with no weapon named is bare hands even with a sword carried | traced | line 1362 |
| Mary arrives, unamused, when you swear: fourteen swear words are in the dictionary | live | line 120; d$ words 241–254; "damn" typed in play brought "Mary is not amused..." |
| SYMBOL SHIFT S would leave the game for BASIC, but line 9800 disables it | traced | escape_to_basic ($D5DD) |
BREAK while save or load runs resets the machine | live | lines 6050, 6255; the REM code at $5CD0 |
| A thrown object that lands too close ("too close to throw") still does its damage, and is lost | live | line 1482 |
| Characters 2 to 37 file past at Valhalla to congratulate you | traced | line 5135 |
| Error 18, "... not strong enough", is never raised; errors 8, 11, 15 and 16 have no message | traced | lines 9909–9918 |
| Throws you order at a character of goodness 1 can stop the game: its counterattacks step its goodness below 0 | live | line 1356 (CHR$ of a negative number) after line 1452. From the tape's start with nothing poked, Thor, Idun, Skadi and Odin told to throw at Loki: "B Integer out of range, 1356:8" after ten minutes of play |
| A character with charisma 15 cannot step up to goodness 15: Boldir can lose his 15 for good, and Loki climbs to 14 at most | traced | line 1356 keeps byte 17 only under 255 |
| A character alone with you never acts | live | line 4040 needs a second character here besides the one whose turn it is. In the two 133-minute runs, 26 minutes alone with one character, and nothing done |
| Only the location you are at runs; characters elsewhere stay as they were, and are put back to full strength when you meet them | live | lines 5105, 5320, 5630, 5705 and 5760 are the only ones that change a location; lines 5122 and 5760 restore strength. After the run from the start, the 20 characters never named in its text had rows as the tape loaded them, to the byte |
| A stage manager fills an empty place and thins a crowded one, so two to four others are usually with you | live | lines 5500–5526. Two to four others were with you 83 % of the run from the start, 94 % of the run beside Saga; Loki, sent away from the five at Valheim, had been sent by line 8120's GO SUB 5500 |
| The clever characters are the ones given orders by others, the reverse of the inlay | live | line 4057: a character with brains above 7 (flipped one time in ten) is ordered by a random other one here, one time in two. 41 of the 42 orders seen in the two runs went to brains above 7 |
RANDOMIZE with no number reseeds from the frame counter at four lines, so two games from the same tape part ways | traced | lines 8100, 4070, 4105, 5021 |
s$ and m$): the search took every condition but a quest object as met (the right ordinary object or character at hand, a ring for every ringway, someone strong enough to open each container). The order it gives is the order those gates force; it is not a route someone has played.The symbol map for this game is symbols.json; the listing behind the Source tab is listing.json. Write-ups, facts and symbol maps are CC BY-SA 4.0. The game itself is not hosted here.