/******************************************************************************
 * palette.c - Chapter 5 sample code                                          *
 *                                                                            *
 * To be used with Engine mach64 sample code.                                 *
 * Functions to set, get, save, restore, and initilize palette.               *
 *                                                                            *
 * Copyright (c) 1994-1998 ATI Technologies Inc.  All rights reserved.        *
 ******************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include "atim64.h"
#include "defines.h"
#include "main.h"

/******************************************************************************
 * set_palette                                                                *
 *  Function: sets a specific palette entry. Each component has a range       *
 *            of 0 to 255.  Note DAC_INDEX automatically increments after     *
 *            3 consecutive writes.                                           *
 *    Inputs: index - range from 0 to 255.                                    *
 *            entry - struct of 3 values (red, green, blue) each from 0       *
 *                    to 255.                                                 *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void set_palette (int index, palette entry)
{
    // Set DAC write index.
    iow8 (DAC_W_INDEX, index);

    // Set red component.
    iow8 (DAC_DATA, entry.red);

    // Set green component.
    iow8 (DAC_DATA, entry.green);

    // Set blue component.
    iow8 (DAC_DATA, entry.blue);

    return;

} // set_palette


/******************************************************************************
 * get_palette                                                                *
 *  Function: Given the index, retrieves the RGB value in struct palette.     *
 *    Inputs: index - range from 0 to 255.                                    *
 *   Outputs: entry - palette structure of red, green, and blue value         *
 *                    ranging from 0 to 255 each.                             *
 ******************************************************************************/

palette get_palette (int index)
{
    palette entry;

    // Set DAC read index.
    iow8 (DAC_R_INDEX, index);

    // Get red component.
    entry.red = ior8 (DAC_DATA);

    // Get green component.
    entry.green = ior8 (DAC_DATA);

    // Get blue component.
    entry.blue = ior8 (DAC_DATA);

    return (entry);

} // get_palette


/******************************************************************************
 * save_palette                                                               *
 *  Function: reads and saves 256 palette entries into a buffer.  The         *
 *            application should ensure that there is enough space for        *
 *            256 entries.  Note that this routine should only be called      *
 *            for 4 or 8 bpp modes.                                           *
 *    Inputs: *palettebuffer - buffer in which to save all entries            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void save_palette (palette *palettebuffer)
{
    int index;

    // Make sure DAC mask is enabled.
    iow8 (DAC_MASK, 0xFF);

    for (index = 0; index < 256; index++)
    {
        palettebuffer[index] = get_palette (index);
    } // for

    return;

} // save_palette


/******************************************************************************
 * restore_palette                                                            *
 *  Function: restores 256 palette entries from the given palette buffer      *
 *            previously filled by save_palette.  Note that this routine      *
 *            should only be called for 4 and 8 bpp modes.                    *
 *    Inputs: *palettebuffer - buffer containing palette entries to           *
 *                             restore.                                       *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void restore_palette (palette *palettebuffer)
{
    int index;

    // Make sure DAC mask is enabled.
    iow8 (DAC_MASK, 0xFF);

    for (index = 0; index < 256; index++)
    {
        set_palette (index, palettebuffer[index]);
    } // for

    return;

} // restore_palette


/******************************************************************************
 * init_palette                                                               *
 *  Function: This function initializes the palette table by setting the      *
 *            entries to a set of default values.  The first 16 entries       *
 *            are set to EGA/VGA colours.  these 16 colours are then          *
 *            replicated 16 times to fill all 256 palette entries.            *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void init_palette (void)
{
    int i, j, index;
    palette entry[16] =
    {
        {0, 0, 0},                      // Black
        {0, 0, 168},                    // Blue
        {0, 168, 0},                    // Green
        {0, 168, 168},                  // Cyan
        {168, 0, 0},                    // Red
        {168, 0, 168},                  // Magenta
        {168, 168, 0},                  // Brown
        {168, 168, 168},                // Light Gray
        {84, 84, 84},                   // Gray
        {0, 0, 255},                    // Light Blue
        {0, 255, 0},                    // Light Green
        {0, 255, 255},                  // Light Cyan
        {255, 0, 0},                    // Light Red
        {255, 0, 255},                  // Light Magenta
        {255, 255, 0},                  // Yellow
        {255, 255, 255}                 // White
    };

    // Set first 16 entries.
    for (index = 0; index < 16; index++)
    {
        set_palette (index, entry[index]);
    } // for

    // Set other entries by replicating the first 16 entries.
    index = 16;
    for (i = 1; i < 16; i++)
    {
        for (j = 0; j < 16; j++)
        {
            set_palette (index, entry[i]);
            index++;
        } // for
    } // for

    return;

} // init_palette


/******************************************************************************
 * init_palettized                                                            *
 *  Function: This function initializes the palette for hi colour modes       *
 *            (15, 16, 24, 32 bpp) so that they will behave as the direct     *
 *            colour map hi colour modes.  This function is specific to       *
 *            cards with ATI68860 RAMDACs and its variants where the mode     *
 *            was set with the palettized flag set.                           *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/

void init_palettized (void)
{
    int index;
    palette entry;


    // Make sure DAC mask is enabled.
    iow8 (DAC_MASK, 0xFF);

    for (index = 0; index < 256; index++)
    {
        entry.red = index;
        entry.green = index;
        entry.blue = index;
        set_palette (index, entry);
    } // for

    return;

} // init_palettized
