The VIC-II will move the Commodore 64’s picture up to seven pixels sideways and seven pixels vertically for nothing: two three-bit values in $D016 and $D011 shift the display. The eighth pixel is where the work starts. The picture then has to move a whole character, so every one of the 1,000 bytes of screen memory is copied one place along, and often the 1,000 bytes of colour memory too, before the fine scroll can start again from the other end. Lasse Öörni, who writes as Cadaver and wrote the Metal Warrior games, gives the cost: “Shifting 1000 bytes (the whole screen) around takes more than half of the rastertime of a frame.”
A game that scrolls in only one direction can plan for that copy. A game that scrolls in eight directions, or in any direction, has to be ready for it on either axis at any time, while still moving the sprites, the enemies and the player. Martin Walker, writing a development diary for Zzap!64 in 1988 while he wrote Citadel, called the scroll routine “more often than not the longest and most ‘processor consuming’ of any in a game”, and noted that “Most eight-way scrolling games use a smaller part of the screen as the playing window to reduce this problem.”
Splitting the copy
The copy does not have to happen in one frame. Öörni’s ‘rant’ on the subject, published on his own site and mirrored on the Codebase64 wiki, splits it across as many frames as the fastest scroll speed allows: “If you scroll with 4 pixels/frame, you can split the shifting on two frames”. A half-finished copy would show on screen, so it is made on a second, hidden screen, and the VIC-II is switched to that screen once the copy is complete. This is double buffering, and on the C64 it costs only a write to $D018, which tells the chip where screen memory is.
Double buffering also makes the copy easier to write. When a program shifts one screen in place, the loop must run in the right direction or it overwrites bytes before it has copied them. When it copies from the visible screen into the hidden one, the order does not matter. Öörni indexes the source with the X register and the destination with Y, so “all 8 directions can be achieved by simply adjusting the initial index register values”.
Walker had used the same idea, which he called “the Blue Peter method”, after the BBC children’s programme’s habit of producing one it had made earlier: “preparing a second screen while the first was being displayed”. The price in his earlier routines was “the slight (4 frame) delay before moving off from rest”, and he added that a twelfth of a second “might not sound like very much, but you do notice it”.
Eight-directional: centred when idle
Öörni noticed that Turrican and Navy Seals “only scroll one char-length at a time, never less”, and suggests they keep the fine scroll “centered when idle”: when the screen is not moving, the scroll value rests at 4 or 3, the middle of a character. Each scroll is then a planned run of frames. At two pixels a frame to the left:
| Frame | Fine scroll | Work |
|---|---|---|
| 1 | 4 | first half of the screen copy |
| 2 | 2 | second half, and new data on the edge |
| 3 | 0 | copy colour memory, swap screens |
| 4 | 6 | nothing |
| 5 | 4 | start again, or stop |
To the right the run starts from 3 (3, 5, 7, 1, 3), because starting from 4 would bring the wrap one frame too early, with the copy not finished. The one-pixel step from 4 to 3 before the run is, in Öörni’s words, “barely noticeable”. The scheme works, but only in the eight directions and at speeds where the copy fits the run: “This method gives the possibility to 8-directional scrolling, but not freedirectional.”
Free-directional
Öörni’s own method drops the resting position. He worked it out himself and did not know whether any game had used it (“Possibly Chuck Rock or X-Out, they seem to allow quite free direction in scrolling”). Any speed up to four pixels a frame works, in any direction, with two kinds of frame:
- Add the speed to the fine scroll and, if it would wrap, hold it at the end of the 0 to 7 range. Then work out next frame’s values, this time allowing the wrap. If nothing wraps, no copy is needed. If something does, copy the screen onto the hidden screen and draw new data along the edges.
- Copy the colour memory, swap the screens and put the new scroll values into use.
Because the copy is always split over just two frames, each frame does more work than in the eight-way scheme, but Öörni found it “a much simpler approach than the 8-directional when you understand it”. In Metal Warrior 4 he kept the scroll position and speed with three extra bits of precision, so the fine scroll runs from 0 to 63 instead of 0 to 7 and the speed from −32 to +32. Speeds above four pixels a frame are not supported, “as screen shifting can happen on each second frame at most”. The work is split between two routines: SCROLLLOGIC runs at the start of the frame and decides whether a shift is due, also updating the value subtracted from sprite positions so that they stay in place, and SCROLLWORK runs at the end of the frame and does the copying.
Colour memory
Colour memory at $D800 is a separate 1K × 4-bit chip, fixed in place, so it cannot be double-buffered. It has to be updated while the rows being written are not on screen. “If you don’t care about NTSC compatibility,” Öörni writes, “you’ll have enough time to shift about 20-21 lines around during the time it’s not being displayed.” On NTSC machines, with fewer lines per frame, the update is split: the top half is shifted while the bottom half is still being displayed, and the bottom half once the display has finished.
There are two ways to make it cheaper, one good and one bad:
- Colour per block. If each tile has one colour rather than each character, as in the Shoot-’Em-Up Construction Kit, only every fourth column of colour memory changes when a map of 4×4 blocks scrolls, which cuts the work to a quarter. Achim’s tile-decoding page on Codebase64 sets out the trade: colour per tile is “very useful when you want to save rastertime” but “obviously less colourful”. Öörni points to the Metal Warrior 1 source for an example.
- Looking the colour up. Reading each character code from the screen and looking up its colour in a table (
ldy screen,x/lda charcolortable,y/sta colormemory,x) is easy, but “It is wasting 4 cycles each byte, compared to plain shifting”, and is “so slow that you can forget about NTSC compatibility when using it”. Öörni names Nobby the Aardvark, Darkman and Cool World as games that used it.
Tile scrollers
Malcolm Bamber’s 4 Way Scroll on Codebase64 shows the eight-way scheme in full source for a map of 2×2 tiles. Its raster interrupt moves the fine scroll two pixels at a time (3, 5, 7, 1 in one direction), draws half a tile at each step, keeps a spare colour map from which it copies the even and odd lines into colour memory on alternate passes, and swaps between screens at 1024 and 3072. The public-domain SEUCK Redux scroller on the same wiki includes a free-directional mode and a single-direction mode that spreads each copy over several frames to lower the cost per frame.
Where the objects live
A scrolling world also changes how a game keeps track of its objects. Using screen coordinates is fastest, since they are what the sprites use, but Öörni calls it “fast, but honestly, incorrect”. His example is the walking enemies in Turrican, which “sometimes behave very erratically” near the edges of the screen, “Because they’re only using the screen coordinate system, and checking only the characters on screen for background collisions.” Metal Warrior 1 and 2 stored positions as 16-bit pixel counts from the map’s top-left corner. Metal Warrior 3 and BOFH put the block number in the high byte and the position within the block in the low byte. A block is four characters, 32 pixels, so that leaves three bits of subpixel precision, and the map lookup for background collisions reads the high byte directly.
Öörni credits part of what he knew to the Finnish book Pelintekijän opas: Commodore 64 (“Game maker’s guide”) by Jukka Tapanimäki, whose C64 game Netherworld Zzap!64 reviewed in 1988, and to his older brother’s experiments with block-map scrolling in the late 1980s.
The C64 is not the only machine that had to copy to scroll. Scrolling and Hardware scroll compare it with the Spectrum, which had no scroll hardware at all, and with machines such as the NES and Amiga, whose hardware did more of the work.
Sources
- Lasse Öörni (Cadaver), “Multidirectional scrolling and the ‘game world’” (Rant 4), mirrored on the Codebase64 wiki (web, secondary): the cost of the copy, splitting and double buffering, the eight-directional and free-directional methods, colour memory, the lookup method, colour per block, coordinate systems and the book and brother credits. https://codebase64.net/doku.php?id=base:rant4
- Lasse Öörni (Cadaver), “Significant tricks & techniques in MW4” (Rant 11), Codebase64 wiki (web, secondary): subpixel scroll values, the speed limit,
SCROLLLOGICandSCROLLWORK. https://codebase64.net/doku.php?id=base:rant11 - Martin Walker, Citadel development diary, Zzap!64 issue 41, September 1988, pp. 98–99: the cost of the scroll routine, smaller playing windows, “the Blue Peter method” and the four-frame delay.
- Zzap!64 issue 41, September 1988, pp. 116–117: Netherworld review, programmed by Jukka Tapanimäki.
- Christian Bauer, The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64 (28 August 1996): section 2.4, colour RAM as a 1K × 4-bit memory at
$D800; section 3.2, the scroll bits of$D011and$D016and the screen address in$D018. - Malcolm Bamber, “4 Way Scroll”, with source parts 1 and 2, Codebase64 wiki (web, secondary). https://codebase64.net/doku.php?id=base:4_ways_scroll
- “Scrolling and SEUCK file player”, Codebase64 wiki (web, secondary). https://codebase64.net/doku.php?id=base:scrolling_and_seuck_file_player
- Achim, “Decoding 4x4 tiles”, Codebase64 wiki (web, secondary). https://codebase64.net/doku.php?id=base:decoding_tile_based_maps
- Antikvaari.fi, catalogue record for Pelintekijän opas: Commodore 64, Jukka Tapanimäki, Tecnopress, ISBN 9518320160 (web, secondary).