The Commodore 64 graphics chip VIC-II offers 8 hardware sprites. This number is not that impressive, but as C64 sprites can be placed freely on any part of the screen without any limitation, the hardware sprites offered are usually enough for most tasks.
However, sometimes more sprites are needed. On a soccer game, more than 8 sprites at a time may be displayed for instance. War games with many enemies and big objects will usually require sprite multiplexing as well.
Each unexpanded sprite is 24 x 21 dots only. If a big sprite is required, it can be made up of more sprites together. This kind of approach easily asks for more than 8 sprites. Expanded sprites can be of help to represent big objects as well, but they do imply a resolution loss. And even by using them, multiplexing may be required anyway.
The sprite multiplexing technique doesn’t create new hardware sprites. That is plain impossible. This technique just allows you to show the same sprite on different parts of the screen by displacing it very quicky between two given positions. That will make the illusion of two different sprites. And if the sprite takes its two different positions on the same frame, no flickering will happen. The following little program shows off this technique (you can past it on the VICE emulator to test it).
10 v=53248:pokev+21,1:poke2040,192:fort=12288to12350:poket,255:next:pokev+39,1 15 r=53265:s=128:pokev,100 20 waitr,s:pokev+1,100:pokev+1,200:goto20
The above approach cannot be always used however. If the real sprite and the multiplexed “virtual” one must be positioned on the same Y coordinate, they just cannot be shown on the same frame.
So, we may need another technique concerned with displaying the sprite on a position on a frame, and on a different position on the following frame. Let’s say, on even frames the sprite is placed at x1, y1, and on odd frames the sprite is placed at x2, y2. This just makes the illusion of having two different sprites at different positions on the screen. Since alternate frames are used, the frame rate of the process is 25 fps. That is not enough to trick our eyes, so flickering will be noticeable. But, this “flickering” technique allows for free positioning of the “virtual” sprites. A simple BASIC program roughly showing this technique follows. You can paste it on VICE.
10 v=53248:pokev+21,1:poke2040,192:fort=12288to12350:poket,255:next:pokev+39,1 12 pokev+32,0:pokev+33,0:printchr$(147) 15 r=53265:s=128:pokev+1,100 20 waitr,s:pokev,100 30 waitr,s:pokev,200:goto 20
Even if BASIC is slow, it is possible to do some more advanced sprite multiplexing with it. The following program puts sixteen sprites on the screen. Sprite positions are quickly changed by using the “PRINT on memory” technique. Location 648 decimal is changed so that characters are no longer printed on the screen but on the VIC-II registers instead. That kind of approach may easily crash the machine, so it must be used with extreme care. VIC-II registers start is 53248, so the ratio 53248/256 = 208 is the new content of location 648.
This “PRINT on memory” trick is mandatory here. Otherwise, slow POKEs will not allow such a multiplexing.
After obvious initialization tasks, line 4 sets the X position of each sprite. X positions will stay fixed during program execution, so simple POKE instructions are used.
On line 6, among other things, the KERNAL is told to print characters on VIC-II registers (POKE 648,208).
On line 8, a string is created. A$ holds the Y positions of the sprites dealing with both the upper and the lower part of the screen. Please note the HOME control character on that string. It is required so that registers can be written again and again from the beginning. Please also note the cursor control characters, which are required so that X sprite coordinates are left unchanged.
Graphics characters have been chosen so that their screen codes match the Y sprite positions values.
NOTE: system interrupts are not disabled to show the efficiency of the multiplexing routine. RUN/STOP is not disabled as well because I wanted to keep the program as short as possible. However, do not press RUN/STOP while the program is running.