Loading listing…
1988 · Electronic Arts
Every routine, table and variable the game uses, with the names and descriptions given to them. Click an operand to follow it; the counter beside a label lists what refers to it. The reference below the fold is rendered from the game's facts file.
This game is in 64 parts, and the same addresses hold something else in each. Each part has a listing of its own, chosen from the list beside it.
Las Vegas, jail and Fat Freddy's is loaded over Resident engine and loader and The game and Tile set 4. The listing shows them together, as the machine holds them; the rows of this part are marked.
The jail, Fat Freddy's Place and three small buildings of Las Vegas share this map. Las Vegas enters them with "Entering the jail." (map 12's message 20, on its exit 1, to (6,1)), "Entering Fat Freddy's Place where even low rollers can have a ball." (map 12's message 40, on its exit 2, to (11,23)) and "Entering a small beat up building." (map 12's message 55, on its exits 3, 4 and 5, to (26,1), (24,30) and (1,17)). The ways out are "Leaving the jail." (message 7, exit 6, to Las Vegas at (61,2)), "Leaving Fat Freddy's." (message 21, exit 1, to Las Vegas at (18,25)) and "Leaving the building." (message 20, exit 5, back to the party's return point). It is a map of 32 by 32 squares. It is stored on side 3 of the disks from track 11, logical sector 2, 35 pages: entry 40 of the map directory, T35/L14. enter_map (engine $25BD) loads it to $3400-$56FF and unpacks its tile layer to $DE00-$E1FF. Tile set 4 draws it (part tiles-4). Every address here is this map's unless a part is named beside it.
$3A00, where load_map_pages (engine $2603) points $61/$62: 22 address words ($3A00-$3A2B), 11 setting bytes ($3A2C-$3A36) and 37 combat phrase numbers ($3A37-$3A5B).$3A2C holds 32, which enter_map reads at engine $25D3 as both the height and the width.$3A30, which enter_map reads at engine $25EE. Off the edge of the map it draws tile 58, $3A33, which draw_square reads at engine $0B5E.$3A2F holds 0, on which random_encounter returns at once (game $B019).$3A34 holds 128, in 256ths of a minute, and $3A35 0 whole minutes (advance_clock, game $AF32). $3A36 adds 4 to $D2 and to the count $04-$06 (game $AF58).$DE00-$E1FF, is a byte a square (map_tile_row, engine $0B06), unpacked by unpack_map_stream (engine $26E7) from entry 40 of the stream directory, T35/L13. The unpack runs on to $E2BB; the layer is its first 1,024 bytes, the rows below the height that map_tile_row reads.$3A37-$3A5B, name messages 110 to 142 of the map's text (show_map_msg_at, game $BCE5, and show_map_msg_pair, game $BCE1).$3400-$35FF, a nibble a square, map_class_at at engine $0953; number layer $3600-$39FF, map_number_row at engine $098E), and the records of each class's list (header words 3-18, $3A06-$3A25; action_record, engine $09B8). A null word, 0, names no record:| Class | Squares | List | Words | Records |
|---|---|---|---|---|
| 0 plain | 347 | |||
| 1 message | 2 | $3A5C | 36, 13 null | 23 |
| 2 check | 6 | $3ADD | 15, 2 null | 13 |
| 3 encounter | 14 | $3BF4 | 27, 7 null | 20 |
| 4 tile | 4 | $3D19 | 12, 7 null | 5 |
| 5 loot bag | 1 | $3D42 | 27, 8 null | 19 |
| 6 action | 0 | $3E2A | 12, 1 null | 11 |
| 8 question | 8 | $3EF7 | 9 | 9 |
| 10 exit | 7 | $3F88 | 8, 2 null | 6 |
| 11 blocking | 634 | $3FB9 | 7, 2 null | 5 |
| 12 remote change | 1 | $3FD2 | 20, 7 null | 13 |
| total | 1,024 | 124 |
square_action, game $8839, and run_action, game $8845): 1 the map's routine 0 ($3E42); 2 the map's routine 0 ($3E46); 3 the map's routine 0 ($3E4A); 4 the map's routine 0 ($3E4E); 5 the map's routine 0 ($3E52); 6 the map's routine 0 ($3E56); 7 the map's routine 0 ($3E5A); 8 the map's routine 0 ($3E5E); 9 the map's routine 0 ($3E62); 10 the map's routine 0 ($3E66); 11 the map's routine 1 ($3E6A).$3E71 (run_action reads it at game $885C): routine 0 $3E75; routine 1 $3EA1.$436E (select_map_text, engine $1E4F): an alphabet of 60 characters, a table of 37 group offsets at $43AA, and messages 0 to 142 in groups of four, $43F4-$5677. Message 142 is the last that a record, the map's code or a combat phrase names, and none of them names a message in the 136 bytes after it, $5678-$56FF. Messages 25, 79 and 85, below it, are named by none of them either.$41F5 (header word 1; print_monster_name, game $9E5D, reads it at game $9E78) and their eight-byte records at $42E6, monster n at $42E6 + 8*n* (header word 2; monster_record, game $9EA4, reads it at game $9EA7): 1 Hired Gun, 2 Sniper, 3 Mercenary, 4 Bodyguard, 5 Casino Guard, 6 Gambler, 7 Servant of the Mushroom Cloud, 8 Slicerdicer, 9 Insect, 10 Prostitute, 11 Thug, 12 Fat Freddy, 13 Woman, 14 Combat Hacker, 15 Kesa the Beggar and 16 Covenant.$40F5), hired from encounter 15 ($3C96). The list is at $40F1 (header word 20; order_hire, game $A3F1, reads it at game $A424), and the character's 256-byte record is copied whole (game $A42C-$A433); the NPC number is the high nibble of the encounter record's byte +9.$3F88; square_exit, game $89A3): to Las Vegas, map 12 (exits 1 and 6, to (18,25) and (61,2), each asking first); back to the party's return point, map byte $FF (exit 5; game $89EE); 3 within the map (exits 2, 4 and 7). No square, and no change the squares lead to, names exits 0 and 3.$3E75 roulette_payout, routine 0, run by action records 1 to 10 ($3E42-$3E69, four bytes each: 00 05 19 and the payout, 20 for record 1, 40 for record 2 and so on up to 200 for record 10). It takes the record's byte +3 into $3E91 roulette_win ($3E75-$3E79), keeps $5F/$60 on the stack, finds loot bag 25 ($3E12) through action_record (engine $0428, A = 25, Y = 5) and gives it a fresh cash entry: $5E at +2, the payout at +3 and 0 at +4 ($3E89-$3E97). It puts $5F/$60 back and returns with carry clear ($3E99-$3EA0), so run_action does not redraw the view (game $8872). The record's change then makes the square loot bag 25, which opens at once (square_action, game $8840; run_square_action, game $ACCE-$ACD1). (run on the map's snapshot: record 10 made $3E15 go from 20 to 200, and with the bag's cash entry marked opened, $3E14 = $DE and $3E15 = 7, record 1 wrote back $5E and 20)$3E91 roulette_win is the operand of the LDA # at $3E90, written at $3E79. It is 0 as stored.$3EA1 knockout_gas, routine 1, run by action record 11 ($3E6A: 01 00 00 01 00 0C 0D). It sets $3EE2 gas_nobody_masked to 1, and for each member from position 1 up to the party's member count, $07, counted in $3ED5 gas_member, it makes the member current (select_member, engine $0335) and looks for a Gas mask, item 47 (find_item, engine $0344) ($3EA1-$3EB1). A member with one clears $3EE2 ($3EB3-$3EB5). A member without one has CON, +$1D/+$1E, saved in +$26/+$27, where the game keeps the CON from before a blow, and set to $FB $FF, −5, which is unconscious ($3EBA-$3ED2). Then the pair at +3/+4, when somebody had a mask, or the pair at +5/+6, when nobody had one, is copied into +1/+2 ($3EDF-$3EF3), the change square_action makes next (game $8840), and the routine returns with carry clear ($3EF5-$3EF6). (run on the map's snapshot: the CON of all four members, engine $F51D, engine $F61D, engine $F71D and engine $F81D, became $FB $FF, their +$26 took the 28, 27, 34 and 23 they had, and $3E6B-$3E6C became $0C $0D; with a Gas mask put in member 1's first item slot, engine $F5BD, member 1's CON was left alone, the other three went down, and $3E6B-$3E6C became $01 $00)$3ED5 gas_member is the operand of the LDA # at $3ED4: the position, 1 at the start ($3EA1), written at $3EA6 on each pass, then raised by one and compared with $07 ($3ED6-$3EDD). $3EE2 gas_nobody_masked is the operand of the LDA # at $3EE1: 1 from $3EA3, 0 from $3EB5. With 0 the BEQ at $3EE3 keeps Y = 3 from $3EDF; with 1 the routine falls through to the LDY #$05 at $3EE5. Both are 0 as stored.$3F81): "Do you want to play roulette at $50 a try (Y/N)?" (message 8), answered with one key. Y (message 36) gives check square 4. Any other key, or none, writes nothing ($FF), and the question waits for the next step onto the table.$3B24) runs at once, and the first conscious member decides (flags $C0). Its one pair, 80 32 ($3B2E-$3B2F), passes when that member has less than 50 in cash (game $8E73-$8E83): "You don't have enough money!." (message 107), and the change $FD puts question square 8 back without asking again (engine $0A38-$0A3C). A member with 50 or more fails the check and pays 50, its effect (95 B2, $3B2C-$3B2D), and check square 14 follows at once.$3BC1, flags $C8) is the spin. It tests the same member against ten pairs in order, LK 13, Gamble 12, LK 11, Gamble 10, LK 9, Gamble 8, LK 7, Gamble 6, LK 5 and Gamble 4 ($3BCB-$3BDE), and the first one passed shows "You win back..." (message 104) and makes its own change ($3BE0-$3BF3; game $8F46-$8F59): action square 10 for LK 13, action square 9 for Gamble 12, and so on down to action square 1 for Gamble 4. A member without the Gamble skill skips its pairs (game $8EA2-$8EA7). A member who passes none reads "Sorry, pal, you lose. Try again." (message 105), and the square becomes question square 8, which asks again at once.roulette_payout with a payout of 20 times k and becomes loot bag 25, which opens at once. A cash entry $5E is rolled from 1 to its amount when the bag is first opened, and marked $DE (game $91B8-$91BF; loot_roll_next_byte, game $92E1), so a spin passed at LK 13 pays from 1 to 200 and one passed at Gamble 4 from 1 to 20, for the 50 already paid. Emptied, the bag becomes question square 8 ($3E12: 08 08), which asks again at once (game $92D6-$92E0).$3F09): "The office door is heavy, oak, and closed. When you knock, a voice yells, "What's the word?"" (message 23), answered by typing. BIRD (message 24) gives remote-change square 17 ($40CA): "The door swings open. An incredibly fat man is waiting to greet you." (message 45). It makes the doorway at (6,27) tile square 10 ($3D3C, tile 58), and (6,23) and the party's square plain ground.$3B0A), which runs at once, and the first conscious member decides (flags $C0). Its only pair is skill 37 at difficulty 0 (00 25). Of the 14 NPC records of the 42 maps and the records of the four Rangers of the starting party, only Dan Citrine's holds skill 37 (map-06 $44A0; skill_level, engine $1392), so for any other first member the check fails: "When you give the wrong password, a panel in the door opens and a boxing glove attached to a spring punches you in the nose, and retracts back into the door." (message 102) and 3d6 of CON for that member, less the member's armour roll (1D 83; flag bit 0 clear, game $90AF-$90B4). Its change $FE puts the question back (alter_square, engine $0A28), and since set_square then returns carry set (engine $0A3D), the question asks again at once.$3F11): "You are standing face to face with Fat Freddy. Would you like to: A) Chat B) Attack C) Apologize & leave" (message 29), one key. No answer, or another key, gives question square 1 again, which asks at once. A (message 30) gives message square 9 ($3AB4: "Read paragraph 21.", message 33) and then question square 2. B (message 31) gives remote-change square 18 (below). C (message 32) gives remote-change square 1 ($4002): "Freddy isn't very gracious. "Get out of my office and don't come back!" he yells. The guards escort you out and slam the door." (message 34). It makes (6,27) blocking square 3 ($3FCE: "Freddy's office walls are heavily reinforced. Steel and concrete lie beneath the plaster.", message 19), (6,23) tile square 10 and (6,28) question square 0, and the party's square exit 7 ($3FB3), which takes the party to (6,29) and puts question square 1 back.$3F1F) asks "Fat Freddy looks at you expectantly. Will you take his offer (Y/N)?" (message 35), one key. No answer, or any key but Y and N, gives question square 2 again, which asks at once, so only Y or N ends it.$3AD5): ""Good, good!" bubbles the corpulent mobster. "Here's $1000 on account. Enjoy yourselves in the casino." (message 38), then loot bag 11 ($3DAC: 0C 02 DE E8 03 FF), whose cash entry is marked opened, so it holds exactly 1,000 (game $91A9-$91AB). Emptied, it becomes remote-change square 2 ($4014): "You're taken back into the casino." (message 39). It closes the office as C does, and the party's square becomes exit 2 ($3F9D), which takes the party to (6,29) and makes the square it left check square 3 ($3B17).$E4), and each one who carries a ring loses a charge of it (game $8E65-$8E70); a ring taken from a loot bag has a count of 1 (game $335C), so it is gone. With the ring: ""I see that you have got the ring. Brygo must be dead. Good. You have served me well, fools." Read paragraph 119." (message 41), and remote-change square 4 ($4026) puts encounter 11 on (6,23) and encounters 13 and 14 ($3C7E, $3C8A) on (5,25) and (8,25), each 5 Casino Guards, 5 Thugs and 5 Hired Guns (monsters 5, 11 and 1): "It's an ambush! Freddy doesn't intend to pay. His office is full of hired killers." (message 46). Without it: ""Beat it! I don't want to see you again until you have Brygo's ring."" (message 42), and remote-change square 19 ($40DF) closes the office and sends the party back to (6,29) through exit 2, as remote-change square 2 does.$3AA7): ""You may change your mind," he sneers, and pushes a button on his desk. You hear a faint hissing and smell a sickly sweet scent that numbs the mind." (message 40), then action square 11, knockout_gas.$3AA4): "Those with gas masks manage to get them on in time." (message 103), then remote-change square 18 ($40D7): "Combat flares. Freddy's henchmen go for their guns, and the Cloud help anyone who gets in their way!" (message 26). B at question square 1 leads there too. It puts encounter 11 ($3C72) on (6,23): Fat Freddy (monster 12) and two Bodyguards (monster 4), "Get 'em!" (message 28), not peaceful (byte +9 $05), and makes the party's square plain ground. Wiped out, they leave loot bag 10 ($3DA0): 1 to 5 45 clips, an M1911A1 45 pistol, two Mac 17 SMGs and 257 to 500 in cash, since each byte of 500 (F4 01) is rolled from 1 to itself (loot_roll_next_byte, game $92E1).$4060): "Everything is spinning. The gas knocks you out in just a couple of seconds." (message 101). It ties up the cell around (1,12) (the jail, below), closes the cell's slab at (4,9), check square 7, and puts encounter 11 on (6,23). The party's square becomes exit 4 ($3FA3): "While unconscious, you are transported to a prison. When you awaken, you find that sturdy ropes bind your hands and feet." (message 15), which takes the party to (1,12) and leaves plain ground behind.health_tick runs (game $B7BA) and wakes at 0 with half the CON it had, or 1 (game $B7C2-$B7DB). While nobody in the party is conscious, the main loop calls view_command (game $7F0C-$7F11), which moves the clock on when it comes back to the same party (game $9B8C).con_heal_one, game $B854-$B858), and one with bits 4 to 7 loses points instead (game $B816-$B83F), so that member does not wake. The end-of-game test counts an unconscious character with any +$28 bit as lost (game_over_test, game $7EE6-$7EF3), and when every character in use is lost the game loads its death part (game $7EFE).$3B9A); (1,11), (2,11) and (2,12) check square 12 ($3BA7); and (1,10), (2,10), (3,10), (3,11) and (3,12) message square 35 ($3ADA). It closes the slab but does not set the panel at (5,9), which keeps question square 4 if the cell was open before.$00) with "You are bound by ropes. Unless you free yourself, you aren't going anywhere." (message 3). With bit 6 of its flags clear its one pair, skill 37, is never tested (game $8E30-$8E39).$80). DEX 2 Used on it (42 13) shows "Your nimble fingers undo the knot in the rope. You have freed yourself!" (message 1) and makes it remote-change square 14 ($409A), which makes the nine squares from (1,10) to (3,12) plain ground. A failed Use shows "The ropes are too tight. The more you struggle, the more the rope bites into your wrist." (message 2; game $8DC8-$8DD3) and changes nothing.$3FC9): "There is a man chained to a wall here. It's Covenant! He has been captured by Fat Freddy." (message 88). Bumping it makes it check square 6 ($3B3E), which refuses a step with ""Get me loose," says the prisoner." (message 48). Picklock 3 or ST 5 Used on it (03 0F, 45 0E) shows "You did it. You freed him!" (message 49) and makes it encounter 15 ($3C96): Covenant (monster 16), peaceful and stationary, the NPC 1 a party can hire (byte +9 $17). A failed Use shows "The chains resist all your efforts." (message 50).$3B4D), as the map is stored and after the gas. A step onto it shows "A massive block of concrete seals the room shut." (message 51) and tests every conscious member for skill 40 at difficulty 0, one pass enough (flags $64; 00 28). Of the 14 NPC records of the 42 maps and the records of the four Rangers of the starting party, only Covenant's holds skill 40, at level $FF in its last skill pair ($41AF-$41B0, in NPC 1's record at $40F5). With him: "Covenant presses certain sections on the wall beside it, and it slowly sinks into the floor." (message 52), and the party steps onto the slab, which has become remote-change square 0 ($3FFA; game $8DF2-$8E0C); that makes the panel at (5,9) question square 4 and the slab tile square 10, open. Without him: "There doesn't seem to be a way out." (message 53), and the step is refused (game $8E07-$8E0E).$3F2A) while the slab is closed and question square 4 ($3F34) while it is open: "The door is marked "Danger! Prisoners within!" There are two buttons marked O)pen C)lose. Press one?" (message 54), one key. O at question square 3 gives remote-change square 5 ($4038): "The concrete slab slowly descends into the floor and opens the cell." (message 57), which makes the panel question square 4 and the slab tile square 10. C at question square 4 gives remote-change square 6 ($4044): "The concrete slab slowly rises out of the floor and closes the cell." (message 58), which makes the panel question square 3 and the slab check square 7. The other button gives message square 4 ($3AB0: "The door is already closed.", message 43) or 5 ($3AB2: "The door is already open.", message 44), whose $FE puts the question back to ask again at once.Current truth for this game. The workflow lives in kit/skills/; how this understanding developed lives in agent-history.md. Every fact names the routine or table it comes from. Unless marked live, a fact comes from reading the code in the snapshot named in orientation.md.
The game is in 64 parts (orientation.md, "The parts"): a resident engine, the programs loaded over it, nine tile sets and 42 maps. What is true of one part is in that part's own parts/<id>/facts.md, with that part's addresses. This file holds what spans the parts, and names the part beside every address it gives: "engine $25BD" is the engine's routine at $25BD.
PRODOS and 2.0 on sides 1 and 3 and the game's data in raw sectors on all four (orientation.md, "The image").$81AD), and its packed text "Electronic Arts and Interplay Productions proudly present" and "Copyright 1986-88 Interplay Productions." (startup $84BE, $8505).$514F) reads "A computer software poster reads, "WASTELAND!"" and lists programming, design, maps, graphics, general help and playtest, 26 credits to 20 people, ending "Rated PG-13. Coming soon to a theatre near you." It is one of four messages on one wall square (column 20, row 25, class 11), each bump showing the next: 91 "Coming soon, "The Radheads!"", 92 the credits, 93 and 94 two more films, then 91 again (live). Map 1's message 26 is a gravestone: "Ken St. Andre, 4/28/47--4/28/87." (map-01 $4300), shown on the graveyard's square at column 27, row 24 (live). The string sweep of every program part and the decoded text of every text block (the 52 blocks' 4,920 messages, 478 the programs' and 4,442 the maps') find no other credit: the start-up's lines above are the only others that name a maker.$7E06, against side 1's $7F2A; 2,766 of its 4,096 bytes differ), and its own boot sector, named "A JERKVISION PRODUCTION". Its credits read "Copyright 1986,87 Interplay Productions." where side 1's read "1986-88", and where side 1's start-up calls its title sounds, side 3's calls three RTS stubs ($7E03-$7E05) and writes no SID register. Booted, side 3 cannot run: its 2.0 loads side 3's track 34, logical sector 10 to $0200-$30FF, where side 1 has the engine and side 3 has other bytes, and the first raster interrupt after the hand-over goes through engine $04F9 into them and halts the processor on a JAM at $2931 (live). Run over side 1's engine instead, with side 3 in the drive, it shows a title picture it unpacks from side 3's track 3 and stops at "Computer defense initiative activated." (live, reference/side-3-start-up.png).$8600-$8FFF is the radio program's $7E00-$87FF, all 2,560 bytes.$874B-$87FF, and so also the Ranger Center's $8F4B-$8FFF, is the game's $874B-$87FF except two operand bytes ($87B4, $87B9), each 4 lower than the game's: a copy from a slightly different build of the game.$860B-$86FF is the engine's $0A0B-$0AFF.In play (parts/game/work/play-map.vsf), with $01 = $35: all RAM but the I/O area, both ROMs out.
| Range | What | Part |
|---|---|---|
$0000-$00FF | the engine's zero page; $02-$0F are saved with the game | engine |
$0200-$30FF | the engine: two jump tables ($0204-$044E, $04CF-$0504), its code and its text block ($29E4-$30FE) | engine |
$3100-$33FF | the item table: eight bytes an item | game |
$3400-$59FF | the map the party is in: class layer, number layer, record, lists, text and code | map-nn |
$5A00-$5AFF | the sector buffer | engine |
$5B00-$5BFF | tables and work space the boot file copies from its $C17B, among them the menu bar's text at $5BAB | engine |
$5C00-$5FFF | the screen matrix: the bitmap's colours | engine (output) |
$6000-$7DFF | the bitmap, 24 character rows | engine (output) |
$7E00-$C5FF | the program in play: the game, or the start-up, the utilities, the Ranger Center, the radio or the death screen | each its own part |
$C600-$C9FF | the font, the track table $C930, the key table $C953, the sound player $C993 and its three sounds | engine |
$CA00-$CFFF | a module, the party-order program, or a picture unpacked for the picture window | module-n, order |
$D000-$DD7F | the tile set, in RAM under the I/O area | tiles-n |
$DD80-$DDFF | the map window's scroll copy, in RAM under the I/O area | engine |
$DE00-$EDFF | the tile layer of the map, one byte a square, under the I/O area and above it | map-nn |
$EE00-$F3FF | cleared by the start-up (startup $7F3D-$7F55); the game keeps four 376-byte records from $EE00 (game $BBC7) | engine |
$F400-$FBFF | the game state: party tables, saved zero page, line buffer, character records from $F500, written to the disk as the save | engine |
$FC00-$FFFF | the fast loader's computer side, and the hardware vectors in RAM | engine |
The bitmap's 25th character row would be $7E00-$7F3F; with $D011 set to $37 (24 rows, startup $7F55-$7F57) it is hidden, except that screen_shake's random vertical scroll (engine $077A) brings its top lines into view for a moment, and the programs load from $7E00.
$FF00), installed by the boot file. It moves whole 256-byte sectors with no link bytes: a file is a track, a logical sector and a page count, and logical sectors run down from there.$FFD3, $FDEA, $FDD8, $FFE8).$C930 gives for that track (engine $FD0B). The table is laid out as if indexed by the track number less one, and is indexed by the track number: track 17 is entered at logical sector 0, track 24 at 17 and track 30 at 16, below their top sectors of 20, 18 and 17. Files are laid out on the disks by the same rule: maps 0, 2, 5, 11 and 19 cross one of those tracks, and each loads the sectors the rule names, not the ones a full track would give (the 42 maps loaded by the game's own enter_map compared with the image read both ways). The game writes through the same routine.$2790).$2759).$27C3).$C800 (glyphs $60-$7F, the lower case), from T35/L16 for each unpack and replaces from T35/L11 afterwards (engine $0524). T35/L11 holds the same 256 bytes as the third page of the font's own file, four pages from T34/L14 (engine $C800).$280C-$283E).$D7 $CC side on the masters, $00 $CC side on copies (orientation.md, "The play disks").$1897) reads T35/L8 and wants its byte $FD to equal $ED, its byte $FE to be $CC and byte $FF the side asked for; until they are, it prints "INSERT SIDE n. (RETURN)". $ED is 0 in play, so the masters are refused (live). The start-up sets $ED to $D7 only around the check of side 1 before it loads the utilities (startup $81E4-$81ED), which is how Copy reads the masters.$2856, from $25BD); a map entered by a number from $80 up (the generic maps 5 and 11) never is (engine $2858).save_game (engine $18EA) copies zero page $02-$0F to $F478-$F485, sums $F400-$FBFF into one byte (engine $1918: for each page and Y = 0-254, the sum plus the byte, then plus Y and the carry out of that first addition; the carry out of the second is dropped, and byte 255 of each page is left out), keeps the sum at $F4FF, scrambles bytes 0-254 of every page by EOR with (2*Y* mod 256) EOR the sum (engine $1944), writes page n to T35, logical sector 7-n, and unscrambles. The key is the byte at $F4FF, saved in clear. The start-up reads the eight sectors back, unscrambles them and compares the sum (startup $830E-$832D), but a sum that does not match is accepted: every byte is EORed with twice its offset again, which leaves it as stored EORed with the key alone, and the start-up goes on with no message (startup $832F-$834C). So a save written in clear with a key of 0 loads as written, unless the sum the start-up forms from it comes out 0. Live: member 1's cash set to 12,345 in play and saved with S and Y; the eight sectors read off the disk image afterwards are this rule applied to memory as the save began, all 2,048 bytes, with the key $6B the sum as the code forms it.save_game has no side check, so a save lands on the side in the drive. It is called by Save (game $8820, after asking for side 1), by Radio (game $8802, before asking for side 1), at the end of every map change (engine $2600), by modules 1 and 3, by the Ranger Center's Start and by the utilities.$3400: the class layer, a nibble a square, the high nibble for an even column (engine $0953); the number layer, a byte a square (engine $098E); then the map record, at $3A00 on a 32 x 32 map and at $4C00 on the four 64 x 64 maps, 0, 12, 22 and 26. From $DE00: the tile layer, a byte a square (engine $0B06), unpacked from the map's stream.$5C-byte header: address words for the packed text (engine $1E4F), the monster names and records (game $9E76, $9EA4), a list of records for each square class 0-15 (engine $09B8), the map's own routines (game $885C) and its non-player characters (game $A424); then the size (+$2C, engine $25D3), the chance of a random encounter after a step (+$2F, game $B017), the tile set (+$30, engine $25EE), the tile drawn off the map (+$33, engine $0B5E), what a step costs (+$34 and +$35, a fraction of a minute and minutes, and +$36, ticks of the elapsed count, game $AF32-$AF72), and 37 message numbers for the phrases of combat (+$37-$5B, game $BCE1, $BCE5).$ACF3, a table of 16 words) runs on the record that word number of the class's list names (engine $09B8): class 1 shows a message, 2 tests the party (skills, attributes, items, cash, party size), 3 and 15 are encounters, 4 shows another tile and a message, 5 is loot, 6 an action, 8 a question, 9 radiation, 10 an exit, 11 a wall that shows its message when walked into (game $915E), and 12 changes other squares. Classes 0, 7, 13 and 14 do nothing, and no map uses 7, 13 or 14.$0B80-$0B8A; live). Tiles 0-8, the party, the creatures, the loot bag and the sign, are the same bytes in all nine tile sets as they load (the nine sets compared byte for byte); maps 0 and 26 exchange tile 7's bytes with the jeep's or the train's for their rides (map-00 $4FCD, map-26 $4EF9).$A0, "ignore armour", to 1 (game $82E7), but the routine that applies the damage replaces it, for each member, with bit 0 of the square record's byte 0 (game $90AF-$90B4), which is the flag byte of the check squares it was written for and the message number of a radiation square. So armour counts on radiation squares whose message is even and not on those whose message is odd. The radiation records name messages 23 on map 0, 28, 29 and 30 on map 19, 69, 70 and 71 on map 20, 0 on map 26, 12 on map 31, and 43 and 0 on map 38 (live).$0A00). An action square's byte $80 + n loads module n to $CA00 and runs it; a smaller n calls the map's own routine n (game $8845).$09B8). On map 11 the square at column 24, row 13, a wall on the screen, is class 2 number 2, and word 2 of class 2's list is $0000, so its record is read from address 0 on: the processor's port registers, then zero page. Its flags are the port's direction register, $2F, which has no checks tested and the move refused; the message it shows is the byte at $0001, the port, $35. So walking into that wall prints map 11's message 53, "Ah! Fresh air and open spaces once again.", every time (live). The wall is next to squares the party can walk to from the map's exit at column 28, row 0 (a search of the map's classes).$43/$44 points at (engine $1DFB). The engine's is $29E4-$30FE, messages 0-169, and $30FF is a spare byte.$291D): code $1E capitalises the next letter, $1F adds $1E to the next code, and the code whose alphabet byte is 0 ends the message (engine $28F4).$1F42, $1F64): $0A singular or plural on the count $38, $0B the current character's name, $0C his or her, $0E him, her or it, $0F the count, $0D a new line, $05 and $06 wait for RETURN, space or back-arrow (wait_return, engine $2501).$6000 with its colours at $5C00, in VIC bank $4000 (live: $DD00 = $86, $D018 = $79, $D011 = $B7, $D016 = $D8). The start-up writes $D011 as $37 (startup $7F55-$7F57, $7F91-$7F93); bit 7 reads back as the high bit of the raster line, which was past 255 when it was read. Text is drawn into the bitmap from the 6-pixel font at $C600 (engine $1F03).$2947), which scans the keyboard; the NMI vector ends in an RTI, so RESTORE does nothing (engine $2966).$C953: Apple II-style codes with bit 7 set, no shifted keys, no repeat, one new key per interrupt (engine $29BD-$29D4).$1B36, $1BBF): the game's bar is "Use Enc Order Disband View Save Radio", and its hidden keys I, J, K and L move the party, back-arrow and space (game $7F18).$7E00-$8DFF replaced at the hand-over, side 3 attached): above.orientation.md, "The play disks").$6A from 0 to 1 and the roster drawn over the bottom of the map window.$57/$58 before and after each key).$DC00) and port B ($DC01) and, as the control, on the interrupt handler (engine $2947). The party stayed at column 55, row 62 ($57/$58), and in each hold port A was read 0 times against 203 or 204 reads of port B and as many interrupts; I then moved the party north, to row$AE26), play_sound_16 (engine $0741) and play_sound (engine $C993). The three steps the party took called each once; K, which the map refused, called none.kit/c64/frame.py and drawn by site/lib/c64.js: 0 of 104,448 pixels differ from the emulator's picture, with the roster hidden and shown.enter_map, its pages, stream and tile set measured with two fills (orientation.md, "The maps").$6B.enter_map and K (south, into the wall) pressed five times, with RETURN through the credits' six screens; the messages came 91, 92, 93, 94, 91, and the clock did not move.enter_map and L (east) pressed three times; each press printed message 53 and left the party, the square (class 2, number 2) and the clock as they were. The processor read $2F $35 at $0000-$0001 throughout.redraw_view (game $AC8C) at 5:00, 6:00, 12:00, 17:00 and 18:00. The 36 radiation squares around the building at columns 57-58, rows 36-37 showed the sign at 5:00 and 18:00 and plain ground at the other three.$7E63), its idle turn (game $7E93) and, as the control, the interrupt handler (engine $2947): 2,999 interrupts, 58,486 passes of the loop (19.5 a frame), three idle turns, and the clock from 1:24 to 1:36, four minutes a turn on the world map. So with no key pressed a turn passes about every 840 frames, 17 seconds on a PAL machine.$9F = $FF (no radiation in view), and 471 in the one chunk that held an idle turn. The port of the loop on the page makes 21.19 passes a frame on a processor that has every cycle; giving the video chip 1,075 cycles a frame brings it to 20.02, and the Geiger counter's player on the How it works page runs it so.$8382-$83C0; parts/ranger/facts.md).$A8C5) was skipped for all four members and they lost 22, 23, 16 and 14 CON; with it poked to 22 the roll was taken four times and nobody lost any.$8390 read the five dice of each of 1,000 attribute rolls: 1,043 ones, 869 twos, 786 threes, 727 fours, 749 fives and 826 sixes (even dice: 833 each), and two neighbours equal 699 times in 4,000. From play-map.vsf, a stub threw 4,096 pairs of dice with roll_2d6_open's instructions between them (engine $084A-$0850), each after the seed was moved 1 to 256 times as read_key moves it: 869 doubles, 21.2% (fair dice: 16.7%).enter_map, every member's weapon cleared so that all four fought with fists, and K (south) pressed: "3 Shambler Ghouls appear at 14 feet." With every member ordered to attack each round, ten melee rounds (game $7F64) brought three kills. Each kill was worth 40 experience (engine $1C-$1E at game $8163), and each killer's experience went from 0 to 80 across the two adds at game $8163 and $8166. The screen named the kill ("KIT hammers the Shambler Ghoul for 6 points of damage killing it.") and printed no experience.enter_map), every weapon cleared, then Hell Razor (record $F500) given LK 3 (+$10) and a Throwing knife (item 15) in slot 1, equipped (+$BD, +$1F = 1); K brought "2 Shambler Ghouls appear at 14 feet." With every member ordered to attack, the first throw stopped at game $A7E7, where weapon_damage has written the roll into its two ADC operands ($A7EC, $A7F0): the roll was 10, and 2 and 0 were written there, the roll of a 1 and a 1. weapon_damage returned 65,535 ($A7F3: X:A = $FFFF), the kill path at game $A6E5 ran, and the screen read "Hell Razor attacks and hits 1 Shambler Ghoul for 65532 points of damage spinning it into a dance of death." (reference/unlucky-throw.png).$A7C3); weapon_damage adds it to the roll with plain ADCs ($A7EA-$A7F0), while the melee path adds it through num2_add_clamped (engine $07C6), which stops at 0. Of the item table's thrown and fired weapons the Throwing knife has the fewest dice, 2 (item 15, byte 6); every other gun and rocket has 3 or more (the Mangler's and Sabot rocket's 2 × dice − armour is never fewer than their dice), and explosives take no luck ($A054). So only a 1 and a 1 on the knife with an LK of 3 or 4 goes below 0. No loot record of the 42 maps names item 15 or a random class-2 item (43 records, scanned with the levels page's port); Christina, NPC 1 of map 32 ($40AE), carries one in her slot 3. The ranger roll gives an LK of 3 or 4 for 261 of the 7,776 ways five dice fall (3.4%), the best three of five for 6. The highest hit-point seed of any named monster in the 42 maps is the Night Terror's, 32,000 (map 23, monster 1), which gives at most about 40,000 hit points (game $9483-$94B9).$05C5), the calls that pass its flags (engine $05DA) and the channels' step (engine $05E6), read every 50 frames. While the title's picture moved, the engine called the tick 3,508 to 3,553 times in 50 frames, every call passing the flags, and the channels stepped 7 times, about 7 steps a second; in a later stretch of the same sequence 2,624 to 3,176 calls and 5 or 6 steps. Between the two the flag at engine $AC was 0 and nothing moved.work/lead/sample.py): one stratum for each annotator's range, and one for the maps' descriptions that a decoder wrote, 7,973 comments (69%). Three agents that wrote none of the 63 checked them against the bytes: 48 were right, 14 had a wrong detail and 1 had the code wrong, so 15 of 63, 23.8% (Wilson 95% interval 15.0-35.6%). Weighted by the strata's sizes the rate was about 52%, because two of the three generated descriptions drawn carried an error of their template. The details were callers and paths left out, counts, the keys a prompt takes, and a field read alike for every value of a flag; the one wrong comment had taken an operand's value in the snapshot for a constant (map 49's poisoned needle, said to miss its target: the member comes from an operand the game writes when a Use begins). All 15 were rewritten to agree with the code.$7E0C); the skill list's header said to print on row 2, where the new line it opens with puts it on row 3 (module 2 $CC63); and play_sound's last write said to start the note, which sound 11's does not, its control byte $A4 having the gate bit clear (engine $C993). All three were rewritten, and so were five neighbouring comments of the death screen that left out the game's instructions in the same way.Pokes that change the game within its own parameters. Each one names the variable it changes and whether it has been tested live. Untested pokes are labelled as candidates.
| Effect | Poke | Status |
|---|