CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

IFF.CPP (13976B)


      1 //
      2 // Copyright 2020 Electronic Arts Inc.
      3 //
      4 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 // software: you can redistribute it and/or modify it under the terms of 
      6 // the GNU General Public License as published by the Free Software Foundation, 
      7 // either version 3 of the License, or (at your option) any later version.
      8 
      9 // TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 // in the hope that it will be useful, but with permitted additional restrictions 
     11 // under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 // distributed with this program. You should have received a copy of the 
     13 // GNU General Public License along with permitted additional restrictions 
     14 // with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
     15 
     16 /***************************************************************************
     17  **   C O N F I D E N T I A L --- W E S T W O O D   A S S O C I A T E S   **
     18  ***************************************************************************
     19  *                                                                         *
     20  *                 Project Name : Westwood Library                         *
     21  *                                                                         *
     22  *                    File Name : IFF.C                                    *
     23  *                                                                         *
     24  *                   Programmer : Joe L. Bostic                            *
     25  *                                                                         *
     26  *                   Start Date : May 16, 1991                             *
     27  *                                                                         *
     28  *                  Last Update : April 19, 1994   [SKB]                   *
     29  *                                                                         *
     30  *                                                                         *
     31  * IFF reader code designed for loading pictures (ILBM or PBM).            *
     32  *                                                                         *
     33  *-------------------------------------------------------------------------*
     34  * Functions:                                                              *
     35  *   Close_Iff_File -- Closes an IFF file handle.                          *
     36  *   Get_Iff_Chunk_Size -- Get the size of the given IFF chunk.            *
     37  *   Open_Iff_File -- Opens an IFF file for reading.                       *
     38  *   Read_Iff_Chunk -- Reads a chunk from an IFF file.                     *
     39  *   Write_Iff_Chunk -- Writes an IFF chuck out.                           *
     40  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     41 
     42 #include "iff.h"
     43 #include "file.h"
     44 
     45 #define ID_FORM			MAKE_ID('F','O','R','M')
     46 
     47 #ifdef MIN
     48 #undef MIN
     49 #endif
     50 
     51 /***************************************************************************
     52  * OPEN_IFF_FILE -- Opens an IFF file for reading.                         *
     53  *                                                                         *
     54  *    This function will open an IFF file for reading.  It will perform    *
     55  *    a the simple validity test of checking the first four bytes to make  *
     56  *    sure they are "FORM".  The value returned is the filehandle of the   *
     57  *    opened file.                                                         *
     58  *                                                                         *
     59  * INPUT:   filename - ASCII name of the IFF file to be opened.            *
     60  *                                                                         *
     61  * OUTPUT:  Returns the filehandle.  If there is an error or the file      *
     62  *          is not an IFF FORM then -1 will be returned.                   *
     63  *                                                                         *
     64  * WARNINGS:   You are responsible for error handling if this function     *
     65  *             returns -1 (not an IFF file).                               *
     66  *                                                                         *
     67  * HISTORY:                                                                *
     68  *   05/16/1991 JLB : Created.                                             *
     69  *   04/19/1994 SKB : Update to 32 bit library.                            *
     70  *=========================================================================*/
     71 int __cdecl Open_Iff_File(char const *filename)
     72 {
     73 	int	fh;		// File handle.
     74 	long	type;		// IFF file type.
     75 
     76 
     77 	/* We want to be able to open the file for READ | WRITE, but we do not
     78 	   want the Open_File to create it.  So check to see if it exists before
     79 		the Open_File */
     80 
     81 //	fh = Open_File(filename, READ);		// Open the source file for READ
     82 //	Close_File(fh);
     83 
     84 	//fh = Open_File(filename, READ | WRITE);	// Open the source file again
     85 	fh = Open_File(filename, READ);	// Open the source file again
     86 
     87 	//	Validate that it is a FORM type.
     88 
     89 	Read_File(fh, &type, 4L);
     90 
     91 	if (type == ID_FORM) {
     92 
     93 		//	The file is valid (so far).  Position the read so that the actual
     94 		//	IFF file type code can be read.
     95 
     96 		Seek_File(fh, 4L, SEEK_CUR);		// Skip the filesize bytes.
     97 
     98 	} else {
     99 
    100 		// This is NOT an IFF file.  Close the source file and return with
    101 		//	the error code.
    102 		Close_File(fh);
    103 		fh = WW_ERROR;
    104 	}
    105 	return fh;
    106 }
    107 
    108 
    109 /***************************************************************************
    110  * CLOSE_IFF_FILE -- Closes an IFF file handle.                            *
    111  *                                                                         *
    112  *    The routine will close the file that was opened with the             *
    113  *    Open_Iff_File() function.                                            *
    114  *                                                                         *
    115  * INPUT:   fh - File handle that was returned from Open_Iff_File().       *
    116  *                                                                         *
    117  * OUTPUT:  none                                                           *
    118  *                                                                         *
    119  * WARNINGS:   none                                                        *
    120  *                                                                         *
    121  * HISTORY:                                                                *
    122  *   05/16/1991 JLB : Created.                                             *
    123  *   04/19/1994 SKB : Update to 32 bit library.                            *
    124  *=========================================================================*/
    125 void __cdecl Close_Iff_File(int fh)
    126 {
    127 	if (fh != WW_ERROR) Close_File(fh);
    128 }
    129 
    130 
    131 /***************************************************************************
    132  * GET_IFF_CHUNK_SIZE -- Get the size of the given IFF chunk.              *
    133  *                                                                         *
    134  * INPUT:      int file handle to open IFF file, long id to get size of   *
    135  *                                                                         *
    136  * OUTPUT:     long size of the chunk or 0L if it was not found            *
    137  *                                                                         *
    138  * WARNINGS:   none                                                        *
    139  *                                                                         *
    140  * HISTORY:                                                                *
    141  *   06/03/1991  CY : Created.                                             *
    142  *   04/19/1994 SKB : Update to 32 bit library.                            *
    143  *=========================================================================*/
    144 unsigned long __cdecl Get_Iff_Chunk_Size(int fh, long id)
    145 {
    146 	long	form;					// Chunk iff form name.
    147 	long	chunksize;			// Size of the chunk.
    148 	char	first_iteration;	// Check once the current chunk name
    149 
    150 
    151 	first_iteration = TRUE;
    152 
    153 	for (;;) {
    154 		if (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;
    155 
    156 
    157 		if (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;
    158 
    159 #if(IBM)
    160 		chunksize = Reverse_Long(chunksize);
    161 #endif
    162 
    163 		if (id == form) {
    164 			Seek_File(fh, -8L, SEEK_CUR);			// Seek back to the start of
    165 			return(chunksize);						// the chunk & return size
    166 		} else {
    167 
    168 			if (first_iteration) {
    169 				Seek_File(fh, 12L, SEEK_SET);		// Start at beginning of file.
    170 				first_iteration = FALSE;			// Don't do this again
    171 			} else {
    172 
    173 				/* Otherwise, go to the next chunk in the file */
    174 
    175 				chunksize = (chunksize + 1) & 0xFFFFFFFEL;
    176 				Seek_File(fh, chunksize, SEEK_CUR);
    177 			}
    178 		}
    179 	}
    180 
    181 	return(0L);
    182 }
    183 
    184 
    185 /***************************************************************************
    186  * READ_IFF_CHUNK -- Reads a chunk from an IFF file.                       *
    187  *                                                                         *
    188  *    Once an IFF file is opened, various chunks must be read from it.     *
    189  *    This routine will search through the IFF file and load in the        *
    190  *    specified chunk.  It will scan through the entire file when          *
    191  *    searching for the chunk.  It will load the FIRST chunk of the given  *
    192  *    type.                                                                *
    193  *                                                                         *
    194  * INPUT:   fh       - File handle of IFF file.                            *
    195  *                                                                         *
    196  *          id       - Chunk ID code.                                      *
    197  *                                                                         *
    198  *          buffer   - Pointer to buffer to load the chunk.                *
    199  *                                                                         *
    200  *          maxsize  - Maximum data bytes to read.                         *
    201  *                                                                         *
    202  * OUTPUT:     Returns with the number of bytes read from the chunk.       *
    203  *             If 0 is returned, this indicates that the chunk wasn't      *
    204  *             found.                                                      *
    205  *                                                                         *
    206  * WARNINGS:   none                                                        *
    207  *                                                                         *
    208  * HISTORY:                                                                *
    209  *   05/16/1991 JLB : Created.                                             *
    210  *   04/19/1994 SKB : Update to 32 bit library.                            *
    211  *=========================================================================*/
    212 unsigned long __cdecl Read_Iff_Chunk(int fh, long id, void *buffer, unsigned long maxsize)
    213 {
    214 	long	form;					// Chunk iff form name.
    215 	unsigned long	chunksize;			// Size of the chunk.
    216 	char	first_iteration;	// Check once the current chunk name
    217 
    218 	first_iteration = TRUE;
    219 
    220 	for (;;) {
    221 		if (Read_File(fh, &form, 4L) != 4L && !first_iteration) break;
    222 
    223 		if (Read_File(fh, (char *) &chunksize, 4L) != 4L && !first_iteration) break;
    224 
    225 #if(IBM)
    226 		chunksize = Reverse_Long(chunksize);
    227 #endif
    228 
    229 		if (id == form) {
    230 
    231 			maxsize = MIN(maxsize, chunksize);
    232 			Read_File(fh, buffer, maxsize);		// Read the buffer.
    233 
    234 			chunksize = (chunksize + 1) & 0xFFFFFFFEL;
    235 			if (maxsize < chunksize) {
    236 				Seek_File(fh, chunksize - maxsize, SEEK_CUR);
    237 			}
    238 			return(maxsize);
    239 		} else {
    240 
    241 			if (first_iteration) {
    242 				Seek_File(fh, 12L, SEEK_SET);		// Start at beginning of file.
    243 				first_iteration = FALSE;			// Don't do this again
    244 
    245 			} else {
    246 
    247 				/* Otherwise, go to the next chunk in the file */
    248 
    249 				chunksize = (chunksize + 1) & 0xFFFFFFFEL;
    250 				Seek_File(fh, chunksize, SEEK_CUR);
    251 			}
    252 		}
    253 	}
    254 
    255 	return(0L);
    256 }
    257 
    258 
    259 
    260 /***************************************************************************
    261  * WRITE_IFF_CHUNK -- Writes an IFF chuck out.                             *
    262  *                                                                         *
    263  * INPUT:                                                                  *
    264  *                                                                         *
    265  * OUTPUT:                                                                 *
    266  *                                                                         *
    267  * WARNINGS:                                                               *
    268  *                                                                         *
    269  * HISTORY:                                                                *
    270  *   04/19/1994 SKB : Created.                                             *
    271  *=========================================================================*/
    272 void __cdecl Write_Iff_Chunk(int file, long id, void *buffer, long length)
    273 {
    274 	long	pos;		// Current position in the IFF file.
    275 	long	oldpos;	// Record of start of chunk offset.
    276 	long	endpos;	// end of file offset before we write our data
    277 	long	value;
    278 	BOOL	odd;		// Is length odd?
    279 	char	pad = 0;	// Optional padding byte for even sized chunks.
    280 
    281 	/*
    282 	** Get the current end of file (before we write more data to the file)
    283 	*/
    284 	pos 	 = Seek_File (file, 0L, SEEK_CUR);
    285 	endpos = Seek_File (file, 0L, SEEK_END);
    286 	Seek_File (file, pos, SEEK_SET);
    287 
    288 	if (length) {
    289 		value = id;
    290 		odd = (short)length & 0x01;
    291 
    292 		Write_File(file, &value, 4L);
    293 		oldpos = Seek_File(file, 0L, SEEK_CUR);
    294 		Write_File(file, &value, 4L);
    295 		Write_File(file, buffer, length);
    296 		pos = Seek_File(file, 0L, SEEK_CUR);
    297 		if (odd) {
    298 			Write_File(file, &pad, 1L);
    299 		}
    300 
    301 		/*
    302 		**	Update the chunk size long.
    303 		*/
    304 		Seek_File(file, oldpos, SEEK_SET);
    305 		value = IFFize_LONG((pos - oldpos)-4);
    306 		Write_File(file, &value, 4L);
    307 
    308 		/*
    309 		**	Update the file size LONG. if we are not just overwriting existing data
    310 		*/
    311 		// (MCC)
    312 		if ( endpos < pos ) {
    313 			Seek_File(file, 4L, SEEK_SET);
    314 			value = IFFize_LONG((pos+odd) - 8);
    315 			Write_File(file, &value, 4L);
    316 		}
    317 
    318 		/*
    319 		**	Return to end of file.
    320 		*/
    321 		Seek_File(file, 0L, SEEK_END);
    322 	}
    323 }
    324 
    325