/*
PMP Mod
Copyright (C) 2006 jonny

Homepage: http://jonny.leffe.dnsalias.com
E-mail:   jonny@leffe.dnsalias.com

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
.pmp header reading routines
*/


#include "pmp_file.h"


void pmp_file_safe_constructor(struct pmp_file_struct *p)
	{
	p->f            = 0;
	p->packet_index = 0;
	}


void pmp_file_close(struct pmp_file_struct *p)
	{
	if (p->f            != 0) fclose(p->f);
	if (p->packet_index != 0) free_64(p->packet_index);


	pmp_file_safe_constructor(p);
	}


char *pmp_file_open(struct pmp_file_struct *p, char *s)
	{
	pmp_file_safe_constructor(p);




	p->f = fopen(s, "rb");
	if (p->f == 0)
		{
		pmp_file_close(p);
		return("pmp_file_open: can't open file");
		}


	if (fread(&p->header, 1, sizeof(struct pmp_header_struct), p->f) != sizeof(struct pmp_header_struct))
		{
		pmp_file_close(p);
		return("pmp_file_open: can't read header");
		}




	if (p->header.signature.pmpm    != 0x6d706d70)     { pmp_file_close(p); return("pmp_file_open: not a valid pmp file"); }
	if (p->header.signature.version != 1)              { pmp_file_close(p); return("pmp_file_open: invalid file version"); }




	if (p->header.video.format           != 0)         { pmp_file_close(p); return("pmp_file_open: invalid video format"); }
	if (p->header.video.number_of_frames == 0)         { pmp_file_close(p); return("pmp_file_open: video.number_of_frames == 0"); }
	if (p->header.video.width            == 0)         { pmp_file_close(p); return("pmp_file_open: video.width == 0"); }
	if (p->header.video.height           == 0)         { pmp_file_close(p); return("pmp_file_open: video.height == 0"); }
	if (p->header.video.scale            == 0)         { pmp_file_close(p); return("pmp_file_open: video.scale == 0"); }
	if (p->header.video.rate             == 0)         { pmp_file_close(p); return("pmp_file_open: video.rate == 0"); }


	if (p->header.video.rate  < p->header.video.scale) { pmp_file_close(p); return("pmp_file_open: video.rate < video.scale"); }
	if (p->header.video.scale > 0xffffff)              { pmp_file_close(p); return("pmp_file_open: video.scale > 0xffffff"); }


	if ((p->header.video.width  % 8) != 0)             { pmp_file_close(p); return("pmp_file_open: (video.width % 8) != 0"); }
	if ((p->header.video.height % 8) != 0)             { pmp_file_close(p); return("pmp_file_open: (video.height % 8) != 0"); }
	if (p->header.video.width        >  720)           { pmp_file_close(p); return("pmp_file_open: video.width > 720"); }
	if (p->header.video.height       >  512)           { pmp_file_close(p); return("pmp_file_open: video.height > 512"); }




	if (p->header.audio.format                   != 0) { pmp_file_close(p); return("pmp_file_open: invalid audio format"); }
	if (p->header.audio.number_of_streams        == 0) { pmp_file_close(p); return("pmp_file_open: audio.number_of_streams == 0"); }
	if (p->header.audio.maximum_number_of_frames == 0) { pmp_file_close(p); return("pmp_file_open: audio.maximum_number_of_frames == 0"); }


	if (p->header.audio.scale  != 1152)                { pmp_file_close(p); return("pmp_file_open: audio.scale != 1152"); }
	if (p->header.audio.rate   != 44100)               { pmp_file_close(p); return("pmp_file_open: audio.rate != 44100"); }
	if (p->header.audio.stereo != 1)                   { pmp_file_close(p); return("pmp_file_open: audio.stereo != 1"); }




	p->packet_index = malloc_64(sizeof(unsigned int) * p->header.video.number_of_frames);
	if (p->packet_index == 0)
		{
		pmp_file_close(p);
		return("pmp_file_open: malloc_64 failed on packet_index");
		}


	if (fread(p->packet_index, 1, sizeof(unsigned int) * p->header.video.number_of_frames, p->f) != sizeof(unsigned int) * p->header.video.number_of_frames)
		{
		pmp_file_close(p);
		return("pmp_file_open: can't read packet index");
		}




	p->packet_start        = sizeof(struct pmp_header_struct) + sizeof(unsigned int) * p->header.video.number_of_frames;
	p->maximum_packet_size = p->packet_index[0] >> 1;

	unsigned int i           = 0;
	unsigned int packet_size = 0;

	for (; i < p->header.video.number_of_frames; i++)
		{
		if ((p->packet_index[i] >> 1) > p->maximum_packet_size)
			{
			p->maximum_packet_size = p->packet_index[i] >> 1;
			}

		packet_size += p->packet_index[i] >> 1;
		}




	if (fseek(p->f, 0, SEEK_END) != 0)
		{
		pmp_file_close(p);
		return("pmp_file_open: fseek failed on SEEK_END");
		}


	int tot_size = ftell(p->f);
	if (tot_size == -1)
		{
		pmp_file_close(p);
		return("pmp_file_open: ftell failed");
		}


	if (tot_size != p->packet_start + packet_size)
		{
		pmp_file_close(p);
		return("pmp_file_open: invalid tot_size");
		}




	fclose(p->f);
	p->f = 0;


	return(0);
	}
