git » fp-git.git » master » tree

[master] / FP / src / res / dat.c

/*  Princed V3 - Prince of Persia Level Editor for PC Version
    Copyright (C) 2003 Princed Development Team

    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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    The authors of this program may be contacted at http://forum.princed.com.ar
*/

/*
dat.c: Princed Resources : DAT library
�����
 Copyright 2004 Princed Development Team
  Created: 15 Mar 2004

  Author: Enrique Calot <ecalot.cod@princed.com.ar>
  Version: 1.00 (2004-Mar-15)

 Note:
  DO NOT remove this copyright notice
*/

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

#include "disk.h"
#include "dat.h"

/***************************************************************\
|                     DAT reading primitives                    |
\***************************************************************/

#ifdef PR_DAT_INCLUDE_DATREAD

char               recordSize;
int                ofk=0;
int                pop1;
unsigned char*     indexPointer;
unsigned long  int indexOffset;
unsigned long  int offset;
unsigned short int indexSize;
unsigned char*     readDatFile;
int                readDatFileSize;

void mReadCloseDatFile() {
	free(readDatFile);
}

int mReadBeginDatFile(unsigned short int *numberOfItems,const char* vFiledat){
	/*
		Return Values:
			0 Wrong Format or file not found
			1 Ok
	*/

	unsigned char* readDatFilePoint;

	/* Open file */
	readDatFileSize=mLoadFileArray(vFiledat,&readDatFile);
	if (!readDatFileSize) 
	{
		fprintf(stderr, "mReadBeginDatFile: %s not found\n", vFiledat);
		return 0;
	}
	if (readDatFileSize<=6)
	{
		fprintf(stderr, "mReadBeginDatFile: File too short\n");
		free(readDatFile);
		return 0;
	}

	readDatFilePoint=readDatFile;

	/* verify dat format */
	indexOffset=array2long(readDatFilePoint);
	readDatFilePoint+=4;
	indexSize=array2short(readDatFilePoint);

	if ((indexOffset>readDatFileSize)&&((indexOffset+indexSize)!=readDatFileSize)) {
		fprintf(stderr, "mReadBeginDatFile: Invalid format\n");
		free(readDatFile);
		return 0; /* this is not a valid prince dat file */
	}

	indexPointer=readDatFile+indexOffset;
	*numberOfItems=array2short(indexPointer);
	indexPointer+=2;
	pop1=(((*numberOfItems)*8+2)==indexSize);

	if (!pop1) { /* verify if pop2 */
		ofk=(*numberOfItems)*6+2+((*numberOfItems)-2)*13;
		(*numberOfItems)=((indexSize-6-((*numberOfItems)*6)-(((*numberOfItems)-2)*13))/11);
	} else {
		ofk=0;
	}
	recordSize=pop1?8:11;

	return 1;
}

int mReadFileInDatFile(int k,unsigned char* *data,unsigned long  int *size) {
	int ok=1; 
	unsigned short int id;

	/* for each archived file the index is read */
	id=array2short(indexPointer+ofk+k*recordSize);
	
	offset=array2long(indexPointer+ofk+k*recordSize+2);
	*size= array2short(indexPointer+ofk+k*recordSize+6);
	if ((!pop1)&&(!(indexPointer[ofk+k*recordSize+8]==0x40)&&(!indexPointer[ofk+k*recordSize+9])&&(!indexPointer[ofk+k*recordSize+10]))) return -1;
	if (offset+indexSize>readDatFileSize) return -1;
	*data=readDatFile+offset;
	return ok?id:-1;
}

int mReadInitResource(tResource** res,const unsigned char* data,long size) {
	if ((*res)==NULL) {
		(*res)=(tResource*)malloc(sizeof(tResource));
		if ((*res)==NULL) return -1; /* no memory */
		(*res)->path=NULL;
		(*res)->palAux=NULL;
		(*res)->desc=NULL;
		(*res)->name=NULL;
		(*res)->palette=0;
		(*res)->number=0;
		(*res)->size=(unsigned short int)size;
		(*res)->offset=(unsigned short)offset; /* TODO delete this line */
		/* (*res)->type=verifyHeader(data,(unsigned short int)size); */
	} else { /* If resource type is invalid or 0, the type will be decided by PR */
		if (!((*res)->type)) (*res)->type=0; /*verifyHeader(data,(unsigned short int)size);*/
	}
	return 0;
}
#endif

/***************************************************************\
|                     DAT Writing primitives                    |
\***************************************************************/

#ifdef PR_DAT_INCLUDE_DATWRITE
FILE* writeDatFile;

int mWriteBeginDatFile(const char* vFile, int optionflag) {
	/*
		Opens safely a dat file for writing mode and
		reserves space for the headers

		Return Values:
			 1 Ok
			 0 File couldn't be open

	*/
	if (writeOpen(vFile,&writeDatFile,optionflag)) {
		fseek(writeDatFile,6,SEEK_SET);
		return 1;
	} else {
		return 0;
	}
}

void mWriteInitResource(tResource** res) {
	if ((*res)==NULL) {
		(*res)=(tResource*)malloc(sizeof(tResource));
		(*res)->path=NULL;
		(*res)->palAux=NULL;
		(*res)->desc=NULL;
		(*res)->name=NULL;
	}
	(*res)->offset=(unsigned long)ftell(writeDatFile);
}

void mWriteFileInDatFile(const unsigned char* data, int size) {
	/*
		Adds a data resource to a dat file keeping
		abstractly the checksum ver	ifications
	*/

	/* Declare variables */
	int            k        = size;
	unsigned char  checksum = 0;
	const unsigned char* dataAux  = data;

	/* calculates the checksum */
	while (k--) checksum+=*(dataAux++);
	checksum=~checksum;

	/* writes the checksum and the data content */
	fwritechar(&checksum,writeDatFile);
	fwrite(data,size,1,writeDatFile);
}

void mWriteFileInDatFileIgnoreChecksum(unsigned char* data, int size) {
	fwrite(data,size,1,writeDatFile);
}

void mWriteCloseDatFile(tResource* r[],int dontSave,int optionflag, const char* backupExtension) {
	/*
		Closes a dat file filling the index and other structures
	*/
	unsigned short int id=1;
	unsigned short int totalItems=0;
	unsigned short int size2=2;
	unsigned long  int size1=ftell(writeDatFile);

	/* Write index */
	fwriteshort(&totalItems,writeDatFile); /* Junk total items count to reserve 2 bytes */
	for (;id!=MAX_RES_COUNT;id++) {
		if (r[id]!=NULL) {
			/* the file is in the archive, so i'll add it to the index */
			totalItems++;
			fwriteshort(&id,writeDatFile);
			fwritelong(&(r[id]->offset),writeDatFile);
			fwriteshort(&(r[id]->size),writeDatFile);
		}
	}
	size2+=totalItems<<3;
	fseek(writeDatFile,size1,SEEK_SET);
	fwriteshort(&totalItems,writeDatFile); /* Definitive total items count */

	/* Write first 6 bytes header */
	fseek(writeDatFile,0,SEEK_SET);
	fwritelong(&size1,writeDatFile);
	fwriteshort(&size2,writeDatFile);

	/* Closes the file and flushes the buffer */
	writeClose(writeDatFile,dontSave,optionflag,backupExtension);
}
#endif

/***************************************************************\
|                       DAT R/W primitives                      |
\***************************************************************/

#ifdef PR_DAT_INCLUDE_DATREAD
#ifdef PR_DAT_INCLUDE_DATWRITE
int mRWBeginDatFile(const char* vFile, unsigned short int *numberOfItems, int optionflag) {
	if (!mReadBeginDatFile(numberOfItems,vFile)) return -2;
	if (!mWriteBeginDatFile(vFile,optionflag)) {
		mReadCloseDatFile();
		return -1;
	}
	return 0;
}
#endif
#endif