# Displaying Images and Cels

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

- initializes the hardware and the operating system
- loads a background image
- loads a single cel
- displays the cel superimposed on the background
- performs cleanup and exits

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:

- `DrawImage()` renders the background image into the display buffer
- `DrawCels()` renders the foreground cel into the display buffer
- `DisplayScreen()` shows the display buffer on the TV screen

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:

- iScreen-Item for the screen into which to project the image.
- pbImage-Pointer to a page-aligned buffer in VRAM containing a full-screen 16-bit image.
- sc-Pointer to a screen context.

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:

- bitmapItem-Item number of a bitmap.
- ccb-Pointer to the first of one or more CCB structures.

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.