/******************************************************************************
 * viewtga.c - Chapter 4 sample code                                          *
 *                                                                            *
 * To be used with Rage 128 sample code.                                      *
 * This module contains primitive for bringing in TGA files to video          *
 * memory.                                                                    *
 *                                                                            *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.             *
 ******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#include "defines.h"
#include "main.h"
#include "viewtga.h"

/****************************************************************************
 * get_targa_header (char *filename, TARGA_HEADER *header)                  *
 *  Function: Loads targa file header information                           *
 *    Inputs: char *filename - name of file                                 *
 *            TARGA_HEADER *header - pointer to header structure            *
 *   Outputs: SUCCESS    - success                                          *
 *            OPEN_ERROR - can't open file                                  *
 ****************************************************************************/
BYTE get_targa_header (char *filename, TARGA_HEADER *header)
{
    FILE *TargaFile;

    // Open targa file.

    TargaFile = fopen (filename, "rb");
    if (TargaFile == NULL)
    {
        return (OPEN_ERROR);
    } // if

    // Check for supportability (type 1, 8 bpp, colour map).

    fread (header, sizeof (TARGA_HEADER), 1, TargaFile);

    fclose (TargaFile);

    return (SUCCESS);
} // get_targa_header

/****************************************************************************
 * set_targa_palette (char *filename)                                       *
 *  Function: Loads a targa image colour table and sets the palette         *
 *    Inputs: char *filename - name of file                                 *
 *   Outputs: SUCCESS - success                                             *
 *            OPEN_ERROR - can't open file                                  *
 *            IMAGE_TYPE_ERROR - targa file does not have colour table      *
 ****************************************************************************/
BYTE set_targa_palette (char *filename)
{
    FILE *TargaFile;
    TARGA_HEADER header;
    palette entry;
    BYTE i;

    // Open targa file.

    TargaFile = fopen (filename, "rb");
    if (TargaFile == NULL)
    {
        return (OPEN_ERROR);
    } // if

    // Check for supportability (type 1, 8 bpp, colour map).

    fread (&header, sizeof (TARGA_HEADER), 1, TargaFile);

    // Support check for type 1, 8 bpp, colour map.

    if ((header.cm_type != 1) ||
        (header.image_type != 1) ||
        (header.pixel_depth != 8) ||
        (header.image_coord == 1) ||
        (header.image_coord == 3))
    {
        // Return error if image type is not supported (no colour table).
    fclose (TargaFile);
        return (IMAGE_TYPE_ERROR);
    } // if

    // Read colour map and setup palette for 8 bpp.

    for (i = header.cm_origin; i < (header.cm_length - 1); i++)
    {
        entry.blue = fgetc (TargaFile);
        entry.green = fgetc (TargaFile);
        entry.red = fgetc (TargaFile);
        R128_SetPaletteEntry (i, entry);
    } // for

    fclose (TargaFile);

    // Return to caller.

    return (SUCCESS);
} // set_targa_palette

/****************************************************************************
 * load_targa (char *filename, WORD x, WORD y)                              *
 *  Function: Loads targa image into video memory                           *
 *    Inputs: char *filename - name of file                                 *
 *            WORD x - starting x-coordinate (top-left corner)              *
 *            WORD y - starting y-coordinate (top-left corner)              *
 *   Outputs: SUCCESS - success                                             *
 *            OPEN_ERROR - can't open file                                  *
 *            MEMORY_ERROR - not enough memory for input buffer             *
 *            IMAGE_TYPE_ERROR - targa file is not supported                *
 ****************************************************************************/
BYTE load_targa (char *filename, WORD x, WORD y)
{
    FILE *TargaFile;
    TARGA_HEADER header;
    WORD i, byte_pitch, bytepp, tgabytepp, error;
    char *dstaddr;

    // Open targa file.
    TargaFile = fopen (filename, "rb");
    if (TargaFile == NULL)
    {
        return (OPEN_ERROR);
    } // if

    // Check for support ability (type 1, 8 bpp, colour map).
    fread (&header, sizeof (TARGA_HEADER), 1, TargaFile);

    // Support check for type 1, 8 bpp, colour map.
    error = 0;
    if ((header.cm_type != 1) ||
        (header.image_type != 1) ||
        (header.pixel_depth != 8) ||
        (header.image_coord == 1) ||
        (header.image_coord == 3))
    {
        error++;
    } // if

    // Support check for type 2, 24 bpp, no colour map.
    if ((header.cm_type != 0) ||
        (header.image_type != 2) ||
        (header.pixel_depth == 8) ||
        (header.pixel_depth == 16) ||
        (header.image_coord == 1) ||
        (header.image_coord == 3))
    {
        error++;
    } // if

    // Return error if image type is not supported
    if (error > 1)
    {
        fclose (TargaFile);
        return (IMAGE_TYPE_ERROR);
    } // if

    // Skip over colour table if 8 bpp image type.
    if (header.pixel_depth == 8)
    {
        fseek (TargaFile, (unsigned long) (header.cm_length * 3), SEEK_CUR);
    } // if

    switch(R128_AdapterInfo.bpp)
    {
        case 8:
                byte_pitch = R128_AdapterInfo.pitch*8;
                break;
        case 15:
        case 16:
                byte_pitch = R128_AdapterInfo.pitch * 16;
                break;
        case 24:
                byte_pitch = (R128_AdapterInfo.pitch/3) * 24;
                break;
        case 32:
                byte_pitch = R128_AdapterInfo.pitch * 32;
                break;
    }

    bytepp = R128_AdapterInfo.bpp/8;
    if (R128_AdapterInfo.bpp%8)
    {
        bytepp++;
    }

    tgabytepp = header.pixel_depth/8;
    if (header.pixel_depth%8)
    {
        tgabytepp++;
    }

    dstaddr = (char *) (R128_AdapterInfo.virtual_MEM_BASE +
                        (byte_pitch * y) + (x * bytepp));

    for (i = 0; i < header.height; i++)
    {
        fread(dstaddr, tgabytepp, header.width, TargaFile);
        dstaddr += byte_pitch;
    }

    // Close files.
    fclose (TargaFile);

    // Return to caller.
    return (SUCCESS);

} // load_targa
