The Inner Workings of the VDP
This page presents a more in-depth discussion of how the VDP actually implements the features discussed in the VDP overview section. This information represents a consolidation of the knowledge that the programmer uses to program the VDP, but in keeping with the spirit of this guide I will restrict the discussion to a conceptual level instead of discussing specific VDP register settings, VRAM address blocks, and so on. Anyone interested in such details can see the References and Further Reading section for links.
- Tile Structure
- The VDP’s Tables
- Memory Limitations
- Data Transfer Limitations
- Shadow and Highlight Mode
- Raster Effects
The Video Display Processor, despite its name, is not a general-purpose processor like the 68000. Rather, it is an ASIC (application-specific integrated circuit). This means that, unlike the 68000, the VDP does not process general arithmetic or movement instructions written by the programmer. Instead, the VDP operates in a strictly defined way: it renders the screen according to the settings of its registers, using the data in its memory. The job of the programmer as it relates to the VDP is to set the VDP’s 24 registers and write the appropriate data to the VDP’s memory. The VDP then handles the rendering and output process.
The VDP has 24 registers used to configure it. Each register is set by writing a particular command to the VDP’s control port. The registers of the VDP are used to do things such as:
- turn on the display
- set NTSC or PAL mode
- define the starting addresses of the plane, sprite, and scroll tables in VRAM
- set the background color
- set either H32 (256-pixel) or H40 (320-pixel) display mode
- turn on shadow and highlight mode
- set the size of the background planes
- set the position of the window plane
- set horizontal scrolling as per plane, per row, or per scanline
- set vertical scrolling as per plane or per column
- turn on the horizontal and vertical interrupts
- set up DMA
This list is not comprehensive, but it includes most of the configurable settings that can be changed through the registers. Aside from writing the settings values to the registers, the only other step the programmer must take to use the VDP is to write the data to the VDP’s memory.
The VDP uses 64 KB of memory, called VRAM (Video RAM), to hold graphic tiles and tables. These tables, which will be introduced shortly, contain information such as the arrangement of the background plane tiles and the sprites. In addition to VRAM, the VDP has access to 80 bytes of VSRAM (Vertical Scroll RAM) for the vertical scrolling table and 128 bytes of CRAM (Color RAM) for the color palette table.
Most of the VRAM is used to store the graphic tiles. The VDP references the tile data stored in VRAM when it renders the screen, so a tile cannot be rendered if it is not stored there (in other words, the VDP cannot draw a tile to the screen that is stored in the ROM or the 68000’s RAM—such tiles must first be written to VRAM).
Let’s look at the exact structure of a tile. A tile is a bitmap—a series of bits defining the colors of the pixels that make up the tile. For the VDP, a single pixel is defined by only four bits (i.e., a number between 0-15, which can be conveniently represented by a single hexadecimal digit). How can a pixel only be defined by a number between 0-15, when the VDP has 512 colors available? The answer is the VDP uses indexed color, meaning each pixel does not reference a specific color; instead, it references an entry on one of the VDP’s four color palettes (each of which contains 16 colors). Here is an example of a tile using hexadecimal notation:
The information contained in a tile gives us only an incomplete picture. The tile itself does not tell us which of the VDP’s four color palettes the pixels are referencing. The palette information must come from the plane or sprite table that references the tile. The following example shows the above tile using different color palettes:
Note that the first color of a tile (color 0) is always transparent, regardless of the color defined in the palette. Here, transparent means the pixel is not visible at all—whatever plane or sprite is under the pixel will be fully visible. Using transparent pixels allows tiles to appear less than 8 x 8-pixels in size, which is useful for drawing small objects, curves, and so on.
The use of indexed color for tiles is beneficial for several reasons. First, it greatly reduces the memory required to store a tile. If each pixel contained the full color specification instead, it would require nine bits rather than four to represent one of the VDP’s 512 colors. Second, it allows colors to be changed easily without changing the tile itself. In the following example, the tiles under the water are the same as the tiles out of the water—only the color palettes have changed:
Using the same tiles but referencing different color palettes is also a simple way to add variety to background tiles or enemy sprites. The tradeoff to indexed color, of course, is that the VDP is limited to just 16 colors (more accurately, 15 + transparent) per tile.
The VDP’s Tables
So far, we’ve seen that the VRAM contains the tile data used by the VDP to render the game’s graphics, but the tile data alone does not tell the VDP how the tiles should be arranged and displayed on the screen or with which color palette. This information comes from a set of tables stored in the VDP’s RAM, listed here (note that although these are termed ‘tables,’ they are actually just ordered lists of data):
- Pattern table for Plane A
- Pattern table for Plane B
- Pattern table for the window plane
- Sprite attribute table
- Horizontal scroll table
- Vertical scroll table (in VSRAM)
- Color palette table (in CRAM)
The pattern tables define the tiles that make up each of the planes, the sprite attribute table defines the tiles and on-screen locations of the sprites, the scroll tables are used to set offsets for scrolling each plane, and the color palette table defines the colors of the four palettes. Each of these is looked at in more detail beginning in the next section. The first five tables listed are stored in VRAM together with the graphic tiles. The amount of memory occupied by each of these tables varies depending on the VDP’s settings. For example, the plane pattern tables will take up half the space with a plane size of 32 x 32 compared with a plane size of 64 x 32. Table size is therefore not fixed. Consequently, the starting location of each table in VRAM must be set in the VDP’s registers. The ability to set the starting location of each table is beneficial, since memory can be saved if, for example, using a smaller plane size. The tables in VSRAM and CRAM are fixed size; this memory cannot be used for any other purpose.
Plane Pattern Tables
Let’s look at the plane pattern tables first. Simply put, these tables contain the arrangement of the graphic tiles in their desired order on the plane (i.e., which tile and where). Each entry in the table defines one graphic tile of the plane. The order of the entries reflects the order in which the tiles are displayed: the first entry calls the tile in the top left of the plane, the second entry calls the tile to the right of the first, and so on across the top row before shifting down to start again at the left side of the second row. Since a single entry of the table references a single graphic tile on the plane, the table has the same number of entries as there are total tiles on the plane (e.g., a pattern table for a 64 x 32-tile plane contains 64 x 32 = 2048 entries).
Each pattern table entry is 2 bytes in size and contains several important pieces of information about the tile it is referencing:
- The tile’s priority (low or high)
- The color palette used for the tile (0-3)
- The horizontal and vertical orientations of the tile (reversed or not)
- The indexed number of the tile in VRAM
As mentioned previously, each tile of a plane can have its priority and color palette set independently of other tiles on the plane. Additionally, tiles can be flipped horizontally and/or vertically, which allows for more flexibility in how a single tile in VRAM is displayed.
Within the pattern table entry, tiles are referred to by their indexed position within VRAM rather than by their actual VRAM address. Index 0 refers to the first tile in VRAM, Index 1 to the second tile, and so on. A precise address in VRAM is not needed, since all tiles are necessarily 32 bytes in size.
Different pattern table entries can reference the same tile repeatedly. This is obvious from most games, where background tiles will tend to repeat heavily. The reasons for this will be discussed more below, but the basic explanation is that relatively few tiles can be stored in VRAM at once, making repetition a necessity. Reversing the orientation of a tile or changing its color palette are two ways to add variety while using the same set of tiles.
The window pattern table follows the same format as the plane pattern tables: each entry is 2 bytes and contains information on tile priority, color palette, orientation, and VRAM index. The on-screen size of the window plane is adjustable and is set by the VDP’s registers. However, the window pattern table is always the same size. In H40 mode, it is 64 x 32 entries, even though only the upper-left-most 40 x 28 entries can actually be used to draw the window’s tiles. Since the window plane does not scroll by design, any entries outside of this 40 x 28-entry area are unused. In addition, the window plane typically only covers a small portion of the screen, so any entries that are not part of the on-screen window can be used to store graphic tiles (although such tiles must be in 32-byte increments from the beginning of VRAM, since they are indexed by the VDP). When the VDP renders the screen, it treats plane A and the window plane as being the same plane for purposes of determining priority.
Sprite Attribute Table
The sprite attribute table holds all of the information concerning the sprites. Each entry in the table represents a single sprite, and since the VDP supports 80 sprites, there are 80 entries in the table. Each entry is 8 bytes in size and contains the following information:
- The display position of the sprite (on a 512 x 512 grid)
- The sprite’s size (1-4 tiles on each axis)
- The sprite link data (0-79)
- The sprite’s display priority (low or high)
- The color palette used for the sprite (0-3)
- The horizontal and vertical orientations of the sprite (reversed or not)
- The indexed number of the first sprite tile in VRAM
This list gives us a glimpse of the VDP’s strength at rendering sprites. Let’s go through and examine each of these specialized functions.
Each sprite has an adjustable display position that determines where the sprite appears on the screen. This display position is situated on a 512 x 512 grid, where each point of the grid corresponds to one pixel. Because the pixel resolution of the screen in H40 mode is just 320 x 224, it is possible for sprites to have an off-screen display position. On the horizontal axis, where zero is to the left, any display position between 128 and 447 is on-screen, and on the vertical axis, where zero is to the top, any display position between 128 and 351 is on-screen. Beyond these values, sprites will be off-screen. Having off-screen display positions allows the VDP to keep track of sprites even when they are not visible.
An individual sprite can have a size of 1-4 tiles on both the horizontal and vertical axes (ranging anywhere from 1 x 1 tile to 4 x 4 tiles). Since this size is defined in the sprite attribute table for each sprite, a variety of different sprite sizes is possible at once. This ability to mix small sprites with large sprites is very useful for creating a variety of different-sized objects on the screen.
Sprites are ordered relative to one another according to what can be called sprite priority (different from display priority). Sprite priority determines which sprites are drawn to the screen first. In the event that the per-scanline sprite limit is exceeded, the sprites with the lower priority will not be drawn to the screen. In addition, sprites with higher sprite priority appear above those of lower priority—regardless of their display priority setting (low or high). This ordering is achieved in the sprite attribute table through the use of link data. The first sprite in the table, sprite 0, always has the highest priority; it links to a second sprite, which can be anywhere in the table, by referencing its index number (1-79). This second sprite now has the second highest priority, and it links to a third sprite, which will have the third highest priority, and so on. In this way, each sprite links to another, and as the linked sprite becomes further away from sprite 0, its priority becomes lower. The last sprite, which has the lowest priority, links to index 0 (the first sprite) and completes the loop.
Similar to the plane pattern tables, each entry of the sprite attribute table lists the display priority (low or high), color palette (0-3), and orientation (horizontal/vertical reversed or not) of the sprite. However, unlike the background planes, these factors cannot be adjusted per-tile for sprites. Rather, they can only be changed per-sprite. Specifically, all of the tiles in the sprite must have the same display priority, color palette, and orientation.
Each entry of the sprite attribute table references the VRAM index of a single graphic tile. You might wonder: A sprite can be made of more than one tile, so why does the sprite attribute entry reference only a single tile? The entry also lists the sprite’s size, so the VDP knows how many tiles to read from VRAM in order to draw the sprite. It simply reads however many tiles in sequential order beyond the tile that is referenced. That means that all of the tiles for a single sprite must be stored in VRAM next to each other, in a specific order: starting at the top left of the sprite, the tiles are arranged moving down the column, then shifting one column to the right and again moving down, and so on.
Let’s now move on to the horizontal and vertical scrolling tables. These tables handle the scrolling behavior of planes A and B. Each table entry contains an offset value that determines the positioning of the plane relative to the display area; adjusting this offset each frame causes the screen to scroll.
The horizontal scrolling table is stored in VRAM, and the size of the table is determined by the type of scrolling set in the VDP registers. Recall that there are three types of horizontal scrolling: full-screen scrolling, 8-pixel row scrolling, and line scrolling. The type of scrolling is set by the VDP registers and applies to both planes (each plane cannot have a different scroll type). For full-screen scrolling, the horizontal scrolling table contains just two entries, one for plane A and one for plane B. Each entry is 2 bytes in size and contains the scroll offset, which is a number between 0 and 1023. A scroll offset of zero means that the left edge of the plane aligns with the left edge of the screen. If we add five to the scroll offset, we cause the plane to shift to the right by five pixels (scrolling occurs at a per-pixel level). If we subtract five from a scroll offset of zero, we cause the plane to shift to the left by five pixels. Since the scroll offset wraps around, subtracting five from zero results in an offset of 1019. You might wonder: if the plane size is 64 tiles wide (i.e., 512 pixels wide), how can the offset be larger than 512? The offset has a range of 1024, which can be precisely divided by each of the possible horizontal plane sizes (256, 512, and 1024 pixels). For a 512-pixel-wide plane, the offset values are repeated once. For instance, offsets of 511 and 1023 are functionally the same.
To reiterate: adding to the scroll offset causes the plane to shift to the right, and subtracting from the offset causes the plane to shift to the left. This shift is not yet scrolling, however; it is simply a one-time change in the relative positioning of the plane. To create a scrolling effect, the scroll offset must be changed each frame. In a typical sidescrolling platformer, the screen scrolls from right to left. To achieve this type of scrolling, we subtract a fixed quantity from the scroll offset each frame (e.g., we can subtract a value of one from the scroll offset each frame to cause the screen to scroll to the left at a rate of one pixel per frame). Many games feature a foreground, plane A, and a background, plane B, where the foreground scrolls at a faster rate than the background to achieve a sense of depth. That is accomplished by simply subtracting a higher quantity from the scroll offset for plane A compared to the offset for plane B. In summary, for full-screen scrolling, the horizontal scrolling table contains just two entries, one with the scroll offset for plane A and the other with the scroll offset for plane B; scrolling is achieved by adding to or subtracting from these two scroll offsets.
The full-screen horizontal scrolling table requires just 4 bytes of VRAM (2 bytes for each entry). However, to achieve line scrolling, a much larger table is required. Recall that line scrolling is the effect of scrolling (at most) each of the 224 horizontal scanlines at a different rate. Line scrolling is achieved in the same way as full-screen scrolling, except a scroll offset value is required for each scanline of each plane. To scroll each line independently, the scroll offsets must all be changed each frame. This can be thought of as horizontally dividing the plane into 224 slices and then shifting each slice left or right relative to the display area. A total of 448 table entries are required to accomplish this—224 entries per plane. Since each entry is 2 bytes, the scrolling table for line scrolling takes up a significant 896 bytes of VRAM.
Not only does the line scrolling table require a lot of VRAM, but it also requires each of the 448 entries to be updated every frame to achieve scrolling (assuming both planes are in use and are scrolling). This is a significant amount, given that only several KB of data can be written to VRAM each frame (more on this later). Even if most of the lines scroll at the same rate, every entry must be individually updated. In other words, when line scrolling is enabled, there is no difference if most of the lines scroll together or separately—either way, the same VRAM space is required, and every entry must be updated individually. This represents a possible tradeoff to using line scrolling, since VRAM space is typically in short supply and not much data can be written to VRAM per frame.
Row scrolling—scrolling every 8-pixel row independently—functions nearly identically to line scrolling. The same 448-entry table (896 bytes) is required in VRAM, but only 1/8th of the entries are actually used. There are 28 rows per plane, and each row has a scroll offset, for a total of 56 table entries for both planes. The only advantage of row scrolling over line scrolling is that updating the table requires writing less data to VRAM; instead of having to update each of the 448 entries per frame (assuming both planes are in use), only 56 entries have to be updated.
The vertical scrolling table works in much the same way as the horizontal scrolling table. A big difference, however, is that it has its own area of memory called VSRAM (Vertical Scroll RAM). VSRAM is 80 bytes in size and is independent of the 64 KB of VRAM; it is used exclusively for the vertical scrolling table and cannot be used to store any other data.
As with horizontal scrolling, full-screen vertical scrolling uses just the first two entries of the scrolling table, one entry for plane A and one for plane B. Each entry is 2 bytes in size and contains a scroll offset ranging from 0 to 1023, where a value of 0 means the top edge of the plane is aligned with the top of the display area. Adding to the offset causes the plane to shift up relative to the display area, while subtracting causes the plane to shift down. Therefore, to achieve a down-to-up scrolling effect, the offset is increased each frame, while to achieve an up-to-down scrolling effect, the offset is decreased each frame.
The final scrolling mode to look at is column scrolling, whereby every vertical two-tile (16-pixel) column can be scrolled independently. Since the display area shows 40 tiles on the horizontal axis, it can be divided into 20 columns. Scrolling for each column is set by a 2-byte scroll offset in the vertical scrolling table; with two planes, the table contains a total of 40 entries (at 80 bytes in size—the total size of the VSRAM). As with full-screen vertical scrolling, adding to the scroll offset causes the column to shift downward, and subtracting causes it to shift upward.
There is a bug related to column scrolling that affects most Mega Drive models (except for some late revisions). In some situations where column scrolling is used, the left-most column of the screen will display garbage tiles. Due to how the VDP defines vertical columns when there is also horizontal scrolling, the first column can be mis-defined as “column -1,” which does not actually exist in the scrolling table. Developers were aware of this bug, so they typically obscured the left-most column using a black bar made of sprites. If you ever notice a black bar creeping onto the left side of the screen when playing a game, you can be reasonably sure some column scrolling is coming up.
Color Palette Table
The last table to consider is the color palette table. This table defines the 64 colors that make up the four palettes. The color palette table is stored in its own area of memory called CRAM (Color RAM). CRAM is 128 bytes in size—the same size as the color palette table. Each entry of the table is 2 bytes (so 64 entries total) and defines one color of one palette. To define the color, the entry contains a 9-bit RGB value. This means that each of the color components (Red / Green / Blue) is defined by 3 bits (i.e., a number from one to eight). The eight available shades for each color component are generally evenly-spaced in terms of brightness, from minimum brightness (black) to maximum brightness. A total of 512 colors are available by combining different shades of the three color components.
The entries of the color palette table are ordered according to palette number and color index. The first entry contains the first color (color 0) of the first palette, the second entry contains the second color of the first palette, and so on. Any of the available colors can be placed in any table entry; there is no required ordering based on color type. The only point of caution is that the first color of a palette is never usable by sprites or planes—it will always become fully transparent when indexed by a tile. The first color is only usable as the solid background color, as defined by the VDP registers.
Now that we’ve looked at the contents of the VRAM—graphic tiles and tables—we can discuss memory limitations in detail. All tiles of the planes and sprites that comprise the game screen must be stored in VRAM when they are displayed—but exactly how many tiles can fit in the VDP’s 64 KB of VRAM? Let’s do some basic math, keeping in mind that 1 KB = 1,024 bytes. Since a single tile is 32 bytes, then exactly 2048 tiles can fit in VRAM (65,536 bytes / 32 bytes/tile = 2048 tiles). However, this is a theoretical maximum that doesn’t take into account the memory required for the tables. Recall that the size of each table depends on the VDP’s settings. Let’s consider how much of the VRAM the tables require under several different setups. Keep in mind that the focus here is only on NTSC H40 mode (other modes will have different memory requirements).
First, imagine a simple sidescroller with the following setup: 1) a plane size of 64 x 32 tiles, 2) no window, and 3) horizontal full-screen scrolling. Let’s calculate the VRAM space required for the tables. Since we are really interested in how many graphic tiles will fit in VRAM, let’s use tiles as the basic unit of our calculation rather than bytes. We will start with 2048 tiles and subtract the number of tiles lost to the tables. For each of the plane pattern tables, 2048 entries (64 x 32) are used, and each entryl is 2 bytes. That results in each table taking the space of 128 tiles, and since there are two planes and therefore two tables, a total of 256 tiles are lost for the plane pattern tables. Because there is no window plane, no additional memory is required for the window pattern table. The sprite attribute table contains 80 entries (one for each sprite), and each entry is 8 bytes, so the table takes the space of 20 tiles. Finally, the horizontal scrolling table contains just two entries, one each for plane A and B, and each is 2 bytes, so one tile is lost. Let’s add it all together:
- Plane A pattern table: 128 tiles
- Plane B pattern table: 128 tiles
- Sprite attribute table: 20 tiles
- Horizontal scrolling table: 1 tile
- Total: 277 tiles
Therefore, of a total possible 2048 tiles, 277 are lost to the tables. For this particular setup, there is enough memory in VRAM to store 1771 tiles.
Let’s consider a second scenario—a slightly flashier sidescroller that uses a window and line scrolling with a larger plane size. The particular setup is: 1) a plane size of 64 x 64 tiles, 2) a window of 40 x 3 tiles, and 3) horizontal line scrolling. The plane pattern tables are now double the size of the previous example, equaling 512 tiles. Each entry of the window pattern plane requires 2 bytes, but here we have to remember that the window plane is actually 64 tiles wide, even though only 40 tiles are displayed. Since we have three rows of tiles, the total number of entries required for the window pattern plane is 192 (64 x 3). That means the table size is 384 bytes, or 12 tiles. Finally, each entry of the scrolling table requires 2 bytes, and for line scrolling there are 224 entries per plane (one entry per line), for a total of 896 bytes, or 28 tiles, for both planes. Let’s again break down the exact number of tiles lost for each table:
- Plane A pattern table: 256 tiles
- Plane B pattern table: 256 tiles
- Window pattern table: 12 tiles
- Sprite attribute table: 20 tiles
- Horizontal scrolling table: 28 tiles
- Total: 578 tiles
For this setup, there is enough memory in VRAM to store 1470 tiles (2048 – 578). By increasing the VDP functions used, the amount of space available for tiles can drop significantly.
Let’s put these tile numbers into perspective by considering how many tiles are required to fill the screen. In H40 mode, the display area has a size of 40 x 28 tiles, which equals 1120 tiles. Therefore, if we just want to fill the display area with unique tiles, we have to use approximately 2/3 of the total available tile space. That does not leave us much room to include the sprites and their animation frames, and there won’t be any variety to the background if we want to scroll it. In practice, it is very uncommon to have the background composed of unique tiles due to memory limitations; instead, background tiles tend to repeat heavily. A major focus of level design is determining the best way to make compelling backgrounds while using the least number of tiles possible.
Data Transfer Limitations
Tile memory is severely limited—but can’t we just load new tiles into VRAM when we want them? Transfer speeds are also limited, and it is not possible to instantaneously swap out all tiles in VRAM with new ones. Between the rendering of each frame, approximately 7 KB can be written to VRAM using DMA (if using the 68000 to write the data rather than DMA, only about half that amount can be written). In terms of tiles, about 230 tiles can be written per frame, but that is only in the case that nothing else is being written. The sprite and scrolling tables are also typically updated each frame (and possibly the plane tables), so that reduces the amount of tile data that can be written. Furthermore, since the CPU becomes inactive when doing DMA, there might be problems with game logic calculations if writing a large quantity of data to the VDP via DMA.
This information is intended to illustrate that 1) memory for storing graphic tiles is very limited in the VRAM, and 2) updating the VRAM with new graphic tiles is a relatively slow process. Managing these limitations is one of the most important hurdles that game designers face.
Shadow and Highlight Mode
Shadow and highlight mode is an interesting feature of the VDP that, unfortunately, was not used by many games. The reason for that might be the mode’s somewhat tricky interaction with display priority and the color palettes. Let’s take a brief look at how shadow and highlight effects are created. As a reminder, if a pixel is shadowed, its brightness is lowered, and if it is highlighted, its brightness is raised. Shadow and highlight mode is activated through one of the VDP’s registers.
There are two ways to create shadow effects and one way to create highlight effects. First, the display priorities of the background planes can be manipulated to create shadow. If overlapping tiles of both background planes are set to low priority, they will become shadowed. Since priority is set on a per-tile basis for the planes, the shadow only applies to those tiles set to low priority (meaning there can be multiple shadowed and non-shadowed areas on the planes). If one of the overlapping tiles is set to high priority, even if it is transparent, the shadow effect will not appear for the other tile. A sprite overlapping the low priority, shadowed background tiles can be either low or high priority; if it is low priority, it will also become shadowed, and if it is high priority, it will not be shadowed (although the background tiles remain shadowed).
The second way to create shadow is through the use of sprites. If a sprite’s pixels are set to color 15 of palette 3, those pixels will become transparent and the planes under them will become shadowed. For this to work, there cannot be a plane at a higher priority than the sprite. This method only applies shadow to the planes and cannot be used to shadow another sprite.
The method for creating highlight operates according to the same principle of sprite-based shadowing mentioned in the previous paragraph—only the palette color is different. If a sprite’s pixels are set to color 14 of palette 3, those pixels will also become transparent and create a highlight effect on the planes under them. Again, highlight applies only to planes and not to other sprites.
Regarding colors, there are only three possible settings of a pixel: normal, shadowed, or highlighted. If the background planes are set to low priority and therefore shadowed, they won’t be doubly shadowed if a sprite with color 15 of palette 3 is also overlaid. Rather, they just remain shadowed. However, if a sprite set to highlight overlays planes that are shadowed, the two effects cancel each other out and the planes become normal.
There is a quirk (bug?) in shadow and highlight mode: if a sprite pixel is set to color 14 of palette 0-2, it will appear normal even if it should be shadowed (as would be expected if both planes and the sprite were low priority).
Some of the most interesting effects that the VDP can produce are done by changing the VDP’s registers or memory while it’s in the middle of rendering a frame. These are known as raster effects. To understand how these effects are accomplished, it’s first necessary to understand at a basic level how the screen is displayed on a CRT television.
In a CRT, as shown in the above diagram, an electron beam sweeps across the screen from left to right (viewed from the front), beginning at the top and ending at the bottom, to create a single frame. In this process known as raster scanning, each horizontal sweep of the beam across the screen creates what is called a scanline. The VDP’s active display area—the viewable area used to show the game’s graphics on the television—consists of 224 such scanlines (thus the vertical resolution of 224 pixels), and the VDP generates 60 frames per second in NTSC mode.
When the electron beam reaches the end of each scanline, there is a short retrace period where the beam shuts off and shifts across and down to begin the next scanline. This is known as the horizontal blanking interval (abbreviated HBlank). Similarly, when the electron beam reaches the end of the last scanline at the bottom of the screen, it shuts off and shifts back to the top left in the vertical blanking interval (abbreviated VBlank). HBlank occurs at the interval between scanlines, while VBlank occurs at the interval between frames. VBlank is significantly longer than HBlank, although both occur in a tiny fraction of a second.
We can also refer to active scan, which is the time when the VDP is rendering the screen. Active scan includes the time when the electron beam is drawing the display, as well as HBlank (the VDP remains busy during HBlank). Passive scan, in contrast, occurs during VBlank when the VDP stops rendering the screen.
During active scan, the VDP is very busy preparing and rendering each line of the display. Consequently, it’s difficult for the 68000 to send data to the VDP then. For that reason, most data is written to the VDP during VBlank, when the VDP is free to accept write commands from the 68000. Approximately 7 KB of data can be written during one VBlank if using DMA. However, it is possible to send a tiny amount of data to the VDP during active scan, with some limitations.
In NTSC H40 mode, just 18 bytes can be written to the VRAM each scanline (twice that if writing to CRAM or VSRAM). Aside from the small size, the main limitation is that this data can only be written at specific access slots during active scan, one byte per access slot, spread across the rendering of each scanline. Care must be taken to avoid having the 68000 attempt to write too much to the VDP during active scan, since the 68000 will pause other processing activity to wait for the access slots to become available (the VDP has a small queue to hold incoming data, but it can easily be exceeded and cause the 68000 to pause). Therefore, although data can be written to the VDP during active scan, the amount is very small, and doing so runs the risk of slowing down the CPU.
By changing values in the VDP’s registers or tables during active scan, various raster effects can be achieved. Perhaps the most recognizable effect is the mid-frame palette swap, accomplished by writing a new color or colors to the CRAM after a portion of the screen has been rendered. The same tile, referencing the same color palette, can be displayed in different colors on different vertical sections of the screen. Another such raster effect is vertical scaling, done by changing a plane’s vertical scroll offset in VSRAM while the frame is being rendered. This causes the plane to vertically stretch or contract. Examples of these can be seen in the next section.
Want to post a comment? You can do so here.