Displaying Images and Cels


To display a cel, the jsshowcel program does the following:

The jsshowcel program does the minimum to display graphics that reside on the Macintosh or a CD-ROM on the TV screen by means of the 3DO system.

The sample code below comes from jsshowcel.c. The main() function calls three functions to create the display:

This section first lists the part of the main() function in the example below, then discusses the function calls in some detail.

Example 1: Displaying an image and a cel

int main(int argc, char** argv)
{
    printf("jsshowcel\n");
    
    /*    Initialize global resources */
    if ( Initialize() < 0 )
        goto DONE;
    
    /*    Draw the background image to the current screen. */
    DrawImage(gScreenContext->sc_Screens[gScreenContext->sc_curScreen], 
gBackgroundImage, gScreenContext);

    /*
        Draw (project) the cel to the current bitmap.  If this cel
        were linked to other cels, all of them would be drawn.
    */
    DrawCels(gScreenContext->sc_BitmapItems[gScreenContext->sc_curScreen], gUFO_CCB);

    /*
        DisplayScreen automatically waits for the next vertical blank,
        then tells the hardware to use the specified screen as the
        display buffer. The hardware will continue to show this buffer
        on the TV each frame, until another call to DisplayScreen, specifying
        a different block of memory, is made.
    */
    DisplayScreen(gScreenContext->sc_Screens[gScreenContext->sc_curScreen], 0);

    /*    Give the user a little time to look at the screen. */
    {
        int nCountdown;
        for (nCountdown = (10 * 30); nCountdown; nCountdown--)
            WaitVBL( gVBLIOReq, 1 );
    }

DONE:
    if ( gScreenContext )
        FadeToBlack(gScreenContext, 60);

    /*    Always clean up after ourselves */
    Cleanup();
    
    printf("end of jsshowcel ( wasn't that special? )\n");

    return 0;

}

The Lib3DO function DrawImage() has three arguments:

The example above uses double buffering. During initialization, two screens were allocated for the screen context. One of the screens can now be used for display, the other can be written to. Since this example uses only one cel, this is not actually required, however, in any program that uses several cels, it's crucial to avoid drawing to the on-screen buffer.

The image is block-copied into the frame buffer using direct memory access (DMA), which is very fast and happens in the background while the CPU continues execution. Drawing an image, even if only a blank one, is by far the most common method of clearing the buffer between frames, since DMA copy operations are several times faster than cel engine rendering. While images can be displayed very quickly, they lack flexibility and are therefore only useful for large, static backgrounds.

The graphics folio function DrawCels() sets up the cel engine according to parameters in the bitmapItem, and then submits the list of cels specified by the ccb argument. When the call returns, the cels have been rendered. The function has two arguments:

Like the screen item, the bitmap item is a field in the ScreenContext structure allocated by OpenGraphics(). All information about the cel, including XY location, rotation, and scaling, is stored in the CCB. To change any aspect of a cel, you only have to alter one of the fields of the CCB and then rerender the cel list to the screen. Those CCB fields are discussed in a later chapter; for now, the default values (including the default XY position of 0,0) are sufficient.

The graphics folio function DisplayScreen() displays the bitmap(s) of the specified screen (or screens). The hardware draws the active display to the TV screen 30 times a second for NTSC screens. The software is only responsible for telling the hardware what memory to use. There is no way to disable the hardware or shut off the display, so as long as the hardware is on, some piece of memory is being displayed on the TV.

Only one call to DisplayScreen() is necessary until you want to change to a different buffer. The jsshowcel program uses only one buffer, even though it allocates two. The animation example discussed in the following chapter uses two buffers, displaying one while drawing into the other.