/******************************************************************************
 * palette.c - Chapter 3 sample code                                          *
 *                                                                            *
 * To be used with Rage 128 sample code.                                      *
 * Functions to set, get, save, restore, and initilize palette.               *
 *                                                                            *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.             *
 ******************************************************************************/

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

/******************************************************************************
 * R128_SetPalette                                                            *
 *  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 R128_SetPaletteEntry (WORD index, palette entry)
{
    DWORD temp;

    // Set PALETTE_INDEX write index.

    iow8 (PALETTE_INDEX, (BYTE)index);

    temp = (entry.red << 16) | (entry.green << 8) | entry.blue;
    regw (PALETTE_DATA, temp);

    return;

} // R128_SetPaletteEntry


/******************************************************************************
 * R128_GetPaletteEntry                                                       *
 *  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 R128_GetPaletteEntry (WORD index)
{
    palette entry;
    DWORD temp, value;

    // Set PALETTE_INDEX read index.
    iow8 ((int)PALETTE_INDEX + 2, (BYTE)index);

    temp = regr (PALETTE_DATA);
    value = temp & 0x00FF0000; // isolate red component
    entry.red = value >> 16;

    value = temp & 0x0000FF00; // isolate green component
    entry.green = value >> 8;
    value = temp & 0x000000FF; // isolate blue component
    entry.blue = value;

    return (entry);
} // R128_GetPaletteEntry


/******************************************************************************
 * R128_SavePalette                                                           *
 *  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 R128_SavePalette (palette *palettebuffer)
{
    WORD index;

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

    return;

} // R128_SavePalette

/******************************************************************************
 * R128_RestorePalette                                                        *
 *  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 R128_RestorePalette (palette *palettebuffer)
{
    WORD index;

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

    return;

} // R128_RestorePalette


/******************************************************************************
 * R128_InitPalette                                                           *
 *  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 R128_InitPalette (void)
{
    int 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
    };

    for (index = 0; index < 256; index++)
    {
        R128_SetPaletteEntry (index, entry[index%16]);
    } // for

    return;

} // R128_InitPalette

/******************************************************************************
 * R128_InitGamma                                                             *
 *  Function: This function initializes the gamma ramp for hi colour modes    *
 *    Inputs: NONE                                                            *
 *   Outputs: NONE                                                            *
 ******************************************************************************/
void R128_InitGamma (void)
{
    int i;
    palette entry;

    // Set entries
    entry.red = 0;
    entry.blue = 0;
    entry.green = 0;

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

    return;

} // R128_InitGamma
