The MOS 6567/6569 video controller (VIC-II) and its application in the Commodore 64
Contents 3. Description of the VIC 3.8. Sprites
3.8.1. Memory access and display |
The 63 bytes of sprite data necessary for displaying 24×21 pixels are stored in memory in a linear fashion: 3 adjacent bytes form one line of the sprite. These 63 bytes can be moved in steps of 64 bytes within the 16KB address space of the VIC. For this, the VIC reads a sprite data pointer for each sprite in every raster line from the very last 8 bytes of the video matrix (p-access) that is used as the upper 8 bits of the address for sprite data accesses (s-accesses). The lower 6 bits come from a sprite data counter (MC0-MC7, one for each sprite) that plays a similar role for the sprites as VC does for the video matrix. As the p-accesses are done in every raster line and not only when the belonging sprite is just displayed, you can change the appearance of a sprite in the middle of its display by changing the sprite data pointer. When s-accesses are necessary for a sprite, they are done in the three half-cycles directly after the p-access belonging to the sprite within the raster line. The VIC also uses the BA and AEC signals (as in the Bad Lines) to access the bus in the second clock phase. BA will also go low three cycles before the proper access in this case. The s-accesses are done in every raster line in which the sprite is visible (for the sprites 0-2, it is always in the line before, see the timing diagrams in section 3.6.3.), for every sprite in statically assigned cycles within the line. Like the text and bitmap graphics, the sprites also have a standard mode and a multicolor mode. In standard mode, every bit directly corresponds to one pixel on the screen. A "0" pixel is transparent and the underlying graphics are visible below it, a "1" pixel is displayed in the sprite color from registers $d027-$d02e belonging to the sprite in question. In multicolor mode, two adjacent bits form one pixel, thus reducing the resolution of the sprite to 12×21 (the pixels are twice as wide). Moreover, the sprites can be doubled in their size on the screen in X and/or Y direction (X/Y expansion). For that, every sprite pixel simply becomes twice as wide/tall, the resolution doesn't change. So a pixel of an x-expanded multicolor sprite is four times as wide as a pixel of an unexpanded standard sprite. Although both expansions look similar, they are implemented completely differently in the VIC. The X expansion simply instructs the sprite data sequencer to output pixels with half frequency. But the Y expansion makes the sprite address generator read from the same addresses in each two lines in sequence so that every sprite line is output twice. Every sprite has its own sprite data sequencer whose core is a 24 bit shift register. Apart from that, there are two internal registers for every sprite: "MC" (MOB Data Counter) is a 6 bit counter that can be loaded from MCBASE. "MCBASE" (MOB Data Counter Base) is a 6 bit counter with reset input. Besides, there is one expansion flip flop per sprite that controls the Y expansion. The display of a sprite is done after the following rules (the cycle numbers are only valid for the 6569): The expansion flip flip is set as long as the bit in MxYE in register $d017 corresponding to the sprite is cleared. If the MxYE bit is set in the first phase of cycle 55, the expansion flip flop is inverted. In the first phases of cycle 55 and 56, the VIC checks for every sprite if the corresponding MxE bit in register $d015 is set and the Y coordinate of the sprite (odd registers $d001-$d00f) match the lower 8 bits of RASTER. If this is the case and the DMA for the sprite is still off, the DMA is switched on, MCBASE is cleared, and if the MxYE bit is set the expansion flip flip is reset. In the first phase of cycle 58, the MC of every sprite is loaded from its belonging MCBASE (MCBASE-<MC) and it is checked if the DMA for the sprite is turned on and the Y coordinate of the sprite matches the lower 8 bits of RASTER. If this is the case, the display of the sprite is turned on. If the DMA for a sprite is turned on, three s-accesses are done in sequence in the corresponding cycles assigned to the sprite (see the diagrams in section 3.6.3.). The p-accesses are always done, even if the sprite is turned off. The read data of the first access is stored in the upper 8 bits of the shift register, that of the second one in the middle 8 bits and that of the third one in the lower 8 bits. MC is incremented by one after each s-access. If the sprite display for a sprite is turned on, the shift register is shifted left by one bit with every pixel as soon as the current X coordinate of the raster beam matches the X coordinate of the sprite (even registers $d000-$d00e), and the bits that "fall off" are displayed. If the MxXE bit belonging to the sprite in register $d01d is set, the shift is done only every second pixel and the sprite appears twice as wide. If the sprite is in multicolor mode, every two adjacent bits form one pixel. In the first phase of cycle 15, it is checked if the expansion flip flop is set. If so, MCBASE is incremented by 2. In the first phase of cycle 16, it is checked if the expansion flip flop is set. If so, MCBASE is incremented by 1. After that, the VIC checks if MCBASE is equal to 63 and turns of the DMA and the display of the sprite if it is. As the test in rule 3 is done at the end of a raster line, the sprite Y coordinates stored in the registers must be 1 less than the desired Y position of the first sprite line, as the sprite display will not start until the following line, after the first sprite data has been read (as long as the sprite is not positioned to the right of sprite X coordinate $164 (cycle 58, see rule 4)). Sprites can be "reused" vertically: If you change the Y coordinate of a sprite to a later raster line during or after its display has completed, so that the comparisons mentioned in rules 1 and 2 will match again, the sprite is displayed again at that Y coordinate (you may then of course freely set a new X coordinate and sprite data pointer). It is therefore possible to display more than 8 sprites on the screen. This is not possible in the horizontal direction. After 24 displayed pixels, the shift register has run empty and even if you change the X coordinate within a line so that the comparison in rule 4 will match again, no sprite data is displayed any more. So you can only display up to 8 sprites within one raster line at a time. Once again an overview of the scheme of p- and s-accesses: p-access
Adresses
13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
VM13 | VM12 | VM11 | VM10 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | Sprite number
Data
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
MP7 | MP6 | MP5 | MP4 | MP3 | MP2 | MP1 | MP0
s-access
Adresses
13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
MP7 | MP6 | MP5 | MP4 | MP3 | MP2 | MP1 | MP0 | MC5 | MC4 | MC3 | MC2 | MC1 | MC0
Data
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
MxMC=0
8 pixels (1 bit/pixel) "0": Transparent "1": Sprite color ($d027-d02e)
MxMC=1
4 pixels (2 bits/pixel) "00": Transparent "01": Sprite multicolor 0 ($d025) "10": Sprite color ($d027-d02e) "11": Sprite multicolor 1 ($d026)