VDP-1 by yzoer
From XCore Exchange
VDP - Video Display Processor VDP-1 is the first in a series of Video Display Processors, primarily modelled after console / handheld hardware such as the Sega Genesis and Nintendo's Gameboy Advance.
With only a handful of resistors to form an R2R DAC, a single-core XS1 using VDP-1 can output either VGA or NTSC. Given the nature of a tile- and spritebased architecture, the memory footprint for applications is surprisingly small and allows for applications to be loaded concurrently.
Overview
As mentioned before, VDP-1 uses a tile- and spritebased architecture. What this boils down to is that the system doesn't use a frame-buffer but instead uses a scanline based rendering approach, saving significant amounts of memory. VDP-1 can render 2 independently controlled Backgrounds that can be moved both horizontally and vertically, on a per-pixel basis.
Similarly, the system allows for 32 independently controlled objects, called sprites. Sprites can be compared to 'mini-backgrounds' and range from 8x8 to 64x64 pixels. Like backgrounds, the can be positioned on a per-pixel basis.
In order to use VDP-1 efficiently, a brief description of the system will be described below.
Tiles
Tiles are the foundation of VDP-1. A tile is the base unit for both backgrounds and sprites and consists of 8x8 pixels. Each pixel in a tile can take one of 16 colors. Each color is therefore encoded as a 4-bit nibble. With 4-bits per pixel and 64 pixels per tile, the total memory footprint for a tile is 32 bytes.
Palettes
VDP-1 supports 16 palettes of 16 colors each, giving a grand total of 256 colors on-screen at once. Each palette entry consists of 5 bits for red,green and blue respectively ( 5:5:5 ) and therefore occupies 2 bytes per entry. The total palette foot-print therefore comes in at 512 bytes ( 16 palettes x 16 entries x 2 bytes per entry = 512 ).
Palettes are closely related to tiles ( and sprites ) in that each 4-bit pixels in a tile serves as a look-up into a specified palette. In order to see the relationship between pixels on-screen, tiles and palettes, consider the following scenario:
Tile pattern definition in hexadecimal:
unsigned int tiledata[] = {
0x11111111, 0x10000001, 0x10000001, 0x10022001, 0x10022001, 0x10000001, 0x10000001, 0x11111111,
};
and a corresponding palette:
unsigned short palette[16] = {
RGB(0,0,0), // black RGB(31,0,0), // red, RGB(0,31,0), // blue
};
For each nibble in the tile, a corresponding color is fetched from its referenced palette. So for each pixel that is serialized out of the tile, a 15-bit RGB value is displayed on-screen. By limiting the number of colors in a tile to 16, we saved ourselves 4 times the amount of memory!
Backgrounds
Now that we know how a tile gets defined in memory and how each pixels gets a color from its specified palette, we need to figure out a way to organize the tiles together so we can create more interesting images. This is where backgrounds come in. Backgrounds are yet another level of indirection, which is often somewhat confusing.
A background is a rectangular area in memory that specifies which tiles get rendered where and with what palette. Each background is made up of 64x32 'cells', creating a 512x256 image.
Cells contain the index and palette number of the tile to be rendered as well as two additional bits to allow for tiles to be flipped horizontally and vertically. Since tiles are always of a fixed size, each index is internally multiplied by 32.
- more to come -
