The key to working with custom VDLs is knowing how to write a VDL. To start, you must know how the VDL processor reads a VDL.
When the 3DO hardware is finished reading the VDL entry, the display generator puts up a new frame line using the entry's display parameters. If a VDL entry is specified for the next line, the VDL processor reads that entry during the next horizontal blank, and uses the entry's settings to control the display of the following line. If no VDL entry is specified for a line, the VDL processor keeps the same display settings in effect with one exception: pointers to bitmap buffers.
As you can imagine, if each display line used the same part of the bitmap buffer for its pixels, each line would be identical and you'd end up with a screen full of vertical stripes. To fully display the contents of the bitmap buffer, the pointer to the bitmap buffer must advance through the buffer from line to line. To make this possible, the VDL processor uses two registers: the current bitmap-buffer register and the previous bitmap-buffer register.
As the names imply, one register-the current bitmap-buffer register-stores a pointer to the bitmap buffer used to display the current line. (The current line is the one immediately following a horizontal blank.) The other register-the previous bitmap-buffer register-stores a pointer to the bitmap buffer used to display the previous line. Why does the VDL processor need a pointer to the previous bitmap buffer? Because vertical interpolation between pixels in adjacent lines requires a look at the pixels in the previous line.
As soon as the display generator finishes displaying a line of the frame, the VDL processor automatically increments the contents of the current bitmap-buffer register by a fixed amount (modulo addition). The modulo value, which is typically 320 for a standard 320-by-240 video display, causes the new current bitmap-buffer pointer to skip over 320 pixels-the contents of a single line. When the next line is displayed, it receives a fresh (and consecutive) row of pixels from the bitmap buffer.
Just before the current bitmap-buffer register is incremented, the previous bitmap buffer usually receives the value from the current bitmap-buffer register, which is typically 320 pixels greater than its current value. By rotating the current bitmap-buffer pointer to the previous bitmap-buffer pointer-and then incrementing the current bitmap-buffer pointer-the VDL processor marches its way steadily through a bitmap buffer, displaying its contents line by line, and correctly interpolating between vertically adjacent pixels.
As you'll read in the sections that immediately follow this one, the bitmap-buffer registers' contents and operation can be modified in many ways by a VDL entry. What's important to know about the bitmap-buffer registers is that they're always ticked forward at the end of each line before the VDL processor reads a VDL entry for the next line. The order is
A VDL can have as many VDL entries as there are display lines, but should not have more entries than display lines. If there are fewer VDL entries than there are display lines, some of those entries must persist for more than one display line. The entries themselves can define the length (in lines) of their persistence. If the persistence of the last VDL entry isn't set to last to the end of the display, the VDL processor will increase its persistence to reach to the end of the display.
The command words, which are optional for a VDL entry, set CLUT colors and control display generator operation. They need not occur in any particular order, but you should note that if two command words contain contradictory commands (two different colors for the same CLUT register, for example) the later word wins out.
The types of command words are
Table 1: Bits of the CLUT-DMA. ------------------------------------------------------ Bits |Operation Controlled ------------------------------------------------------ 3126 |Not available to a user task. Set to 0. ------------------------------------------------------ 2523 |Sets the modulo value (in words) added to the |VDL processor's bitmap-buffer registers. |000=320; 001=384; 010=512; 011=640; 100=1024; |101, 110, and 111 are unused. ------------------------------------------------------ 22 |Not available to a user task, set to 0. ------------------------------------------------------ 21 |Enables video DMA. 1=enable, which shows the |bitmap-buffer image on the display; |0=disable, which shows only vertical-blank |color on the display. ------------------------------------------------------ 20 |Not available to a user task. Set to 0. ------------------------------------------------------ 19 |Sets vertical mode. 1=480 lines per frame; |0=240 lines per frame. ------------------------------------------------------ 18 |Indicates the type of the address stored in |the next VDL-entry-address word. 1=absolute; |0=relative. ------------------------------------------------------ 17 |Sets how the previous bitmap-buffer address |register is ticked at line's end. 1=add |modulo amount (set in bits 25-23); 0=accept |current bitmap-buffer address-register value. ------------------------------------------------------ 16 |Sets current bitmap-buffer address register |override. 1=load address from current |bitmap-buffer address word; 0=use address |generated by register tick (modulo addition |to last register contents). ------------------------------------------------------ 15 |Sets previous bitmap-buffer address-register |override. 1=load address from previous |bitmap-buffer address word; 0=use address |generated by register tick (rotated current |bitmap-buffer value or modulo addition to |last register contentsset by bit 17). ------------------------------------------------------ 149 |Gives the number of control words in this VDL |entry (total number of VDL entry words minus |the four used for the header). Should be from |1 to 34. ------------------------------------------------------ 8-0 |Gives the number of display lines this VDL |entry persists. This is the number of lines |the VDL processor waits until reading the |next entry in the VDL. The current line |counts as one. The minimum value is 1 except |for the last VDL entry, which should be 0. (0 |specifies persistence until the bottom of the |screen.) ------------------------------------------------------
Note that any bits listed as "not available" to a user task must be set to 0 or the system will reject the VDL.
What follows is an explanation of the parameters set by the CLUT-DMA control word:
Table 2: Bits of a color-value word. ---------------------------------------------------------- Bits |Significance ---------------------------------------------------------- 31 |Set to 0 to specify that this is a color-value |word. ---------------------------------------------------------- 3029 |Determines what parts of a register are written |to. 00=write to all three registers (red, green, |and blue); 01=write to blue only; 10=write to |green only; 11=write to red only. ---------------------------------------------------------- 2824 |Contains the number (031) of the color register to |write to. ---------------------------------------------------------- 2316 |Contains 8 bits of red color value with bit 23 as |the most-significant bit. ---------------------------------------------------------- 158 |Contains 8 bits of green color value with bit 15 |as the most-significant bit. ---------------------------------------------------------- 70 |Contains 8 bits of blue color value with bit 7 as |the most-significant bit. ----------------------------------------------------------
If the color-value word is set up to write to only the red, green, or blue part of a register, only the red, green, or blue value contained in the word is used.
Table 3: Bits of a background-value word. -------------------------------------------------------- Bits |Significance -------------------------------------------------------- 3124 |Set to 11100000 to specify that this is a |background-value word. -------------------------------------------------------- 2316 |Contains eight bits of red color value with bit |23 as the most-significant bit. -------------------------------------------------------- 158 |Contains eight bits of green color value with |bit 15 as the most-significant bit. -------------------------------------------------------- 70 |Contains eight bits of blue color value with bit |7 as the most-significant bit. --------------------------------------------------------
The background color register contains a full 24-bit RGB value, so all of bits 23-0 are written to the register when the background-value word is executed by the VDL processor.
Table 4: Bits of a display-control word. -------------------------------------------------------- Bits |Significance -------------------------------------------------------- 3126 |Set to 110000 to specify that this is a |display-control word. -------------------------------------------------------- 25 |Makes the fixed CLUT set available. |1=bitmap-buffer pixels with bit 15 set to 1 pass |through the fixed CLUT set, those with bit 15 |set to 0 pass through the custom CLUT set; 0=all |bitmap-buffer pixels pass through the custom |CLUT set (the fixed CLUT set is not available). -------------------------------------------------------- 24 |Not available to a user task. Set to 0. -------------------------------------------------------- 23 |Forces pixel transparency. 1=all pixels are |transparent regardless of color value; |0=transparency limited to background pixels (if |enabled by bit 22). This bit is only meaningful |for SlipStream. -------------------------------------------------------- 22 |Sets transparency for background pixels. 1=all |pixels with 000 RGB value (background pixels) |are transparent; 0=all background pixels are not |transparent, and are filled with the background |register color. This bit is only meaningful for |SlipStream. -------------------------------------------------------- 21 |For pixels going through the fixed CLUT setswaps |the meaning of V and H cornerweight bits. 1=H |value is MSB, V value is LSB; 0=H value is LSB, |V value is MSB. -------------------------------------------------------- 2019 |For pixels going through the fixed CLUT setsets |each pixel's V cornerweight value. 00=set V to |0; 01=set V to 1; 10=use V value stored in |pixel; 11=don't change this setting from the one |used by the last VDL entry. -------------------------------------------------------- 1817 |For pixels going through the fixed CLUT setsets |each pixel's H cornerweight value. 00=set H to |0; 01=set H to 1; 10=use H value stored in |pixel; 11=don't change this setting from the one |used by the last VDL entry. -------------------------------------------------------- 1615 |For pixels going through the fixed CLUT setsets |the value of each pixel's least-significant blue |bit. 00=set to 1; 01=use bit 5 of the |bitmap-buffer pixel value (the least-significant |green bit); 10=use bit 0 of the bitmap-buffer |pixel value; 11=don't change this setting from |the one used by the last VDL entry. -------------------------------------------------------- 14 |For pixels going through the fixed CLUT |setenables vertical interpolation. 1=vertical |interpolation on; 0=vertical interpolation off. -------------------------------------------------------- 13 |For pixels going through the fixed CLUT |setenables horizontal interpolation. |1=horizontal interpolation on; 0=horizontal |interpolation off. -------------------------------------------------------- 12 |For pixels going through the fixed CLUT |setenables random-number generation to fill in |the three least-significant bits for the 8-bit |red, green, and blue values coming out of the |CLUT set. 1=random number generation on; |0=random number generation off, LSBs filled by |technique determined in bit 11. -------------------------------------------------------- 11 |For pixels going through the fixed CLUT |setdetermines how three least-significant bits |for 8-bit red, green, and blue values are filled |in. 1=copied from the three most-significant |bits of the color value; 0=set to 000. -------------------------------------------------------- 10 |For pixels going through the custom CLUT |setswaps the meaning of V and H cornerweight |bits. 1=H value is MSB, V value is LSB; 0=H |value is LSB, V value is MSB. -------------------------------------------------------- 98 |For pixels going through the custom CLUT setsets |each pixel's V cornerweight value. 00=set V to |0; 01=set V to 1; 10=use V value stored in |pixel; 11=don't change this setting from the one |used by the last VDL entry. -------------------------------------------------------- 76 |For pixels going through the custom CLUT setsets |each pixel's H cornerweight value. 00=set H to |0; 01=set H to 1; 10=use H value stored in |pixel; 11=don't change this setting from the one |used by the last VDL entry. -------------------------------------------------------- 54 |For pixels going through the custom CLUT setsets |the value of each pixel's least-significant blue |bit. 00=set to 1; 01=use bit 5 of the |bitmap-buffer pixel value (the least-significant |green bit); 10=use bit 0 of the bitmap-buffer |pixel value; 11=don't change this setting from |the one used by the last VDL entry. -------------------------------------------------------- 3 |For pixels going through the custom CLUT |setenables vertical interpolation. 1=vertical |interpolation on; 0=vertical interpolation off. -------------------------------------------------------- 2 |For pixels going through the custom CLUT |setenables horizontal interpolation. |1=horizontal interpolation on; 0=horizontal |interpolation off. -------------------------------------------------------- 1 |Not available to a user task. Set to zero. --------------------------------------------------------
Note that any bits listed as not available to a user task must be set to 0 or the system will reject the VDL.
What follows is an explanation of the display generator parameters set by the display-control word:
SubmitVDL()
function described later recommends that VDL entries have a word length that's a multiple of four. The NULLOP word is the perfect way to fill in, it does absolutely nothing. Table 5 shows the bits that don't do the work.
Table 5: Bits of the NULLOP word. -------------------------------------------------------- Bits |Significance -------------------------------------------------------- 3124 |Set to 11100001 to specify that this is a NULLOP |word. -------------------------------------------------------- 230 |Have no significance whatsoever. Set to zero. --------------------------------------------------------
You set all of these bitmap-buffer properties in the CLU- DMA control word, the first word of the VDL entry header. You provide supporting values, if necessary, in the current bitmap-buffer address and previous bitmap-buffer address words.
The combination of properties you set determines how the display generator reads VRAM for an image. You must also set up the data in the specified bitmap buffer (or bitmap buffers) to match the bitmap-buffer properties or you'll get garbage on the screen. For example, if you store an image in VRAM that is 320 pixels wide and then set row width in the CLUT-DMA control word to 384 pixels, you'll see a curiously skewed image on the screen.
Once you've tied the band on the screen to a bitmap buffer in VRAM, you must consider how the display generator handles the pixels in the bitmap buffer. Should it make them all transparent to show underlying images, make just background images transparent, or offer no transparency at all? Should it allow pixels to use the fixed CLUT set so they have a guaranteed color for each pixel, or should it turn the fixed CLUT set off? Should the pixels be interpolated for smooth integration one to the next, or should interpolation be turned off for crispy pixels? Should only the first line escape interpolation to establish a crisp border with the preceding band? How does each pixel determine its cornerweight values? How are missing low-order color bits filled in?
You set these display generator operation properties in a single display-control word. If you use more than one, only the last display-control word in the VDL entry is used for the band. If you don't want to change the display generator operation used in the last band, you can omit a display-control word completely.
You may also want to consider the custom color palette that interprets the bitmap-buffer pixel values. If you want to change the colors in the custom CLUT registers, create an appropriate color-value word for each register change. If you want to change the background color, create an appropriate background-value word. If you create more than one color-value word for a single register, or more than one background-value word, only the last duplicate word in the VDL entry is used-so don't waste command words! You can't have more than 34 command words in a VDL entry. That's just enough to change all 33 CLUT registers and set display generator properties for the band.
When your task's custom VDL is submitted to the 3DO system, the VDL is checked for integrity and then written to system RAM. Because of alignment constraints in the hardware, VDL entries may not fit correctly in system RAM if their length in words is not a multiple of four.
Your task should pad each VDL entry with NULLOP words at the end of the VDL entry to create a length that's a multiple of four. The CLUT-DMA control-word setting that sets the number of command words in the VDL entry need not include NULLOP pad words. For example, consider a VDL entry with a full complement of 34 command words-it's 38 words long. The task writing it to memory adds two NULLOP words at the end of the entry to bring the entry to 40 words in length. The entry still claims it has 34 command words, so it's a legal entry and not overlong. The NULLOP words are simply not read by the VDL processor when the VDL is used.
Item SubmitVDL;( VDLEntry *VDLDataPtr, int32 length, int32 type
)
The first argument, VDLDataPtr
, is a pointer to a custom VDL data structure. The second argument, length
, is the length of the VDL in words. And the third argument, type
, gives the type of VDL submitted.
When executed, SubmitVDL()
reads the submitted VDL, proofs it for inconsistent or system-crashing settings, and, if it finds none, copies the VDL, into system RAM, as a screen VDL. The call can alter some VDL settings before the VDL becomes an item. For example, if the total persistence for the VDL entries doesn't cover the entire screen, the persistence of the last VDL entry is set to continue to the bottom of the screen. Control-word bits that aren't available to user tasks are also set when the VDL becomes an item.
SubmitVDL()
returns an item number for the screen VDL it creates. You can use that item number with a CreateScreenGroup()
tag argument to associate the VDL with a newly created screen in a screen group. You can also use the VDL item number to specify the VDL when you modify it or its connections. If unsuccessful, this call returns a negative value (an error code). A task should check for GRAFERR_PROOF_ERR
in particular, which indicates that the submitted VDL had illegal control codes or bad data.
The first argument,
Err ModifyVDL( Item vdlItem, TagArg* vdlTags )
vdlItem
, specifies the screen VDL to modify. The second argument, vdlTags
, points to a tag argument array that describes the changes to be made to the VDL.
The tag arguments include:
CREATEVDL_TAG_SLIPSTREAM
sets transparency for background pixels (bit 22 of the display-control word). 1 turns background transparency on; 0 turns it off. When transparency is on, SlipStream images can be displayed in transparent pixels.
CREATEVDL_TAG_HAVG
turns horizontal interpolation on or off (bit 13 and bit 2 of the display-control word). 1 turns horizontal interpolation on; 0 turns it off.
CREATEVDL_TAG_VAVG
turns vertical interpolation on or off (bit 14 and bit 3 of the display-control word). 1 turns vertical interpolation on; 0 turns it off.
ModifyVDL()
executes, it accepts the tag arguments and writes their arguments to the proper display-control bits of each VDL entry in the VDL. Its effects are VDL-wide; tag argument can't specify a single VDL entry within a VDL (unless, of course, the VDL has only one entry). If successful, the call returns a 0. If unsuccessful, it returns a negative value (an error code).
A task can't modify a screen VDL by modifying the VDL data structure it used to create that VDL. Once created the VDL exists in system RAM and must be modified using ModifyVDL()
.
itemSetVDL( Item screenItem, Item vdlItem )
screenItem
, specifies the item number of the screen to which you want to assign a new screen VDL. The second argument, vdlItem
, specifies the screen VDL that you want to assign. When executed, the call assigns the VDL to the screen. When the screen is displayed, its display operation is controlled by its associated VDL. If successful, the call returns a 0. If unsuccessful, it returns the item number of the VDL that was replaced.
DeleteItem()
and supply it with the item number of the screen VDL you want to delete. If you delete a VDL that is in use, the screen depending on that VDL goes black.