/*
 * MTV to Targa graphics file converter
 * EWZ 02-05-92 16:20 EST
 *
 * Note: This is not a general purpose conversion program. I didn't have
 *       the specification for either of these graphics formats. I just
 *	 looked at the code for Rayshade 4.0 and DKB 2.12. So it 
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct targa_header_tag {
   char fill1[2];		/* Filler all 0's */
   char signature;		/* Signature Byte 2 */
   char fill2[7];		/* Filler all 0's */
   char fill3[2];		/* Filler all 0's */
   char width_lo;		/* High and Low byte of width */
   char width_hi;
   char height_lo;		/* High and Low byte of height */
   char height_hi;
   char bit_per_pel;		/* 24 bits per pels */
   char bitmask;		/* 32 bitmask, pertinent bit: top-down raster */
} targa_header;

struct targa_pel_tag {
   char blue;
   char green;
   char red;
} targa_pel;

struct mtv_pel_tag {
   char red;
   char green;
   char blue;
} mtv_pel;

/* Function prototypes */
int ReadWriteHeaders(int *ImageWidth, int *ImageHeight);
int ReadWritePels(int ImageWidth, int ImageHeight);
int main(int argc, char **argv);

/* Global variables */
FILE *In_FileHandle;		/* Input filehandle - mtv file */
FILE *Out_FileHandle;		/* Output filehandle - targa file */
char In_Buffer[16000];
char Out_Buffer[16000];

int main(int argc, char **argv)
{
   char In_Filename[80];	/* Input file name */
   char Out_Filename[80];	/* Output file name */
   int ImageWidth;
   int ImageHeight;

   /* Get the filename if available */
   if (argc > 1) {
      sprintf(In_Filename, "%s.mtv", argv[1]);
      sprintf(Out_Filename, "%s.tga", argv[1]);
   } else {
      printf("Usage: mtv2tga filename (without extension)\n");
      return 0;
   }

   /* Open the files, if any error report to user and quit */
   if ((In_FileHandle = fopen(In_Filename, "rb")) == NULL) {
      printf("Error opening input file %s\n", In_Filename);
      return -1;
   }
   if ((Out_FileHandle = fopen(Out_Filename, "wb")) == NULL) {
      printf("Error opening output file %s\n", Out_Filename);
      return -2;
   }

   /* Setup buffers to get a little better performance out of the I/O */
   setvbuf(In_FileHandle, In_Buffer, _IOFBF, sizeof(In_Buffer));
   setvbuf(Out_FileHandle, Out_Buffer, _IOFBF, sizeof(Out_Buffer));

   if (ReadWriteHeaders(&ImageWidth, &ImageHeight) < 0)
      return -3;

   if (ReadWritePels(ImageWidth, ImageHeight) < 0)
      return -4;

   fclose(In_FileHandle);
   fclose(Out_FileHandle);
   return 0;
}

int ReadWriteHeaders(int *ImageWidth, int *ImageHeight)
{
   if (fscanf(In_FileHandle, "%d %d\n", ImageWidth, ImageHeight) != 2) {
      printf("Error reading mtv header\n");
      return -1;
   }
   printf("Image size %dx%d ", *ImageWidth, *ImageHeight);

   memset(&targa_header, 0, sizeof(targa_header));
   targa_header.width_lo = (char) (*ImageWidth % 256);
   targa_header.width_hi = (char) (*ImageWidth / 256);
   targa_header.height_lo = (char) (*ImageHeight % 256);
   targa_header.height_hi = (char) (*ImageHeight / 256);
   targa_header.bit_per_pel = (char) 24;
   targa_header.bitmask = (char) 32;
   targa_header.signature = (char) 2;

   /* Write the targa header out to the file */
   fwrite(&targa_header, sizeof(targa_header), 1, Out_FileHandle);
   return 0;
}

int ReadWritePels(int ImageWidth, int ImageHeight)
{
   int Width;
   int Height;

   for (Height = 0; Height < ImageHeight; Height++) {
      for (Width = 0; Width < ImageWidth; Width++) {
	 if (fread(&mtv_pel, sizeof(mtv_pel), 1, In_FileHandle) != 1) {
	    printf("\nTrouble reading MTV line\n");
	    return -1;
	 }

	 /* Convert pels; different ordering */
	 targa_pel.red = mtv_pel.red;
	 targa_pel.blue = mtv_pel.blue;
	 targa_pel.green = mtv_pel.green;
	 fwrite(&targa_pel, sizeof(targa_pel), 1, Out_FileHandle);
      }
      printf("%4d\b\b\b\b", Height);
   }
   printf("done\n");
   return 0;
}
