1988 · Electronic Arts

Wasteland

This minisite was contributed by air. It’s currently claimed by air who is editing it to reach a Gold tier standard.

Wasteland finds every file on its four disk sides by track and sector, and writes each map back as the party leaves it, so the disks hold the world as the party left it. Side 3 also carries an older build of the title program.

01 · The disks

Four disk sides and no file names

Apart from its two boot files, Wasteland keeps nothing on its disks that a directory listing would show. Its own loader reads sectors by number, and every map, program, and save has a fixed track and sector on the four sides.

This picture needs JavaScript and the site’s c64.js.

The four sides. A row for each track, track 35 at the top, and a box for each sector, coloured by what the side holds there. Pick a file and its sectors light up in the order the loader reads them. Logical numbers lines the sectors up as the files count them, Physical order as they pass the drive’s head. The places come from the directories on the four master sides. The order is the engine’s own arithmetic ($FFAC, $FD0B), ported and run against the original on a 6502 simulator for every pair of track and sector bytes, 131,072 cases, and for every file through the game’s own read and write calls, with no difference.

A file is three numbers: a track, a logical sector, and a count of 256-byte pages. The loader reads that sector, steps to the next, and stops when the count runs out ($FF00). The numbers for the maps and the item tables are kept in two directories on track 35, four bytes a file: the track, the sector, the count, and the side ($2790). Every side carries both directories, but only the side that holds a file fills in its place. Elsewhere the entry is three zeros and the side. The game reads the side first, prints INSERT SIDE and that number until the side is in the drive, and then reads the directory again from it ($27C3).

Logical sectors are the files’ own numbering. A table for each speed zone turns them into the drive’s physical sectors, which are numbered in the order they pass the head: logical n is physical 10n mod 21 on tracks 1-17, 8n mod 19 on tracks 18-24, 7n mod 18 on tracks 25-30, and 6n mod 17 on tracks 31-35 ($FFD3, $FDEA, $FDD8, $FFE8). A file runs down from its first logical sector, and in every zone the next one is 11 physical places further round. Ten other sectors pass the head between two of a file’s.

The count is all a load knows of a file’s length, and the Ranger Center’s is too big. The program is eight pages, but its header asks for 72, so the load also brings in the 64 sectors after it: the radio program, side 1’s two item tables, packed modules, tile sets, and portraits. Nothing in the Ranger Center reads them, and the game program loads over all of it when the party leaves ($7EEE).

One place off

After logical sector 0 the loader moves down a track, skipping track 18, and starts the new track at the logical sector a 35-byte table gives ($FD0B, table $C930). The table holds each track’s top sector, track 1’s first. The loader reads it by the track number, which counts from 1, so it gets the entry for the track above: the one it has just left. Within a speed zone the tracks have the same top sector, and this changes nothing. At three zone edges it does. Track 30 is entered at logical sector 16, track 31’s top, where its own is 17. Track 24 is entered at 17 where its own is 18. Track 17 gets the entry for track 18, which the step never enters, and that entry is 0. The strip under the map shows the 35 bytes, and the three that differ open a file that crosses them.

The disks were written by the same rule, so the game reads what was meant. The world map starts at track 20, logical sector 9, runs through track 19, takes the one sector of track 17 the step gives it, and goes on at track 16. The other 20 sectors of track 17 hold filler on every side, and so do the top sectors of tracks 24 and 30. Read with each track entered at its top, the world map would come out with 1,477 wrong bytes, and maps 2, 5, 11, and 19, the game program, and the Ranger Center would go wrong as well. The game writes through the same routine, so a map saved back lands where it will next be read.

The world is written back

The maps on a side are the world as the party left it. Leaving a map writes its pages back to the sectors they were read from ($2856, called from $25BD). A loot bag’s contents are rolled the first time it is opened, and the roll goes back to the disk with the map ($9194). A shop writes its item table back after a sale or a purchase, so its stock lasts ($CB56), except after a purchase that sells out its stock, which leaves without writing it ($CBBA). Maps 5 and 11 can escape this. The flags sector, track 35 logical sector 8, sends every map number from $80 to $BF to map 5 and from $C0 to $FC to map 11 ($2621), and a map entered by one of those numbers is never written back ($2858).

Players turned this into a copier. T. Maki told the Wasteland Ranger HQ-Grid's Underground (22 April 1996) to keep an unused copy of a side, put it in the drive before entering a place, take everything there, and put the used disk back before leaving. J. Dunlap (26 September 1998) did the same with a backup of a data disk. A map is read from the disk in the drive on the way in and written to the disk in the drive on the way out, so the copy keeps the place as it was before the party took anything, and every visit with it finds the loot again.

The party's own records are the one thing a fresh disk does not reset. Clem the Hick (24 October 1996) won the game more than once this way and found that the second time through and on, you won't get the huge bonus from Ranger Center at the end. Destroying Base Cochise sets a bit in every Ranger's record ($CA03-$CA1C). The radio pays the reward, 10 points to spend and 10 more MAXCON, only to a Ranger whose record has that bit set and a second bit clear, and it sets the second bit as it pays ($7EBC-$7EDD). Both bits travel with the Ranger, so the base can fall again on a fresh disk, and the radio pays nobody twice.

The save and its sum

The party itself lives in memory at $F400-$FBFF: the party tables on the first page, then a page for each character. Saving copies the fourteen zero-page bytes that hold the map number, the party’s place, the clock, and the game time into the first page. The save then adds the eight pages up into a one-byte sum, scrambles them with it, and writes page n to track 35, logical sector 7 − n ($18EA).

This widget needs JavaScript and the site’s c64.js.

One page of the save. Left, the page in memory as the play snapshot holds it. Right, the same page as the last save wrote it to the disk, made by the port’s scramble. Change a member’s cash in the game and save, patch it on the disk with the old sum left in place, or write the whole save unscrambled with 0 for the sum, and the start-up’s reading of the result appears below. The port matched a save the game made in the emulator, byte for byte (cash 12,345, sum $6B). The sum, the scramble, the save and the start-up’s check were each run against the game’s own code on a 6502 simulator, 1,549 cases, with no difference.

The sum ($1918) runs over bytes 0 to 254 of each page. Each byte is added to it, then the byte’s offset, with the carry from the first addition going into the second. The scramble ($1944) EORs each of those bytes with twice its offset and with the sum. Byte 255 of each page is left out of both, and the sum itself is kept there on the first page, in clear, at $F4FF.

There is no slot to choose. The game saves at the end of every change of map, when the new map’s side is in the drive ($2600), and Save asks for side 1 first ($8820). The save goes to whichever side is in the drive, with no side check, so each side keeps a save of its own. At the title, Start asks "Use last saved game (Y/N)?". Y loads side 1’s save ($8284), and N reads all four sides and takes the save with the longest game time ($8228).

The start-up reads the eight sectors back, unscrambles them with the byte at $F4FF, and sums them again ($830E, $8321). A save whose sum does not match is not refused. The start-up EORs every byte with twice its offset once more and goes on ($832F), which leaves each byte as it was stored on the disk, EORed with the byte at $F4FF alone. A party whose cash was changed on the disk comes back with its names and numbers garbled. A save written unscrambled, with 0 at $F4FF, comes back exactly as written, unless its sum happens to be 0. What the second EOR was meant for is not known.

Masters and play disks

The game will not play on its master disks. Track 35, logical sector 8 of every side ends in three bytes: $D7 $CC and the side number on a master, $00 $CC and the side on a copy. Before the game uses a side, it compares them with the byte in $ED, then $CC, then the side it wants ($1897). In play $ED is 0, so only a copy passes. The start-up sets $ED to $D7 only around its check of side 1 before it loads the utilities ($81E4), which is how Utils loads from a master.

This widget needs JavaScript.

The side check. The last three bytes of track 35, logical sector 8, against the three the check wants. The game’s check ran on a 6502 simulator over 6,912 combinations of the three bytes, $ED and the side asked for, then from the start-up’s Utils and in play on all four sides of the masters and the copies. The port gave the same answer every time.

The utilities’ Copy reads the identity itself and copies only a master ($8068). It moves a side as 642 sectors, from track 35, logical sector 16 down to track 1, logical sector 0, with the loader’s own step ($833F), and writes $00 where the master has $D7 ($83E7). The step never reaches 41 sectors: all of track 18, track 17 above logical sector 0, and the top sectors of tracks 24 and 30. On sides 1 and 3 track 18 holds the directory that names the boot files, so a copy cannot be booted, and the game always starts from the master. The last choice in the picker above shows a whole copy.

02 · Disk side 3

Secret: side 3 carries an older version of the title program

The second disk's first side has a boot sector of its own, named "A JERKVISION PRODUCTION", and an earlier build of the program that shows the title. The older build shows a different picture, has none of the title's sounds, and cannot run from its own disk.

Side 1's title: the planet and the WASTELAND logo, the story text, and Start, Utils and Written by Alan Pavlish on the bar.
Side 1's start-up, as the game boots.
Side 3's start-up: a planet in blue and grey with no logo, stripes at the right of the picture, and Computer defense initiative activated.
Side 3's start-up, run over side 1's engine with side 3 in the drive.
Side 1Side 3
Wheretrack 4, logical sector 16, 16 pages loaded to $7E00
Where $7E00 jumps$7F2A$7E06
Bytes that differ2,766 of 4,096
Copyright lineCopyright 1986-88 Interplay Productions.Copyright 1986,87 Interplay Productions.
Title soundsthe siren, the whistles and the explosionsthree calls to RTS stubs ($7E03-$7E05); no SID register is written
Boot sector's nameWASTELANDA JERKVISION PRODUCTION

Both screens are from the emulator. Side 3's program was put in place of side 1's at the moment the boot hands over to it, with side 3 in the drive. It unpacks its picture from side 3's track 3 and stops at "Computer defense initiative activated." Side 3's addresses are its own, at the load address side 1's start-up shares, and have no Source page.

Booted on its own, side 3 does not get as far. Its boot file loads track 34, logical sector 10 of side 3 to $0200-$30FF, where side 1 keeps the engine and side 3 keeps other bytes. The first raster interrupt after the hand-over jumps through the engine's table at $04F9 into them, and the processor halts on a JAM instruction at $2931.