| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** 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 3 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, see <http://www.gnu.org/licenses/>.
- */
- /****************************************************************************
- *
- * C O N F I D E N T I A L -- W E S T W O O D S T U D I O S
- *
- *----------------------------------------------------------------------------
- *
- * FILE
- * mixfile.c
- *
- * DESCRIPTION
- * A mix file is basically a group of files concatinated together
- * proceeded by a header describing where in the file each individual
- * entry is located. These routines are provided to simplify the access
- * to these file entries.
- *
- * PROGRAMMER
- * Denzil E. Long, Jr.
- *
- * DATE
- * January 26, 1995
- *
- *----------------------------------------------------------------------------
- *
- * MixFile format:
- *
- * HEADER
- * (2 bytes) Count - The number of entries in this file.
- * (4 bytes) Size - Size of the mix file in bytes.
- *
- * SUBBLOCKS (There are "Count" number of these.)
- * (4 bytes) CRC - Entry descriptor (CRC of filename).
- * (4 bytes) Offset - Offset in bytes from beginning of the DATA chunk.
- * (4 bytes) Size - Size of entry.
- *
- * DATA
- * Entry data.
- *
- *----------------------------------------------------------------------------
- *
- * PUBLIC
- * OpenMix - Open mix file for access.
- * CloseMix - Close a mix file.
- * OpenMixEntry - Open a mix file entry.
- *
- ****************************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <fcntl.h>
- #include <io.h>
- #include <mem.h>
- #include <string.h>
- #include "mixfile.h"
- #include "crc.h"
- /*---------------------------------------------------------------------------
- * PRIVATE DECLARATIONS
- *-------------------------------------------------------------------------*/
- int compfunc(void const *ptr1, void const *ptr2);
- /****************************************************************************
- *
- * NAME
- * OpenMix - Open mix file for access.
- *
- * SYNOPSIS
- * MixHandle = OpenMix(Name)
- *
- * MixHandle *OpenMix(char *);
- *
- * FUNCTION
- * Open a mix file for access.
- *
- * INPUTS
- * Name - Pointer to name of mix file to open.
- *
- * RESULT
- * MixHandle - Pointer to handle for mix file.
- *
- ****************************************************************************/
- MIXHandle *OpenMix(char *name)
- {
- MIXHeader mfhdr;
- MIXHandle *mix = NULL;
- long fh;
- long sbsize;
- long size;
- /* Open mix file and read in header. */
- if ((fh = open(name, (O_RDONLY|O_BINARY))) != -1) {
- if (read(fh, &mfhdr, sizeof(MIXHeader)) == sizeof(MIXHeader)) {
- /* Allocate handle based on the number of SubBlocks. */
- sbsize = (mfhdr.Count * sizeof(MIXSubBlock));
- size = sbsize + sizeof(MIXHandle);
- if ((mix = (MIXHandle *)malloc(size)) != NULL) {
- memset(mix, 0, size);
- mix->Name = name;
- mix->Size = mfhdr.Size;
- mix->Count = mfhdr.Count;
- /* Read in the SubBlock entries. */
- if (read(fh, &mix->Entries[0], sbsize) != sbsize) {
- free(mix);
- mix = NULL;
- }
- }
- }
- close(fh);
- }
- return (mix);
- }
- /****************************************************************************
- *
- * NAME
- * CloseMix - Close a mix file.
- *
- * SYNOPSIS
- * CloseMix(MixHandle)
- *
- * void CloseMix(MixHandle *);
- *
- * FUNCTION
- * Close a mix file by freeing its handle.
- *
- * INPUTS
- * MixHandle - Pointer to MixHandle returned by OpenMix().
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void CloseMix(MIXHandle *mix)
- {
- free(mix);
- }
- /****************************************************************************
- *
- * NAME
- * OpenMixEntry - Open a mix file entry.
- *
- * SYNOPSIS
- * FH = OpenMixEntry(MixHandle, EntryName)
- *
- * short OpenMixEntry(MIXHandle *, char *);
- *
- * FUNCTION
- * Opens an entry from the specified mix file handle. Use close() to close
- * the file when done.
- *
- * INPUTS
- * MixHandle - Pointer to MIXHandle containing entry to open.
- * EntryName - Pointer to name of mix file entry to open.
- *
- * RESULT
- * FH - DOS filehandle, -1 if unable to open.
- *
- ****************************************************************************/
- long OpenMixEntry(MIXHandle *mix, char *name)
- {
- MIXSubBlock key;
- MIXSubBlock *block;
- long fh;
- /* Search for the specified file in the mix file. */
- key.CRC = Calculate_CRC(name, strlen(name));
- block = (MIXSubBlock *)bsearch(&key, &mix->Entries[0], mix->Count,
- sizeof(MIXSubBlock), compfunc);
- /* If the block exists for the requested filename. */
- if (block != NULL) {
- /* Initialize the key for file access. */
- key.Offset = block->Offset;
- key.Offset += (mix->Count * sizeof(MIXSubBlock)) + sizeof(MIXHeader);
- /* Open the mix file. */
- if ((fh = open(mix->Name, (O_RDONLY|O_BINARY))) != -1) {
- /* Seek to the start of the file. */
- if (lseek(fh, key.Offset, SEEK_SET) == -1) {
- close(fh);
- fh = -1;
- }
- }
- }
- return (fh);
- }
- /****************************************************************************
- *
- * NAME
- * compfunc - Compare function for bsearch().
- *
- * SYNOPSIS
- * Result = compfunc(Entry1, Entry2);
- *
- * int compfunc(void const *, void const *);
- *
- * FUNCTION
- *
- * INPUTS
- * Entry1 - Pointer to first entry to compare.
- * Entry2 - Pointer to second entry to compare.
- *
- * RESULT
- * Result -
- *
- ****************************************************************************/
- int compfunc(void const *ptr1, void const *ptr2)
- {
- if (((MIXSubBlock *)ptr1)->CRC < ((MIXSubBlock *)ptr2)->CRC) return -1;
- if (((MIXSubBlock *)ptr1)->CRC > ((MIXSubBlock *)ptr2)->CRC) return 1;
- return(0);
- }
|