mirror of
https://github.com/electronicarts/CnC_Red_Alert.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
250
WINVQ/VQM32/MIXFILE.CPP
Normal file
250
WINVQ/VQM32/MIXFILE.CPP
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
** 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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user