/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
 * viewimg.c - Chapter 8 sample code                                     *
 *                                                                       *
 * To be used with mach64VT/3D RAGE sample code.                         *
 * This module contains routines to view .IMG files.                     *
 *                                                                       *
 * Copyright (c) 1994-1998 ATI Technologies Inc.  All rights reserved.   *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include <stdio.h>
#include <stdlib.h>

#include "atim64vt.h"
#include "definevt.h"
#include "main.h"
#include "vtga.h"


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
 * get_img_header                                                      *
 *  Function - Retrives information from the file header such as:      *
 *             bpp, height, width, format_id.                          *
 *  Inputs - char *filename                                            *
 *  Outputs - integer value returning a LOAD_SUCCESSFUL if completed   *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

img_handle *get_img_header(char *filename)
{
   FILE *handle;
   img_handle *himage;

   // open image file
   handle = fopen(filename, "rb");

   if (handle == NULL)
   {
      return (NULL);
   }

   // allocate memory for new pointer
   himage = calloc(1,sizeof(img_handle));

   // store filename into himage
   himage->filespec = filename;

   // read header from file
   fread(himage->image, sizeof(img_header), 1, handle);

   // check for IMG id code
   if (strcmpi(himage->image->img_code, "_IMG") != 0)
   {
      free(himage);
      fclose(handle);
      return (NULL);
   }

   // check format id
   switch(himage->image->format_id)
   {
      case FORMAT_TYPE_15BPP:
      case FORMAT_TYPE_16BPP:
      case FORMAT_TYPE_32BPP:
      case FORMAT_TYPE_YUV9:
      case FORMAT_TYPE_YUV12:
      case FORMAT_TYPE_VYUY:
      case FORMAT_TYPE_YVYU:
         break;

      default:
         fclose(handle);
         free(himage);
         return (NULL);
   }

   fclose(handle);
   return(himage);
}


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
 * load_img                                                            *
 *  Function - Draws the image to the screen.                          *
 *  Inputs - char *filename                                            *
 *           int x (where to place the file horizontally)              *
 *           int y (where to place the file vertically)                *
 *  Outputs - integer value returning a LOAD_SUCCESSFUL if completed   *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

int load_img(img_handle *himage, int x, int y)
{
   int byte_pitch, i, count;
   unsigned long temp;
   char tempu, tempv;
   char *dstaddr;
   char *VT_loadbuffer;
   FILE *handle;

   // ensure engine is idle before writing to video memory
   wait_for_idle();

   // open image file
   handle = fopen(himage->filespec, "rb");
   if (fseek(handle, 32, SEEK_SET))
   {
      exit(1);
   }

   switch(MODE_INFO.bpp)
   {
      case 4:
         byte_pitch = MODE_INFO.pitch / 2;
         break;
      case 8:
         byte_pitch = MODE_INFO.pitch;
         break;
      case 15:
      case 16:
         byte_pitch = MODE_INFO.pitch * 2;
         break;
      case 24:
         byte_pitch = MODE_INFO.pitch * 3;
         break;
      case 32:
         byte_pitch = MODE_INFO.pitch * 4;
         break;
      default:
         free(himage);
         fclose(handle);
         return (LOAD_FAILED);
   }

   dstaddr = (char *) (MODE_INFO.virt_seg+(byte_pitch*y)+(x*MODE_INFO.bpp/8));

   // load data for other formats
   if (himage->image->format_id == FORMAT_TYPE_YUV9)
   {
       VT_loadbuffer = malloc(5120);
       wait_for_idle ();
       temp = regr(VIDEO_FORMAT);

       //change_overlay_pitch(8);
       wait_for_fifo(1);
       regw(VIDEO_FORMAT, SCALE_IN_YUV9 | HOST_YUV_APERTURE_LOWER | HOST_MEM_MODE_Y);
       for (i = 0; i < himage->image->height; i++)
       {
          fread(dstaddr, himage->image->bytes_per_pixel,
                         himage->image->width, handle);
          dstaddr += byte_pitch/2;
       }
       dstaddr = (char *)
                 (MODE_INFO.virt_seg+(byte_pitch*y)+(x*MODE_INFO.bpp/8));
       wait_for_fifo(1);
       regw(VIDEO_FORMAT, SCALE_IN_YUV9 | HOST_YUV_APERTURE_LOWER | HOST_MEM_MODE_U);
       fseek(handle, 0L | (himage->image->u_offset), SEEK_SET);
       for (i = 0; i < (himage->image->height / 4); i++)
       {
          fread(VT_loadbuffer,
                himage->image->bytes_per_pixel,
                himage->image->width / 4,
                handle);
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
       }
       dstaddr = (char *)
                 (MODE_INFO.virt_seg+(byte_pitch*y)+(x*MODE_INFO.bpp/8));
       wait_for_fifo(1);
       regw(VIDEO_FORMAT, SCALE_IN_YUV9 | HOST_YUV_APERTURE_LOWER | HOST_MEM_MODE_V);
       fseek(handle, 0L | himage->image->v_offset, SEEK_SET);
       for (i = 0; i < (himage->image->height / 4); i++)
       {
          fread(VT_loadbuffer,
                himage->image->bytes_per_pixel,
                himage->image->width / 4,
                handle);
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width / 4));
          dstaddr += byte_pitch/8;
       }
       free(VT_loadbuffer);
       regw(VIDEO_FORMAT, temp);
   }

   dstaddr = (char *) (MODE_INFO.virt_seg+(byte_pitch*y)+(x*MODE_INFO.bpp/8));

   // load data for other formats
   if (himage->image->format_id == FORMAT_TYPE_YUV12)
   {
       VT_loadbuffer = malloc(5120);
       wait_for_idle ();
       temp = regr(VIDEO_FORMAT);

       //change_overlay_pitch(8);
       wait_for_fifo(1);
       regw(VIDEO_FORMAT, SCALE_IN_YUV12 | HOST_YUV_APERTURE_LOWER | HOST_MEM_MODE_Y);
       for (i = 0; i < himage->image->height; i++)
       {
          fread(dstaddr, himage->image->bytes_per_pixel,
                         himage->image->width, handle);
          dstaddr += byte_pitch/2;
       }
       dstaddr = (char *)
                 (MODE_INFO.virt_seg+(byte_pitch*y)+(x*MODE_INFO.bpp/8));
       wait_for_fifo(1);
       regw(VIDEO_FORMAT, SCALE_IN_YUV12 | HOST_YUV_APERTURE_LOWER | HOST_MEM_MODE_U);
       fseek(handle, 0L | (himage->image->u_offset), SEEK_SET);
       for (i = 0; i < (himage->image->height)/2; i++)
       {
          fread(VT_loadbuffer,
                himage->image->bytes_per_pixel,
                (himage->image->width)/2,
                handle);
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*((himage->image->width)/2));
          dstaddr += byte_pitch/4;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*((himage->image->width)/2));
          dstaddr += byte_pitch/4;
       }
       dstaddr = (char *)
                 (MODE_INFO.virt_seg+(byte_pitch*y)+(x*MODE_INFO.bpp/8));
       wait_for_fifo(1);
       regw(VIDEO_FORMAT, SCALE_IN_YUV12 | HOST_YUV_APERTURE_LOWER | HOST_MEM_MODE_V);
       fseek(handle, 0L | himage->image->v_offset, SEEK_SET);
       for (i = 0; i < (himage->image->height)/2; i++)
       {
          fread(VT_loadbuffer,
                himage->image->bytes_per_pixel,
                himage->image->width/2,
               handle);
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*(himage->image->width)/2);
          dstaddr += byte_pitch/4;
          memcpy(dstaddr, VT_loadbuffer,
                 (himage->image->bytes_per_pixel)*((himage->image->width)/2));
          dstaddr += byte_pitch/4;
       }
       free(VT_loadbuffer);
       regw(VIDEO_FORMAT, temp);
   }

   else
   {
       for (i = 0; i < himage->image->height; i++)
       {
          fread(dstaddr, himage->image->bytes_per_pixel,
                         himage->image->width, handle);

          dstaddr += byte_pitch;
       }

   }

   // free allocated memory to pointer "himage"
   free(himage);

   // close file
   fclose(handle);

   return (LOAD_SUCCESSFUL);
}











