What is the "side scrolling hack" from old games?
Asked Answered
C

4

15

I have heard that old arcade side scrolling games used a specific programming hack to enable performant side scrolling.

I understand that years ago the machines weren't powerful enough to repaint the whole screen every frame as it's done nowadays. There are techniques, such as dirty rectangles, which allow to minimise the screen area needed to repaint when the background is stationary and only the sprites move.

The above approach only works when the background doesn't change (and hence most of the screen pixels remain stationary).

Vertical scrolling games, like old school shoot'em ups, have the thing a bit more difficult with the background changing every frame due to the scroll. However, one could take advantage of the way pixels are fed to the display (line-by-line). I imagine that one could use a bigger buffer and shift the data pointer some lines "down" every frame, so that it will be redrawn starting from another position, thus giving the impression of a smooth scroll. Still only sprites (and a bit of the background at the edge of the screen) would need to be redrawn, which is a serious optimisation.

However, for side scrolling games, the thing is not that simple and obvious. Still, I'm aware that somebody, somewhere in the past, has though of an optimisation which (with some limitations) allowed the old machines to scroll the background horizontally without redrawing it every frame.

IIRC it was used in many old games, mostly 80's beat'em ups, as well as in demoscene productions

Can you describe this technique and name its author?

Complicate answered 13/11, 2011 at 17:15 Comment(1)
Two excellent non-overlapping answers! I wish I could accept both :-)Complicate
S
11

I have written games for the good old C64 doing exactly this. And there are basically two things to be aware of:

  1. These games were NOT using bitmapped graphics, but instead used "remapped" character fonts, which means that chunks of 8x8 pixels were actually hurdled around as just one byte.

  2. The next thing to note is that there was hardware support for displacing the whole screen seven pixels. Note that this didn't in any way affect any graphics - it just made everything sent to the TV a little bit displaced.

So 2) made it possible to really smooth scroll 7 pixels away. Then you moved every character around - which for a full screen was exactly 1000 bytes, which the computer could cope with, while at the same time you moved the scrolling register back 7 pixels. 8 - 7 = 1 means that it looked like you scrolled yet another single pixel... and then it just continued that way. So 1) and 2) combined made the illusion of true smooth scrolling!

After that a third thing came into play: raster interrupts. This means that the CPU gets an interrupt when the TV/monitor was about to begin drawing a scan line at a specified location. That technique made it possible to create split screen so that you weren't required to scroll the entire screen as opposed to my first description.

And to be even more into details: even if you didn't want a split screen, the raster interrupt was very important anyway: because it was just as important then as it is today (but today the framework hides this from you) to update the screen at the right time. Modifying the "scroll register" when the TV/monitor was updating anywhere on the visible area would cause an effect called "tearing" - where you clearly notice the two parts of the screen are one pixel off sync with each other.

What more is there to say? Well, the technique with remapped character sets made it possible to do some animations very easily. For example conveyors and cog wheels and stuff could be animated by constantly changing the appearance of the "characters" representing them on screen. So a conveyor spanning the entire screen width could look as it was spinning everywhere by just changing a single byte in the character map.

Stotinka answered 13/11, 2011 at 17:22 Comment(5)
Nice. I tried something like this on a PC, but was hampered by only being able to put 256 different "characters" in a set.Phoenix
there was also a flag in the C64's video chip to shrink the display horizontally by one character so you wouldn't notice the extra character currently scrolled in.Submerged
@yi_H quite so. Now you're really into details! :-)Darby
Notice that on c64 you have to also move 1000 bytes of color ram, which can't be buffered on a copy screen on contrary of screen ramPhelps
...which is why scrollers were always using just four colors!Darby
P
8

I did something similar way back in the 90s, using two different approaches.

The first one involved "windowing," which was supported by the VESA SVGA standard. Some cards implemented it correctly. Basically, if you had a frame buffer/video RAM larger than the displayable area, you could draw a large bitmap and give the system coordinates for a window within that area that you wanted to display. By changing those coordinates, you could scroll around without having to re-fill the frame buffer.

The other method relied on manipulating the BLT method used to get a completed frame into the frame buffer. Blitting a page to the frame buffer that was the same size as the screen is easy and efficient.

I found this old 286 assembler code (on a functioning 17 year old floppy!) that copied a 64000 byte (320x200) screen from an off-screen page to the video buffer:

  Procedure flip; assembler;
    { This copies the entire screen at "source" to destination }
    asm
      push    ds
      mov     ax, [Dest]
      mov     es, ax
      mov     ax, [Source]
      mov     ds, ax
      xor     si, si
      xor     di, di
      mov     cx, 32000
      rep     movsw
      pop     ds
    end;

The rep movsw moved CX words (where a word is two bytes in this case). This was very efficient since it's basically a single instruction that tells the CPU to move the whole thing as quickly as possible.

However, if you had a larger buffer (say, 1024*200 for a side scroller), you could just as easily use a nested loop, and copy a single row of pixels per loop. In the 1024-pixel wide buffer, for instance, you could copy bytes:

start          count            
0+left         320
1024+left      320 
...
255*1024+left  320

where left is the x coordinate within the large background image that you want to start at (left side of the screen).

Of course, in 16-bit mode, some magic and manipulation of segment pointers (ES, DS) was required to get a buffer larger than 64KB (in reality, multiple adjacent 64k buffers), but it worked pretty well.

There were probably better solutions to this problem (and definitely better ones to use today), but it worked for me.

Phoenix answered 13/11, 2011 at 17:28 Comment(0)
H
2

Arcade games frequently featured customized video chips or discrete logic to allow scrolling without the CPU having to do (much) work. The approach would be similar to what danbystrom was describing on the C-64.

Basically the graphics hardware took care of fine scrolling characters (or tiles) and the CPU then handled replacing all tiles once the scrolling registers have reached their limit. I am currently looking at the Irem m-52 board which deals with multiple scrolling backgrounds in hardware. Schematics can be found online.

Howitzer answered 23/2, 2012 at 22:47 Comment(0)
L
1

For right scrolling on the Commodore Amiga we used the Copper to right-shift the screen up to 16 pixels. When the screen had shifted we added 2 bytes to the start address of the screen buffer while on the right side we used the Blitter to copy graphics from the main memory to the screen buffer. We would set the screen buffer slightly larger than the screen view so that we could copy the graphics without you seeing a flickering effect from the copying on the right side of the viewport.

Lading answered 22/4, 2014 at 9:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.