1988 Β· Ocean

Where Time Stood Still

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/spectrum/where-time-stood-still with me to Gold.

The whole game, playable in the browser: the title and the control selection, the plateau's sixteen areas, the party of four, the creatures, the menus and the music. Every routine is ported from the game's own Z80 code and was run beside it until the two agreed.

Loading the game's data…
Γ—2 βˆ’ and + zoom Β· Esc goes back
  • To start the game: press 2, 0, Y to select Joystick and begin
  • ← β†’ ↑ ↓ walk the leader; with fire held, run
  • Left Ctrl, Left Shift, Right Ctrl or Right Alt: fire, which shoots the way the leader faces
  • Space the menus: the arrows move the pointer and fire picks. Or just click and use the mouse: a click opens the menus, the pointer follows the mouse and a click picks; with the game paused, a click carries on
  • 1, 3 or 4 on the control selection: keys of your own, Interface 2 or cursor, played on the Spectrum's keys
  • πŸ”­ Wide view: βˆ’ and + zoom, Esc goes back to the 128's screen

The game's own screen, drawn from the port's memory each frame as the Spectrum 128 would show it, at the 128's own pace: the game draws a new view six to eight times a second, into the screen it is not showing, and then shows it. The sound is the port's writes to the AY chip and the beeper, played by the site's model of them as each frame is shown.

01 Β· The port

Every routine of the game, checked against the original

The game is a Z80 program of 25,132 bytes of code, about half in the 128's main memory and half in its bank 3. The port is the same program written again in JavaScript, one function for each routine the game calls and each place its tables jump to, 452 in all, reading and writing the game's variables at the game's own addresses in the 128's own banks. The page runs only the port: the game's code is in the tests, as the original the port is held to.

CheckWhat it showed
Each routine aloneSixteen test files take each routine at the moments the game itself calls it, in 148 saved moments of play, some with registers and variables changed at random. The port's routine and the game's own, on the kit's Z80, run from the same machine, and every byte of the eight banks, the paging, the AY's registers and the writes to the chips must come out the same.
The whole program in lockstepThe port's program runs beside the game's, pass by pass: from the loader's hand-over through the control selection and 1,500 passes of play, and from each of the 148 moments for 400 passes, with the stick, fire and the menus played at random. Every byte of the eight banks, the paging, the border and the AY was the same at every stop, but for the stack and the two bytes where the sound driver keeps the stack pointer.
Area 14 and the ROMArea 14's map and the mask of one frame of the arm that reaches out of a rock run on past the end of memory into the 128's ROM. The page carries those 171 bytes of ROM 0 and nothing else of it, and the port reads them where the game does. The lockstep runs through area 14.
The page's memoryThe page carries the game's memory as the loader leaves it. Of the main memory's 12,863 bytes of instructions, all but 1,068 are set to zero: 858 the game rewrites and reads as variables, and 210 it reads as data, the start-up code that becomes the sprites' visibility mask and tune 18's code, which tune 17 plays as notes. Bank 3 is carried whole, its code included, because the game's random numbers are bank 3's bytes read one after another. The page's machine on that memory and on the whole memory ran the same, frame for frame, from the hand-over for 2,100 frames and from 37 of the moments for 600 frames each, with input at random.
The paceThe port executes no instructions, so the page charges each stretch of the main loop, each routine, and each byte, row and character it copies or draws the T-states they cost the game, fitted on 22,798 passes timed on the kit's model of the 128: from the hand-over and from the moments, with walks and runs that drag the windows and scroll the view. On 14,799 passes it was not fitted on, four in five come within 1.1 % of the game's time. From 25 other moments, with the same walks, runs and shots on both for 30 seconds, the page takes within 4 % of the game's time for the same passes, 1.6 % less on average, and from the hand-over it reaches play within 2.2 % of the game's time.
The listingPorting a routine means reading every instruction of it. Eleven of the listing's comments disagreed with what the game was shown to do, and are corrected in the Source code tab; four more are completed.

02 Β· Differences

What differs from a Spectrum 128

The game plays as it does on a Spectrum 128, at the 128's pace. These are the places where the page cannot be the machine, and what it does instead.

On a Spectrum 128On this page
The interrupt can fall between any two instructions of the main program.The interrupt runs between two of the port's routines, at the clock's time for it. The bytes the interrupt changes and the main program reads in the middle of a routine (the clock's count to midnight, the light and its count) are read after the interrupts due by then have run.
Each instruction takes its T-states, and a pass takes as long as its drawing does.The port executes no instructions. Each stretch of the main loop, each routine and each byte, row and character it draws costs what it cost the game, fitted on the game's own timings (01, The pace), so a pass takes about as long as on the 128.
Copying the view to the screen takes longer than a frame, with the interrupts off, so in play the 128 misses about one interrupt in five, and the game's clock, which counts them, loses a fifth of its time.The page's copy takes the game's time with its interrupts off too, and loses the same interrupts.
The AY chip plays the music and the effects, and the beeper clicks with the drum.The site's models of the AY and the beeper play the port's writes to them, each at the time in the frame it was made, as the frame is shown.
The ULA draws the screen a line at a time as the beam crosses it.The page takes the screen whole at the moment the beam would reach its first line, so a change made while the beam is drawing shows a frame later, all at once.
The 128's ROM holds the editor and BASIC. The game calls none of it, but reads 171 of its bytes as the bottom of area 14's map.The page carries those 171 bytes of the original 128's ROM and nothing else of it. A +2's ROM differs in two of them, which are two blocks of that map; the page has the original 128's.
The joystick is a Kempston interface, or the keys.The arrow keys are a Kempston joystick, with Left Ctrl, Left Shift, Right Ctrl or Right Alt for its fire, and the pad under the screen is one too; every other key is the Spectrum's own, Left Ctrl and Left Shift as well.
The game has no mouse.The mouse works the menus. In play a click opens the first menu, as SPACE does. In a menu that is open, the pointer goes where the mouse is in its window, and a click there is fire. With the game paused from its menu, a click is fire, which carries on.

03 Β· The wide view

The plateau beyond the 128's screen

The 128 shows the party 28 characters by 18 of a map 256 by 128, about a sixty-fifth of the area they are in. The Wide view button fills the window with the plateau round that view, drawn by the game's own routines, and leaves the game as it is.

Each part of the wide picture is what the game would draw if its view stood there at that moment. The page keeps a copy of the machine from each pass of the main loop, taken where the pass has moved the actors and scrolled the view and is about to draw the actors. For each piece of the picture, 28 characters by 18, the page moves the copy's view there and runs the pass's drawing on it:

The copy, with its view movedThe game's routine
puts back the actors far from the view$DCB9
brings in the creatures and objects near it$DC0B
draws the scenery into the view's buffer$A012
copies the buffer to the screen the game is not showing$963B
draws the rope, the shots, the actors and the objects over it$E6B3, $C21B, $A6F4

The page reads the piece back from that screen and sets the copy back before the next piece, so the game's own machine is never touched. The 128's view sits in the middle of the wide picture, outlined, drawn as before. The menus and the conversation window open over it where the 128 opens them, and the panel the 128 shows under the view sits at the foot of the window.

A creature far from the view is drawn where the game keeps it. The game has eight places for actors and brings a creature into one only when the view comes near; until then the creature is a record of its place. Each pass the game takes the next of its 46 records and, when that creature is out of play, moves it a step along its route ($E187), so a creature out of play takes a step every six or seven seconds at most. The wide view draws a creature out of play as the game would draw it on bringing it in, standing at its record's place between those steps. It comes to life when the 128's view comes near enough to bring it into play.

The plateau is sixteen areas, four by four, and the game holds one at a time. Each area's map overlaps the next by 28 characters across and 20 down, and the game moves into the next area when the view's column reaches 228 or its row 108 ($DB0B). Past the edge of the view's area the wide view draws the next one, on a copy that has crossed into it as the game crosses: the actors carried ($DBDD), the objects carried ($F72A) and the area loaded ($87CF). Where two maps overlap they do not always agree. The wide view draws the overlap from the view's own area, so the picture there changes when the view crosses, while the 128 keeps the rows it drew from the area before until they scroll out of its view. Areas 12 and 15 have no scenery, and the wide view leaves them black, with the world beyond the plateau's edge.

The wide view is made for a large monitor. Full screen fills it, βˆ’ and + set the zoom from Γ—1 to Γ—6, and the page remembers the zoom; Esc goes back to the 128's screen. The CRT screen draws the whole wide picture as one tube. In full screen at Γ—2 on a 2560 by 1440 monitor the window shows about 27 times as much of the plateau as the 128's view. The keys play the game as before.